Interrupted connect(2) and errno issue

Yar Tikhiy yar at freebsd.org
Tue Jul 15 09:00:35 PDT 2003


Hi folks,

Background:
A blocking connect(2) call will be interrupted by any delivered
signal, returning EINTR.  Despites the call interrupted, the
connection establishment will be carried out asynchronously, as
though the socket were in non-blocking mode.

The issue:
Further calls to connect(2) on such a socket will return EADDRINUSE,
while those on a non-blocking socket with connecting in progress
will return EALREADY.  Is there a reason for this difference?  If
there isn't, what do you think of the attached patch?  I believe
it will improve our conformance to POSIX.

BTW, this patch could have been cleaner and not involved a new flag
variable if we were able to drop the splx() stuff, which is anyway
a no-op in CURRENT AFAIK.

-- 
Yar

--- uipc_syscalls.c.orig	Thu Jun 19 07:55:01 2003
+++ uipc_syscalls.c	Tue Jul 15 17:03:25 2003
@@ -480,11 +480,12 @@
 {
 	struct socket *so;
 	int error, s;
+	int interrupted = 0;
 
 	mtx_lock(&Giant);
 	if ((error = fgetsock(td, fd, &so, NULL)) != 0)
 		goto done2;
-	if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
+	if (so->so_state & SS_ISCONNECTING) {
 		error = EALREADY;
 		goto done1;
 	}
@@ -503,6 +504,8 @@
 	s = splnet();
 	while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
 		error = tsleep(&so->so_timeo, PSOCK | PCATCH, "connec", 0);
+		if (error == EINTR || error == ERESTART)
+			interrupted = 1;
 		if (error)
 			break;
 	}
@@ -512,7 +515,8 @@
 	}
 	splx(s);
 bad:
-	so->so_state &= ~SS_ISCONNECTING;
+	if (!interrupted)
+		so->so_state &= ~SS_ISCONNECTING;
 	if (error == ERESTART)
 		error = EINTR;
 done1:
%%%


More information about the freebsd-arch mailing list