summaryrefslogtreecommitdiffstats
path: root/unix
diff options
context:
space:
mode:
authorjenglish <jenglish@flightlab.com>2008-08-05 23:47:11 (GMT)
committerjenglish <jenglish@flightlab.com>2008-08-05 23:47:11 (GMT)
commitc290f50d94d557eda1ec276f0fd53e0879d281e8 (patch)
treedcf41166c3fae19596215e8942953d08da8c6270 /unix
parent1f1a20cf5974c8067fbc369f2205c8ef06c1d1cb (diff)
downloadtcl-c290f50d94d557eda1ec276f0fd53e0879d281e8.zip
tcl-c290f50d94d557eda1ec276f0fd53e0879d281e8.tar.gz
tcl-c290f50d94d557eda1ec276f0fd53e0879d281e8.tar.bz2
Streamline async connect logic [Patch 1994512].
Consolidate error reporting paths in CreateSocket(); Restore blocking mode immediately after connect() FD blocking mode is now consistent with [fconfigure ... -blocking] setting while async connect is in progress.
Diffstat (limited to 'unix')
-rw-r--r--unix/tclUnixChan.c108
1 files changed, 40 insertions, 68 deletions
diff --git a/unix/tclUnixChan.c b/unix/tclUnixChan.c
index 629f9d0..3e99c14 100644
--- a/unix/tclUnixChan.c
+++ b/unix/tclUnixChan.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclUnixChan.c,v 1.93 2008/03/03 14:54:43 rmax Exp $
+ * RCS: @(#) $Id: tclUnixChan.c,v 1.94 2008/08/05 23:47:12 jenglish Exp $
*/
#include "tclInt.h" /* Internal definitions for Tcl. */
@@ -1828,14 +1828,13 @@ TcpBlockModeProc(
*
* WaitForConnect --
*
- * Waits for a connection on an asynchronously opened socket to be
- * completed.
+ * Wait for a connection on an asynchronously opened socket to be
+ * completed. In nonblocking mode, just test if the connection
+ * has completed without blocking.
*
* Results:
- * None.
- *
- * Side effects:
- * The socket is connected after this function returns.
+ * 0 if the connection has completed, -1 if still in progress
+ * or there is an error.
*
*----------------------------------------------------------------------
*/
@@ -1862,9 +1861,6 @@ WaitForConnect(
errno = 0;
state = TclUnixWaitForFile(statePtr->fd,
TCL_WRITABLE | TCL_EXCEPTION, timeOut);
- if (!(statePtr->flags & TCP_ASYNC_SOCKET)) {
- (void) TclUnixSetBlockingMode(statePtr->fd, TCL_MODE_BLOCKING);
- }
if (state & TCL_EXCEPTION) {
return -1;
}
@@ -1910,11 +1906,10 @@ TcpInputProc(
int *errorCodePtr) /* Where to store error code. */
{
TcpState *statePtr = (TcpState *) instanceData;
- int bytesRead, state;
+ int bytesRead;
*errorCodePtr = 0;
- state = WaitForConnect(statePtr, errorCodePtr);
- if (state != 0) {
+ if (WaitForConnect(statePtr, errorCodePtr) != 0) {
return -1;
}
bytesRead = recv(statePtr->fd, buf, (size_t) bufSize, 0);
@@ -1962,11 +1957,9 @@ TcpOutputProc(
{
TcpState *statePtr = (TcpState *) instanceData;
int written;
- int state; /* Of waiting for connection. */
*errorCodePtr = 0;
- state = WaitForConnect(statePtr, errorCodePtr);
- if (state != 0) {
+ if (WaitForConnect(statePtr, errorCodePtr) != 0) {
return -1;
}
written = send(statePtr->fd, buf, (size_t) toWrite, 0);
@@ -2279,25 +2272,23 @@ CreateSocket(
* attempt to do an async connect. Otherwise
* do a synchronous connect or bind. */
{
- int status, sock, asyncConnect, curState, origState;
+ int status = 0, sock = -1;
struct sockaddr_in sockaddr; /* socket address */
struct sockaddr_in mysockaddr; /* Socket address for client */
TcpState *statePtr;
const char *errorMsg = NULL;
- sock = -1;
- origState = 0;
if (!CreateSocketAddress(&sockaddr, host, port, 0, &errorMsg)) {
- goto addressError;
+ goto error;
}
if ((myaddr != NULL || myport != 0) &&
!CreateSocketAddress(&mysockaddr, myaddr, myport, 1, &errorMsg)) {
- goto addressError;
+ goto error;
}
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
- goto addressError;
+ goto error;
}
/*
@@ -2313,7 +2304,6 @@ CreateSocket(
TclSockMinimumBuffers(sock, SOCKET_BUFSIZE);
- asyncConnect = 0;
status = 0;
if (server) {
/*
@@ -2321,9 +2311,9 @@ CreateSocket(
* specified port.
*/
- status = 1;
- (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &status,
- sizeof(status));
+ int reuseaddr = 1;
+ (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+ (char *) &reuseaddr, sizeof(reuseaddr));
status = bind(sock, (struct sockaddr *) &sockaddr,
sizeof(struct sockaddr));
if (status != -1) {
@@ -2331,13 +2321,13 @@ CreateSocket(
}
} else {
if (myaddr != NULL || myport != 0) {
- curState = 1;
+ int reuseaddr = 1;
(void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
- (char *) &curState, sizeof(curState));
+ (char *) &reuseaddr, sizeof(reuseaddr));
status = bind(sock, (struct sockaddr *) &mysockaddr,
sizeof(struct sockaddr));
if (status < 0) {
- goto bindError;
+ goto error;
}
}
@@ -2350,38 +2340,36 @@ CreateSocket(
if (async) {
status = TclUnixSetBlockingMode(sock, TCL_MODE_NONBLOCKING);
- } else {
- status = 0;
- }
- if (status > -1) {
- status = connect(sock, (struct sockaddr *) &sockaddr,
- sizeof(sockaddr));
if (status < 0) {
- if (errno == EINPROGRESS) {
- asyncConnect = 1;
- status = 0;
- }
+ goto error;
+ }
+ }
+
+ status = connect(sock, (struct sockaddr *) &sockaddr,
+ sizeof(sockaddr));
+ if (status < 0) {
+ if (errno == EINPROGRESS) {
+ status = 0;
} else {
- /*
- * Here we are if the connect succeeds. In case of an
- * asynchronous connect we have to reset the channel to
- * blocking mode. This appears to happen not very often, but
- * e.g. on a HP 9000/800 under HP-UX B.11.00 we enter this
- * stage. [Bug: 4388]
- */
-
- if (async) {
- status = TclUnixSetBlockingMode(sock, TCL_MODE_BLOCKING);
- }
+ goto error;
}
+ }
+ if (async) {
+ /*
+ * Restore blocking mode.
+ */
+ status = TclUnixSetBlockingMode(sock, TCL_MODE_BLOCKING);
}
}
- bindError:
if (status < 0) {
+error:
if (interp != NULL) {
Tcl_AppendResult(interp, "couldn't open socket: ",
Tcl_PosixError(interp), NULL);
+ if (errorMsg != NULL) {
+ Tcl_AppendResult(interp, " (", errorMsg, ")", NULL);
+ }
}
if (sock != -1) {
close(sock);
@@ -2394,26 +2382,10 @@ CreateSocket(
*/
statePtr = (TcpState *) ckalloc((unsigned) sizeof(TcpState));
- statePtr->flags = 0;
- if (asyncConnect) {
- statePtr->flags = TCP_ASYNC_CONNECT;
- }
+ statePtr->flags = async ? TCP_ASYNC_CONNECT : 0;
statePtr->fd = sock;
return statePtr;
-
- addressError:
- if (sock != -1) {
- close(sock);
- }
- if (interp != NULL) {
- Tcl_AppendResult(interp, "couldn't open socket: ",
- Tcl_PosixError(interp), NULL);
- if (errorMsg != NULL) {
- Tcl_AppendResult(interp, " (", errorMsg, ")", NULL);
- }
- }
- return NULL;
}
/*