Index: ossp-pkg/sa/ChangeLog RCS File: /v/ossp/cvs/ossp-pkg/sa/ChangeLog,v rcsdiff -q -kk '-r1.33' '-r1.34' -u '/v/ossp/cvs/ossp-pkg/sa/ChangeLog,v' 2>/dev/null --- ChangeLog 2004/04/02 18:21:07 1.33 +++ ChangeLog 2004/04/02 18:47:39 1.34 @@ -13,6 +13,15 @@ Changes between 1.1.0 and 1.2.0 (10-Nov-2003 to xx-Apr-2004) + o In sa_connect() also select(2) on the socket if EINTR was + returned similar to what is done already for EINPROGRESS, because + one is not allowed to re-start connect(2) according to STEVENS + (Unix Network Programming, volume 1, section 5.9) but instead have + to perform the same post-processing under EINTR (under both timeout + and non-timeout situations) what we already did for EINPROGRESS (in + timeout-aware situation). + [Ralf S. Engelschall] + o Adjusted all copyright messages for new year 2004. [Ralf S. Engelschall] Index: ossp-pkg/sa/sa.c RCS File: /v/ossp/cvs/ossp-pkg/sa/sa.c,v rcsdiff -q -kk '-r1.80' '-r1.81' -u '/v/ossp/cvs/ossp-pkg/sa/sa.c,v' 2>/dev/null --- sa.c 2004/04/02 18:21:07 1.80 +++ sa.c 2004/04/02 18:47:39 1.81 @@ -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,75 @@ 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) { 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: + /* 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; + } - /* reset socket flags */ + /* 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); }