summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2016-08-09 02:25:36 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2016-08-09 02:25:36 +0000
commit76093549a56e2aed50d99915a84892f888cd1f34 (patch)
treefa1a6ae232f0e554f7455d1735e790f5d9673b4a
parentdf5c50b4de6fe61587aa6f1b73b69f8c84454cea (diff)
When interrupted, connect() should leave the socket connecting in the
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@
-rw-r--r--regress/lib/libpthread/restart/connect/connect.c7
-rw-r--r--sys/kern/uipc_syscalls.c14
2 files changed, 14 insertions, 7 deletions
diff --git a/regress/lib/libpthread/restart/connect/connect.c b/regress/lib/libpthread/restart/connect/connect.c
index dfa62040a47..e1ef9ac2830 100644
--- a/regress/lib/libpthread/restart/connect/connect.c
+++ b/regress/lib/libpthread/restart/connect/connect.c
@@ -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
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index b00760dd939..a2505fe851b 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -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);