When interrupted, connect() should leave the socket connecting in the
authorguenther <guenther@openbsd.org>
Tue, 9 Aug 2016 02:25:35 +0000 (02:25 +0000)
committerguenther <guenther@openbsd.org>
Tue, 9 Aug 2016 02:25:35 +0000 (02:25 +0000)
background, similar to a non-blocking socket.  Return EALREADY whenever
already connecting, not just for non-blocking sockets.  Fix from {Free,Net}BSD

Prompted by a report from Michael Reed (m.reed (at) mykolab.com)
ok millert@

regress/lib/libpthread/restart/connect/connect.c
sys/kern/uipc_syscalls.c

index dfa6204..e1ef9ac 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: connect.c,v 1.1 2011/09/18 16:36:58 fgsch Exp $       */
+/*     $OpenBSD: connect.c,v 1.2 2016/08/09 02:25:35 guenther Exp $    */
 /*
  * Federico G. Schwindt <fgsch@openbsd.org>, 2011. Public Domain.
  */
@@ -30,7 +30,10 @@ thr_connect(void *arg)
        sa.sin_port = htons(23);
        sa.sin_addr.s_addr = htonl(0xc7b98903); /* cvs.openbsd.org */
        ASSERT(connect(s, (struct sockaddr *)&sa, sizeof(sa)) == -1);
-       return ((caddr_t)NULL + errno);
+       int err = errno;
+       ASSERT(connect(s, (struct sockaddr *)&sa, sizeof(sa)) == -1);
+       ASSERT(errno == EALREADY);
+       return ((caddr_t)NULL + err);
 }
 
 int
index b00760d..a2505fe 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: uipc_syscalls.c,v 1.132 2016/05/18 01:13:13 millert Exp $     */
+/*     $OpenBSD: uipc_syscalls.c,v 1.133 2016/08/09 02:25:35 guenther Exp $    */
 /*     $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $      */
 
 /*
@@ -367,12 +367,12 @@ sys_connect(struct proc *p, void *v, register_t *retval)
        struct file *fp;
        struct socket *so;
        struct mbuf *nam = NULL;
-       int error, s;
+       int error, s, interrupted = 0;
 
        if ((error = getsock(p, SCARG(uap, s), &fp)) != 0)
                return (error);
        so = fp->f_data;
-       if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
+       if (so->so_state & SS_ISCONNECTING) {
                FRELE(fp, p);
                return (EALREADY);
        }
@@ -409,8 +409,11 @@ sys_connect(struct proc *p, void *v, register_t *retval)
        s = splsoftnet();
        while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
                error = tsleep(&so->so_timeo, PSOCK | PCATCH, "netcon2", 0);
-               if (error)
+               if (error) {
+                       if (error == EINTR || error == ERESTART)
+                               interrupted = 1;
                        break;
+               }
        }
        if (error == 0) {
                error = so->so_error;
@@ -418,7 +421,8 @@ sys_connect(struct proc *p, void *v, register_t *retval)
        }
        splx(s);
 bad:
-       so->so_state &= ~SS_ISCONNECTING;
+       if (!interrupted)
+               so->so_state &= ~SS_ISCONNECTING;
        FRELE(fp, p);
        if (nam)
                m_freem(nam);