OSSP CVS Repository

ossp - Difference in ossp-pkg/l2/l2_ut_sa.c versions 1.24 and 1.25
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [History

ossp-pkg/l2/l2_ut_sa.c 1.24 -> 1.25

--- l2_ut_sa.c   2004/04/02 12:27:32     1.24
+++ l2_ut_sa.c   2004/04/21 12:02:12     1.25
@@ -1,8 +1,8 @@
 /*
 **  OSSP sa - Socket Abstraction
-**  Copyright (c) 2001-2003 Ralf S. Engelschall <rse@engelschall.com>
-**  Copyright (c) 2001-2003 The OSSP Project <http://www.ossp.org/>
-**  Copyright (c) 2001-2003 Cable & Wireless Deutschland <http://www.cw.com/de/>
+**  Copyright (c) 2001-2004 Ralf S. Engelschall <rse@engelschall.com>
+**  Copyright (c) 2001-2004 The OSSP Project <http://www.ossp.org/>
+**  Copyright (c) 2001-2004 Cable & Wireless <http://www.cw.com/>
 **
 **  This file is part of OSSP sa, a socket abstraction library which
 **  can be found at http://www.ossp.org/pkg/lib/sa/.
@@ -1452,6 +1452,7 @@
     fd_set rset, wset;
     socklen_t len;
     sa_rc_t rv;
+    struct timeval *tv;
 
     /* argument sanity check(s) */
     if (sa == NULL || raddr == NULL)
@@ -1466,72 +1467,88 @@
         if ((rv = sa_socket_init(sa, raddr->nFamily)) != SA_OK)
             return SA_RC(rv);
 
+    /* prepare return code decision */
     rv = SA_OK;
-    if (SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_CONNECT])) {
-        /* standard/non-timeout-aware connect operation */
-        if (SA_SC_CALL_3(sa, connect, sa->fdSocket, raddr->saBuf, raddr->slBuf) < 0)
-            rv = SA_ERR_SYS;
-    }
-    else {
-        /* emulated/timeout-aware connect operation */
-        error = 0;
+    error = 0;
 
-        /* temporarily switch underlying socket to non-blocking mode */
+    /* temporarily switch underlying socket to non-blocking mode
+       (necessary under timeout-aware operation only) */
+    flags = 0;
+    if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_CONNECT])) {
         flags = fcntl(sa->fdSocket, F_GETFL, 0);
         (void)fcntl(sa->fdSocket, F_SETFL, flags|O_NONBLOCK);
+    }
 
-        /* perform the connect operation */
-        if ((n = SA_SC_CALL_3(sa, connect, sa->fdSocket, raddr->saBuf, raddr->slBuf)) < 0) {
-            if (errno != EINPROGRESS) {
-                error = errno;
-                goto done;
-            }
-        }
-
-        /* ok if connect completed immediately */
-        if (n == 0)
-            goto done;
-
-        /* wait for read or write possibility */
-        FD_ZERO(&rset);
-        FD_ZERO(&wset);
-        FD_SET(sa->fdSocket, &rset);
-        FD_SET(sa->fdSocket, &wset);
-        do {
-            n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &rset, &wset, NULL,
-                             &sa->tvTimeout[SA_TIMEOUT_CONNECT]);
-        } while (n == -1 && errno == EINTR);
-
-        /* decide on return semantic */
-        if (n < 0) {
+    /* perform the connect operation */
+    if ((n = SA_SC_CALL_3(sa, connect, sa->fdSocket, raddr->saBuf, raddr->slBuf)) < 0) {
+        if (errno != EINTR && errno != EINPROGRESS) {
+            /* we have to perform the following post-processing under
+               EINPROGRESS anway, but actually also for EINTR according
+               to Unix Network Programming, volume 1, section 5.9, W.
+               Richard Stevens: "What we are doing [] is restarting
+               the interrupted system call ourself. This is fine for
+               accept, along with the functions such as read, write,
+               select and open. But there is one function that we cannot
+               restart ourself: connect. If this function returns EINTR,
+               we cannot call it again, as doing so will return an
+               immediate error. When connect is interrupted by a caught
+               signal and is not automatically restarted, we must call
+               select to wait for the connection to complete, as we
+               describe in section 15.3." */
             error = errno;
             goto done;
         }
-        else if (n == 0) {
-            (void)close(sa->fdSocket); /* stop TCP three-way handshake */
-            sa->fdSocket = -1;
-            rv = SA_ERR_TMT;
-            goto done;
-        }
-
-        /* fetch pending error */
-        len = (socklen_t)sizeof(error);
-        if (getsockopt(sa->fdSocket, SOL_SOCKET, SO_ERROR, (void *)&error, &len) < 0)
-            error = errno;
-
-        done:
+    }
 
-        /* reset socket flags */
+    /* ok if connect completed immediately */
+    if (n == 0)
+        goto done;
+
+    /* wait for read or write possibility */
+    FD_ZERO(&rset);
+    FD_ZERO(&wset);
+    FD_SET(sa->fdSocket, &rset);
+    FD_SET(sa->fdSocket, &wset);
+    if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_CONNECT]))
+        tv = &sa->tvTimeout[SA_TIMEOUT_CONNECT];
+    else
+        tv = NULL;
+    do {
+        n = SA_SC_CALL_5(sa, select, sa->fdSocket+1, &rset, &wset, NULL, tv);
+    } while (n == -1 && errno == EINTR);
+
+    /* decide on return semantic */
+    if (n < 0) {
+        error = errno;
+        goto done;
+    }
+    else if (n == 0) {
+        (void)close(sa->fdSocket); /* stop TCP three-way handshake */
+        sa->fdSocket = -1;
+        rv = SA_ERR_TMT;
+        goto done;
+    }
+
+    /* fetch pending error */
+    len = (socklen_t)sizeof(error);
+    if (getsockopt(sa->fdSocket, SOL_SOCKET, SO_ERROR, (void *)&error, &len) < 0)
+        error = errno;
+
+    done:
+
+    /* reset socket flags
+       (necessary under timeout-aware operation only) */
+    if (!SA_TVISZERO(sa->tvTimeout[SA_TIMEOUT_CONNECT]))
         (void)fcntl(sa->fdSocket, F_SETFL, flags);
 
-        /* optionally set errno */
-        if (error != 0) {
-            (void)close(sa->fdSocket); /* just in case */
-            sa->fdSocket = -1;
-            errno = error;
-            rv = SA_ERR_SYS;
-        }
+    /* optionally set errno */
+    if (error != 0) {
+        (void)close(sa->fdSocket); /* just in case */
+        sa->fdSocket = -1;
+        errno = error;
+        rv = SA_ERR_SYS;
     }
+
     return SA_RC(rv);
 }
 

CVSTrac 2.0.1