From bbc3bb7823030f97cb3f96d7a76ccf49b0245545 Mon Sep 17 00:00:00 2001 From: oehhar Date: Tue, 1 Apr 2014 12:16:39 +0000 Subject: Removed thread debugging printf messages --- win/tclWinSock.c | 123 ++++++------------------------------------------------- 1 file changed, 13 insertions(+), 110 deletions(-) diff --git a/win/tclWinSock.c b/win/tclWinSock.c index 91f9e8c..1b252e0 100644 --- a/win/tclWinSock.c +++ b/win/tclWinSock.c @@ -50,14 +50,6 @@ #include "tclWinInt.h" -//#define DEBUGGING -#ifdef DEBUGGING -#define DEBUG(x) fprintf(stderr, ">>> %p %s(%d): %s<<<\n", \ - statePtr, __FUNCTION__, __LINE__, x) -#else -#define DEBUG(x) -#endif - /* * Which version of the winsock API do we want? */ @@ -318,6 +310,10 @@ static TclInitProcessGlobalValueProc InitializeHostName; static ProcessGlobalValue hostName = {0, 0, NULL, NULL, InitializeHostName, NULL, NULL}; +/* + * Address print debug functions + */ +#if 0 void printaddrinfo(struct addrinfo *ai, char *prefix) { char host[NI_MAXHOST], port[NI_MAXSERV]; @@ -325,9 +321,6 @@ void printaddrinfo(struct addrinfo *ai, char *prefix) host, sizeof(host), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV); -#ifdef DEBUGGING - fprintf(stderr,"%s: [%s]:%s\n", prefix, host, port); -#endif } void printaddrinfolist(struct addrinfo *addrlist, char *prefix) { @@ -336,6 +329,7 @@ void printaddrinfolist(struct addrinfo *addrlist, char *prefix) printaddrinfo(ai, prefix); } } +#endif /* *---------------------------------------------------------------------- @@ -1319,9 +1313,6 @@ TcpGetOptionProc( } for (fds = statePtr->sockets; fds != NULL; fds = fds->next) { sock = fds->fd; -#ifdef DEBUGGING - fprintf(stderr, "sock == %d\n", sock); -#endif size = sizeof(sockname); if (getsockname(sock, &(sockname.sa), &size) >= 0) { int flags = reverseDNS; @@ -1452,9 +1443,6 @@ TcpWatchProc( { TcpState *statePtr = instanceData; - DEBUG((mask & TCL_READABLE) ? "+r":"-r"); - DEBUG((mask & TCL_WRITABLE) ? "+w":"-w"); - /* * Update the watch events mask. Only if the socket is not a server * socket. [Bug 557878] @@ -1567,13 +1555,8 @@ CreateClientSocket( int async_callback = statePtr->sockets->fd != INVALID_SOCKET; ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey); - DEBUG(async_connect ? "async connect" : "sync connect"); - if (async_callback) { - DEBUG("subsequent call"); goto reenter; - } else { - DEBUG("first call"); } for (statePtr->addr = statePtr->addrlist; statePtr->addr != NULL; @@ -1582,28 +1565,20 @@ CreateClientSocket( for (statePtr->myaddr = statePtr->myaddrlist; statePtr->myaddr != NULL; statePtr->myaddr = statePtr->myaddr->ai_next) { - DEBUG("inner loop"); - /* * No need to try combinations of local and remote addresses * of different families. */ if (statePtr->myaddr->ai_family != statePtr->addr->ai_family) { - DEBUG("family mismatch"); continue; } - DEBUG(statePtr->myaddr->ai_family == AF_INET ? "IPv4" : "IPv6"); - printaddrinfo(statePtr->myaddr, "~~ from"); - printaddrinfo(statePtr->addr, "~~ to"); - /* * Close the socket if it is still open from the last unsuccessful * iteration. */ if (statePtr->sockets->fd != INVALID_SOCKET) { - DEBUG("closesocket"); closesocket(statePtr->sockets->fd); } @@ -1623,14 +1598,10 @@ CreateClientSocket( /* continue on socket creation error */ if (statePtr->sockets->fd == INVALID_SOCKET) { - DEBUG("socket() failed"); TclWinConvertError((DWORD) WSAGetLastError()); continue; } - -#ifdef DEBUGGING - fprintf(stderr, "Client socket %d created\n", statePtr->sockets->fd); -#endif + /* * Win-NT has a misfeature that sockets are inherited in child * processes by default. Turn off the inherit bit. @@ -1650,7 +1621,6 @@ CreateClientSocket( if (bind(statePtr->sockets->fd, statePtr->myaddr->ai_addr, statePtr->myaddr->ai_addrlen) == SOCKET_ERROR) { - DEBUG("bind() failed"); TclWinConvertError((DWORD) WSAGetLastError()); continue; } @@ -1706,7 +1676,6 @@ CreateClientSocket( * Attempt to connect to the remote socket. */ - DEBUG("connect()"); connect(statePtr->sockets->fd, statePtr->addr->ai_addr, statePtr->addr->ai_addrlen); @@ -1717,8 +1686,6 @@ CreateClientSocket( /* * Asynchroneous connect */ - DEBUG("WSAEWOULDBLOCK"); - /* * Remember that we jump back behind this next round @@ -1727,7 +1694,6 @@ CreateClientSocket( return TCL_OK; reenter: - DEBUG("reenter"); /* * Re-entry point for async connect after connect event or * blocking operation @@ -1744,9 +1710,7 @@ CreateClientSocket( /* Free list lock */ SetEvent(tsdPtr->socketListLock); } -#ifdef DEBUGGING - fprintf(stderr, "connectError: %d\n", Tcl_GetErrno()); -#endif + /* * Clear the tsd socket list pointer if we did not wait for * the FD_CONNECT asyncroneously @@ -1763,11 +1727,6 @@ out: /* * Socket connected or connection failed */ - DEBUG("connected or finally failed"); - - /* - * Final connect failure - */ if ( Tcl_GetErrno() == 0 ) { /* @@ -1776,7 +1735,6 @@ out: /* * Set up the select mask for read/write events. */ - DEBUG("selectEvents = FD_READ | FD_WRITE | FD_CLOSE"); statePtr->selectEvents = FD_READ | FD_WRITE | FD_CLOSE; /* @@ -1790,7 +1748,6 @@ out: /* * Connect failed */ - DEBUG("ERRNO"); /* * For async connect schedule a writable event to report the fail. @@ -1799,7 +1756,6 @@ out: /* * Set up the select mask for read/write events. */ - DEBUG("selectEvents = FD_WRITE/FD_READ for connect fail"); statePtr->selectEvents = FD_WRITE|FD_READ; /* get statePtr lock */ WaitForSingleObject(tsdPtr->socketListLock, INFINITE); @@ -1885,8 +1841,6 @@ Tcl_OpenTcpClient( } return NULL; } - printaddrinfolist(myaddrlist, "local"); - printaddrinfolist(addrlist, "remote"); statePtr = NewSocketInfo(INVALID_SOCKET); statePtr->addrlist = addrlist; @@ -1898,7 +1852,6 @@ Tcl_OpenTcpClient( /* * Create a new client socket and wrap it in a channel. */ - DEBUG(""); if (CreateClientSocket(interp, statePtr) != TCL_OK) { TcpCloseProc(statePtr, NULL); return NULL; @@ -2480,7 +2433,6 @@ SocketSetupProc( if (statePtr->readyEvents & (statePtr->watchEvents | FD_CONNECT | FD_ACCEPT) ) { - DEBUG("Tcl_SetMaxBlockTime"); Tcl_SetMaxBlockTime(&blockTime); break; } @@ -2527,12 +2479,10 @@ SocketCheckProc( WaitForSingleObject(tsdPtr->socketListLock, INFINITE); for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { - DEBUG("Socket loop"); if ((statePtr->readyEvents & (statePtr->watchEvents | FD_CONNECT | FD_ACCEPT)) && !(statePtr->flags & SOCKET_PENDING) ) { - DEBUG("Event found"); statePtr->flags |= SOCKET_PENDING; evPtr = ckalloc(sizeof(SocketEvent)); evPtr->header.proc = SocketEventProc; @@ -2570,7 +2520,7 @@ SocketEventProc( int flags) /* Flags that indicate what events to handle, * such as TCL_FILE_EVENTS. */ { - TcpState *statePtr = NULL; /* DEBUG */ + TcpState *statePtr; SocketEvent *eventPtr = (SocketEvent *) evPtr; int mask = 0, events; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); @@ -2579,7 +2529,6 @@ SocketEventProc( address addr; int len; - DEBUG(""); if (!(flags & TCL_FILE_EVENTS)) { return 0; } @@ -2610,7 +2559,6 @@ SocketEventProc( /* Continue async connect if pending and ready */ if ( statePtr->readyEvents & FD_CONNECT ) { statePtr->readyEvents &= ~(FD_CONNECT); - DEBUG("FD_CONNECT"); if ( statePtr->flags & TCP_ASYNC_CONNECT_REENTER_PENDING ) { SetEvent(tsdPtr->socketListLock); CreateClientSocket(NULL, statePtr); @@ -2702,7 +2650,6 @@ SocketEventProc( Tcl_Time blockTime = { 0, 0 }; - DEBUG("FD_CLOSE"); Tcl_SetMaxBlockTime(&blockTime); mask |= TCL_READABLE|TCL_WRITABLE; } else if (events & FD_READ) { @@ -2722,11 +2669,10 @@ SocketEventProc( /* * We must check to see if data is really available, since someone * could have consumed the data in the meantime. Turn off async - * notification so select will work correctly. If the socket is still - * readable, notify the channel driver, otherwise reset the async - * select handler and keep waiting. + * notification so select will work correctly. If the socket is + * still readable, notify the channel driver, otherwise reset the + * async select handler and keep waiting. */ - DEBUG("FD_READ"); SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) UNSELECT, (LPARAM) statePtr); @@ -2751,7 +2697,6 @@ SocketEventProc( */ if (events & FD_WRITE) { - DEBUG("FD_WRITE"); mask |= TCL_WRITABLE; } @@ -2760,10 +2705,8 @@ SocketEventProc( */ if (mask) { - DEBUG("Calling Tcl_NotifyChannel..."); Tcl_NotifyChannel(statePtr->channel, mask); } - DEBUG("returning..."); return 1; } @@ -2878,7 +2821,6 @@ WaitForSocketEvent( /* * Be sure to disable event servicing so we are truly modal. */ - DEBUG("============="); oldMode = Tcl_SetServiceMode(TCL_SERVICE_NONE); @@ -3017,7 +2959,7 @@ SocketProc( { int event, error; SOCKET socket; - TcpState *statePtr = NULL; /* DEBUG */ + TcpState *statePtr; int info_found = 0; TcpFdList *fds = NULL; ThreadSpecificData *tsdPtr = (ThreadSpecificData *) @@ -3056,17 +2998,6 @@ SocketProc( error = WSAGETSELECTERROR(lParam); socket = (SOCKET) wParam; - #ifdef DEBUGGING - fprintf(stderr,"event = %d, error=%d\n",event,error); - #endif - if (event & FD_READ) DEBUG("READ Event"); - if (event & FD_WRITE) DEBUG("WRITE Event"); - if (event & FD_CLOSE) DEBUG("CLOSE Event"); - if (event & FD_CONNECT) - DEBUG("CONNECT Event"); - if (event & FD_ACCEPT) DEBUG("ACCEPT Event"); - - DEBUG("Get list lock"); WaitForSingleObject(tsdPtr->socketListLock, INFINITE); /* @@ -3076,10 +3007,8 @@ SocketProc( for (statePtr = tsdPtr->socketList; statePtr != NULL; statePtr = statePtr->nextPtr) { - DEBUG("Cur InfoPtr"); if ( FindFDInList(statePtr,socket) ) { info_found = 1; - DEBUG("InfoPtr found"); break; } } @@ -3091,14 +3020,9 @@ SocketProc( && tsdPtr->pendingTcpState != NULL && FindFDInList(tsdPtr->pendingTcpState,socket) ) { statePtr = tsdPtr->pendingTcpState; - DEBUG("Pending InfoPtr found"); info_found = 1; } if (info_found) { - if (event & FD_READ) - DEBUG("|->FD_READ"); - if (event & FD_WRITE) - DEBUG("|->FD_WRITE"); /* * Update the socket state. @@ -3109,16 +3033,13 @@ SocketProc( */ if (event & FD_CLOSE) { - DEBUG("FD_CLOSE"); statePtr->acceptEventCount = 0; statePtr->readyEvents &= ~(FD_WRITE|FD_ACCEPT); } else if (event & FD_ACCEPT) { - DEBUG("FD_ACCEPT"); - statePtr->acceptEventCount++; + statePtr->acceptEventCount++; } if (event & FD_CONNECT) { - DEBUG("FD_CONNECT"); /* * Remember any error that occurred so we can report * connection failures. @@ -3143,19 +3064,9 @@ SocketProc( break; case SOCKET_SELECT: - DEBUG("SOCKET_SELECT"); statePtr = (TcpState *) lParam; for (fds = statePtr->sockets; fds != NULL; fds = fds->next) { -#ifdef DEBUGGING - fprintf(stderr,"loop over fd = %d\n",fds->fd); -#endif if (wParam == SELECT) { - DEBUG("SELECT"); - if (statePtr->selectEvents & FD_READ) DEBUG(" READ"); - if (statePtr->selectEvents & FD_WRITE) DEBUG(" WRITE"); - if (statePtr->selectEvents & FD_CLOSE) DEBUG(" CLOSE"); - if (statePtr->selectEvents & FD_CONNECT) DEBUG(" CONNECT"); - if (statePtr->selectEvents & FD_ACCEPT) DEBUG(" ACCEPT"); WSAAsyncSelect(fds->fd, hwnd, SOCKET_MESSAGE, statePtr->selectEvents); } else { @@ -3163,14 +3074,12 @@ SocketProc( * Clear the selection mask */ - DEBUG("!SELECT"); WSAAsyncSelect(fds->fd, hwnd, 0, 0); } } break; case SOCKET_TERMINATE: - DEBUG("SOCKET_TERMINATE"); DestroyWindow(hwnd); break; } @@ -3201,9 +3110,6 @@ FindFDInList( { TcpFdList *fds; for (fds = statePtr->sockets; fds != NULL; fds = fds->next) { - #ifdef DEBUGGING - fprintf(stderr,"socket = %d, fd=%d\n",socket,fds); - #endif if (fds->fd == socket) { return 1; } @@ -3346,12 +3252,10 @@ TcpThreadActionProc( tsdPtr = TCL_TSD_INIT(&dataKey); WaitForSingleObject(tsdPtr->socketListLock, INFINITE); - DEBUG("Inserting pointer to list"); statePtr->nextPtr = tsdPtr->socketList; tsdPtr->socketList = statePtr; if (statePtr == tsdPtr->pendingTcpState) { - DEBUG("Clearing temporary info pointer"); tsdPtr->pendingTcpState = NULL; } @@ -3370,7 +3274,6 @@ TcpThreadActionProc( */ WaitForSingleObject(tsdPtr->socketListLock, INFINITE); - DEBUG("Removing pointer from list"); for (nextPtrPtr = &(tsdPtr->socketList); (*nextPtrPtr) != NULL; nextPtrPtr = &((*nextPtrPtr)->nextPtr)) { if ((*nextPtrPtr) == statePtr) { -- cgit v0.12 From 8945be288772dd0087122837b2b4432109180088 Mon Sep 17 00:00:00 2001 From: oehhar Date: Wed, 2 Apr 2014 08:22:12 +0000 Subject: Marked all communication variables which are set by notifier thread with "volatile". --- win/tclWinSock.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/win/tclWinSock.c b/win/tclWinSock.c index 1b252e0..036f3b9 100644 --- a/win/tclWinSock.c +++ b/win/tclWinSock.c @@ -146,7 +146,7 @@ struct TcpState { int watchEvents; /* OR'ed combination of FD_READ, FD_WRITE, * FD_CLOSE, FD_ACCEPT and FD_CONNECT that * indicate which events are interesting. */ - int readyEvents; /* OR'ed combination of FD_READ, FD_WRITE, + volatile int readyEvents; /* OR'ed combination of FD_READ, FD_WRITE, * FD_CLOSE, FD_ACCEPT and FD_CONNECT that * indicate which events have occurred. * Set by notifier thread, access must be @@ -155,7 +155,8 @@ struct TcpState { * FD_CLOSE, FD_ACCEPT and FD_CONNECT that * indicate which events are currently being * selected. */ - int acceptEventCount; /* Count of the current number of FD_ACCEPTs + volatile int acceptEventCount; + /* Count of the current number of FD_ACCEPTs * that have arrived and not yet processed. * Set by notifier thread, access must be * protected by semaphore */ @@ -173,7 +174,7 @@ struct TcpState { struct addrinfo *myaddr; /* Iterator over myaddrlist. */ int status; /* Cache status of async socket. */ int cachedBlocking; /* Cache blocking mode of async socket. */ - int connectError; /* Async connect error set by notifier thread. + volatile int connectError; /* Async connect error set by notifier thread. * Set by notifier thread, access must be * protected by semaphore */ struct TcpState *nextPtr; /* The next socket on the per-thread socket -- cgit v0.12 From 8978760b1a95d061dff0d9c3f0c8a997aa56998d Mon Sep 17 00:00:00 2001 From: max Date: Fri, 4 Apr 2014 08:51:58 +0000 Subject: Make the naming of TcpState variables consistent --- unix/tclUnixSock.c | 102 ++++++++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 49 deletions(-) diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c index b26d707..466b231 100644 --- a/unix/tclUnixSock.c +++ b/unix/tclUnixSock.c @@ -991,21 +991,21 @@ TcpAsyncCallback( static int CreateClientSocket( Tcl_Interp *interp, /* For error reporting; can be NULL. */ - TcpState *state) + TcpState *statePtr) { socklen_t optlen; - int async_callback = (state->addr != NULL); - int ret = -1, error; - int async = state->flags & TCP_ASYNC_CONNECT; + int async_callback = (statePtr->addr != NULL); + int ret = -1, error = 0; + int async = statePtr->flags & TCP_ASYNC_CONNECT; if (async_callback) { goto reenter; } - for (state->addr = state->addrlist; state->addr != NULL; - state->addr = state->addr->ai_next) { - for (state->myaddr = state->myaddrlist; state->myaddr != NULL; - state->myaddr = state->myaddr->ai_next) { + for (statePtr->addr = statePtr->addrlist; statePtr->addr != NULL; + statePtr->addr = statePtr->addr->ai_next) { + for (statePtr->myaddr = statePtr->myaddrlist; statePtr->myaddr != NULL; + statePtr->myaddr = statePtr->myaddr->ai_next) { int reuseaddr; /* @@ -1013,7 +1013,7 @@ CreateClientSocket( * different families. */ - if (state->myaddr->ai_family != state->addr->ai_family) { + if (statePtr->myaddr->ai_family != statePtr->addr->ai_family) { continue; } @@ -1022,14 +1022,14 @@ CreateClientSocket( * iteration. */ - if (state->fds.fd >= 0) { - close(state->fds.fd); - state->fds.fd = -1; + if (statePtr->fds.fd >= 0) { + close(statePtr->fds.fd); + statePtr->fds.fd = -1; errno = 0; } - state->fds.fd = socket(state->addr->ai_family, SOCK_STREAM, 0); - if (state->fds.fd < 0) { + statePtr->fds.fd = socket(statePtr->addr->ai_family, SOCK_STREAM, 0); + if (statePtr->fds.fd < 0) { continue; } @@ -1038,27 +1038,28 @@ CreateClientSocket( * inherited by child processes. */ - fcntl(state->fds.fd, F_SETFD, FD_CLOEXEC); + fcntl(statePtr->fds.fd, F_SETFD, FD_CLOEXEC); /* * Set kernel space buffering */ - TclSockMinimumBuffers(INT2PTR(state->fds.fd), SOCKET_BUFSIZE); + TclSockMinimumBuffers(INT2PTR(statePtr->fds.fd), SOCKET_BUFSIZE); if (async) { - ret = TclUnixSetBlockingMode(state->fds.fd,TCL_MODE_NONBLOCKING); + ret = TclUnixSetBlockingMode(statePtr->fds.fd,TCL_MODE_NONBLOCKING); if (ret < 0) { continue; } } reuseaddr = 1; - (void) setsockopt(state->fds.fd, SOL_SOCKET, SO_REUSEADDR, + (void) setsockopt(statePtr->fds.fd, SOL_SOCKET, SO_REUSEADDR, (char *) &reuseaddr, sizeof(reuseaddr)); - ret = bind(state->fds.fd, state->myaddr->ai_addr, - state->myaddr->ai_addrlen); + ret = bind(statePtr->fds.fd, statePtr->myaddr->ai_addr, + statePtr->myaddr->ai_addrlen); if (ret < 0) { + error = errno; continue; } @@ -1069,16 +1070,17 @@ CreateClientSocket( * in being informed when the connect completes. */ - ret = connect(state->fds.fd, state->addr->ai_addr, - state->addr->ai_addrlen); - error = errno; + ret = connect(statePtr->fds.fd, statePtr->addr->ai_addr, + statePtr->addr->ai_addrlen); + if (ret < 0) error = errno; if (ret < 0 && errno == EINPROGRESS) { - Tcl_CreateFileHandler(state->fds.fd, - TCL_WRITABLE|TCL_EXCEPTION, TcpAsyncCallback, state); + Tcl_CreateFileHandler(statePtr->fds.fd, + TCL_WRITABLE|TCL_EXCEPTION, TcpAsyncCallback, statePtr); + statePtr->error = errno = EWOULDBLOCK; return TCL_OK; reenter: - Tcl_DeleteFileHandler(state->fds.fd); + Tcl_DeleteFileHandler(statePtr->fds.fd); /* * Read the error state from the socket to see if the async @@ -1089,26 +1091,26 @@ CreateClientSocket( optlen = sizeof(int); - getsockopt(state->fds.fd, SOL_SOCKET, SO_ERROR, + getsockopt(statePtr->fds.fd, SOL_SOCKET, SO_ERROR, (char *) &error, &optlen); errno = error; } - if (ret == 0 || errno == 0) { + if (error == 0) { goto out; } } } out: - state->error = errno; - CLEAR_BITS(state->flags, TCP_ASYNC_CONNECT); + statePtr->error = error; + CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT); if (async_callback) { /* * An asynchonous connection has finally succeeded or failed. */ - TcpWatchProc(state, state->filehandlers); - TclUnixSetBlockingMode(state->fds.fd, state->cachedBlocking); + TcpWatchProc(statePtr, statePtr->filehandlers); + TclUnixSetBlockingMode(statePtr->fds.fd, statePtr->cachedBlocking); /* * We need to forward the writable event that brought us here, bcasue @@ -1119,8 +1121,9 @@ out: * the event mechanism one roundtrip through select(). */ - Tcl_NotifyChannel(state->channel, TCL_WRITABLE); - } else if (ret != 0) { + Tcl_NotifyChannel(statePtr->channel, TCL_WRITABLE); + } + if (error != 0) { /* * Failure for either a synchronous connection, or an async one that * failed before it could enter background mode, e.g. because an @@ -1128,6 +1131,7 @@ out: */ if (interp != NULL) { + errno = error; Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't open socket: %s", Tcl_PosixError(interp))); } @@ -1164,7 +1168,7 @@ Tcl_OpenTcpClient( * connect. Otherwise we do a blocking * connect. */ { - TcpState *state; + TcpState *statePtr; const char *errorMsg = NULL; struct addrinfo *addrlist = NULL, *myaddrlist = NULL; char channelName[SOCK_CHAN_LENGTH]; @@ -1189,32 +1193,32 @@ Tcl_OpenTcpClient( /* * Allocate a new TcpState for this socket. */ - state = ckalloc(sizeof(TcpState)); - memset(state, 0, sizeof(TcpState)); - state->flags = async ? TCP_ASYNC_CONNECT : 0; - state->cachedBlocking = TCL_MODE_BLOCKING; - state->addrlist = addrlist; - state->myaddrlist = myaddrlist; - state->fds.fd = -1; + statePtr = ckalloc(sizeof(TcpState)); + memset(statePtr, 0, sizeof(TcpState)); + statePtr->flags = async ? TCP_ASYNC_CONNECT : 0; + statePtr->cachedBlocking = TCL_MODE_BLOCKING; + statePtr->addrlist = addrlist; + statePtr->myaddrlist = myaddrlist; + statePtr->fds.fd = -1; /* * Create a new client socket and wrap it in a channel. */ - if (CreateClientSocket(interp, state) != TCL_OK) { - TcpCloseProc(state, NULL); + if (CreateClientSocket(interp, statePtr) != TCL_OK) { + TcpCloseProc(statePtr, NULL); return NULL; } - sprintf(channelName, SOCK_TEMPLATE, (long) state); + sprintf(channelName, SOCK_TEMPLATE, (long) statePtr); - state->channel = Tcl_CreateChannel(&tcpChannelType, channelName, state, + statePtr->channel = Tcl_CreateChannel(&tcpChannelType, channelName, statePtr, (TCL_READABLE | TCL_WRITABLE)); - if (Tcl_SetChannelOption(interp, state->channel, "-translation", + if (Tcl_SetChannelOption(interp, statePtr->channel, "-translation", "auto crlf") == TCL_ERROR) { - Tcl_Close(NULL, state->channel); + Tcl_Close(NULL, statePtr->channel); return NULL; } - return state->channel; + return statePtr->channel; } /* -- cgit v0.12 From 053685ad2952fe7a83cf63ff28ec273862c903b3 Mon Sep 17 00:00:00 2001 From: max Date: Fri, 4 Apr 2014 10:02:47 +0000 Subject: * Rework WaitForConnect() to fix synchronous completion of asynchronous connections. * Let TcpInputProc() and TcpOutputProc() fail before calling any I/O syscalls when an asynchronous connection has failed. * Adjust the tests accordingly. --- tests/socket.test | 13 ++++++++----- unix/tclUnixSock.c | 54 ++++++++++++++++++++++++------------------------------ 2 files changed, 32 insertions(+), 35 deletions(-) diff --git a/tests/socket.test b/tests/socket.test index 61660cd..4fba2c3 100644 --- a/tests/socket.test +++ b/tests/socket.test @@ -1993,7 +1993,7 @@ test socket-14.7.2 {pending [socket -async] and blocking [gets], no listener} \ list $x [fconfigure $sock -error] } -cleanup { close $sock - } -match glob -result {{error reading "sock*": socket is not connected} {connection refused}} + } -match glob -result {{error reading "sock*": connection refused} {}} test socket-14.8.0 {pending [socket -async] and nonblocking [gets], server is IPv4} \ -constraints {socket supported_inet supported_inet6} \ -setup { @@ -2055,10 +2055,10 @@ test socket-14.8.2 {pending [socket -async] and nonblocking [gets], no listener} if {[catch {gets $sock} x] || $x ne "" || ![fblocked $sock]} break after 200 } - fconfigure $sock -error + list $x [fconfigure $sock -error] } -cleanup { close $sock - } -match glob -result {connection refused} + } -match glob -result {{error reading "sock*": connection refused} {}} test socket-14.9.0 {pending [socket -async] and blocking [puts], server is IPv4} \ -constraints {socket supported_inet supported_inet6} \ -setup { @@ -2171,7 +2171,9 @@ test socket-14.11.0 {pending [socket -async] and blocking [puts], no listener, n vwait x close $sock } -cleanup { - } -result {broken pipe} -returnCodes 1 + catch {close $sock} + unset x + } -result {connection refused} -returnCodes 1 test socket-14.11.1 {pending [socket -async] and blocking [puts], no listener, flush} \ -constraints {socket supported_inet supported_inet6} \ -body { @@ -2183,8 +2185,9 @@ test socket-14.11.1 {pending [socket -async] and blocking [puts], no listener, f vwait x close $sock } -cleanup { + catch {close $sock} unset x - } -result {broken pipe} -returnCodes 1 + } -result {connection refused} -returnCodes 1 test socket-14.12 {[socket -async] background progress triggered by [fconfigure -error]} \ -constraints {socket supported_inet supported_inet6} \ -body { diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c index 466b231..d4b7b62 100644 --- a/unix/tclUnixSock.c +++ b/unix/tclUnixSock.c @@ -128,8 +128,7 @@ static int TcpInputProc(ClientData instanceData, char *buf, static int TcpOutputProc(ClientData instanceData, const char *buf, int toWrite, int *errorCode); static void TcpWatchProc(ClientData instanceData, int mask); -static int WaitForConnect(TcpState *statePtr, int *errorCodePtr, - int noblock); +static int WaitForConnect(TcpState *statePtr, int noblock); /* * This structure describes the channel type structure for TCP socket @@ -399,41 +398,33 @@ TcpBlockModeProc( static int WaitForConnect( TcpState *statePtr, /* State of the socket. */ - int *errorCodePtr, /* Where to store errors? */ int noblock) /* Don't wait, even for sockets in blocking mode */ { - int timeOut; /* How long to wait. */ - int state; /* Of calling TclWaitForFile. */ - /* * If an asynchronous connect is in progress, attempt to wait for it to * complete before reading. */ if (statePtr->flags & TCP_ASYNC_CONNECT) { - if (noblock || statePtr->flags & TCP_ASYNC_SOCKET) { - timeOut = 0; + if (noblock || (statePtr->flags & TCP_ASYNC_SOCKET)) { + if (TclUnixWaitForFile(statePtr->fds.fd, + TCL_WRITABLE | TCL_EXCEPTION, 0) != 0) { + CreateClientSocket(NULL, statePtr); + } } else { - timeOut = -1; - CLEAR_BITS(statePtr->flags, TCP_ASYNC_CONNECT); - } - errno = 0; - state = TclUnixWaitForFile(statePtr->fds.fd, - TCL_WRITABLE | TCL_EXCEPTION, timeOut); - if (state != 0) { - CreateClientSocket(NULL, statePtr); - } - if (statePtr->flags & TCP_ASYNC_CONNECT) { - /* We are still in progress, so ignore the result of the last - * attempt */ - *errorCodePtr = errno = EWOULDBLOCK; - return -1; + while (statePtr->flags & TCP_ASYNC_CONNECT) { + if (TclUnixWaitForFile(statePtr->fds.fd, + TCL_WRITABLE | TCL_EXCEPTION, -1) != 0) { + CreateClientSocket(NULL, statePtr); + } + } } - if (state & TCL_EXCEPTION) { - return -1; - } } - return 0; + if (statePtr->error != 0) { + return -1; + } else { + return 0; + } } /* @@ -471,7 +462,9 @@ TcpInputProc( int bytesRead; *errorCodePtr = 0; - if (WaitForConnect(statePtr, errorCodePtr, 0) != 0) { + if (WaitForConnect(statePtr, 0) != 0) { + *errorCodePtr = statePtr->error; + statePtr->error = 0; return -1; } bytesRead = recv(statePtr->fds.fd, buf, (size_t) bufSize, 0); @@ -521,7 +514,9 @@ TcpOutputProc( int written; *errorCodePtr = 0; - if (WaitForConnect(statePtr, errorCodePtr, 0) != 0) { + if (WaitForConnect(statePtr, 0) != 0) { + *errorCodePtr = statePtr->error; + statePtr->error = 0; return -1; } written = send(statePtr->fds.fd, buf, (size_t) toWrite, 0); @@ -748,9 +743,8 @@ TcpGetOptionProc( { TcpState *statePtr = instanceData; size_t len = 0; - int errorCode; - WaitForConnect(statePtr, &errorCode, 1); + WaitForConnect(statePtr, 1); if (optionName != NULL) { len = strlen(optionName); -- cgit v0.12 From a07a756335137e754bcd490da46a1cc1fd8df06c Mon Sep 17 00:00:00 2001 From: max Date: Fri, 4 Apr 2014 11:53:33 +0000 Subject: Add tests for bugs [336441ed59] and [581937ab1e] from core-8-5-branch. --- tests/socket.test | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/socket.test b/tests/socket.test index 4fba2c3..e2e40f1 100644 --- a/tests/socket.test +++ b/tests/socket.test @@ -998,6 +998,35 @@ test socket_$af-8.1 {testing -async flag on sockets} -constraints [list socket s close $s1 } -result bye +test socket_$af-8.2 {testing writable event when quick failure} {socket win} { + # Test for bug 336441ed59 where a quick background fail was ignored + + # Test only for windows as socket -async 255.255.255.255 fails directly + # on unix + + # The following connect should fail very quickly + set a1 [after 2000 {set x timeout}] + set s [socket -async 255.255.255.255 43434] + fileevent $s writable {set x writable} + vwait x + catch {close $s} + after cancel $a1 + set x +} writable + +test socket_$af-8.3 {testing fileevent readable on failed async socket connect} {socket} { + # Test for bug 581937ab1e + + set a1 [after 5000 {set x timeout}] + # This connect should fail + set s [socket -async localhost [randport]] + fileevent $s readable {set x readable} + vwait x + catch {close $s} + after cancel $a1 + set x +} readable + test socket_$af-9.1 {testing spurious events} -constraints [list socket supported_$af] -setup { set len 0 set spurious 0 -- cgit v0.12 From a89a49e51557dc13104128a3692631f2edb5c712 Mon Sep 17 00:00:00 2001 From: max Date: Fri, 4 Apr 2014 15:45:34 +0000 Subject: Fix/improve tests. --- tests/socket.test | 67 +++++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/tests/socket.test b/tests/socket.test index e2e40f1..927e544 100644 --- a/tests/socket.test +++ b/tests/socket.test @@ -998,34 +998,36 @@ test socket_$af-8.1 {testing -async flag on sockets} -constraints [list socket s close $s1 } -result bye -test socket_$af-8.2 {testing writable event when quick failure} {socket win} { +test socket_$af-8.2 {testing writable event when quick failure} -constraints [list socket win supported_$af] -body { # Test for bug 336441ed59 where a quick background fail was ignored - - # Test only for windows as socket -async 255.255.255.255 fails directly - # on unix + + # Test only for windows as socket -async 255.255.255.255 fails + # directly on unix # The following connect should fail very quickly set a1 [after 2000 {set x timeout}] - set s [socket -async 255.255.255.255 43434] + set s [socket -async $localhost 43434] fileevent $s writable {set x writable} vwait x + set x +} -cleanup { catch {close $s} after cancel $a1 - set x -} writable +} -result writable -test socket_$af-8.3 {testing fileevent readable on failed async socket connect} {socket} { +test socket_$af-8.3 {testing fileevent readable on failed async socket connect} -constraints [list socket supported_$af] -body { # Test for bug 581937ab1e - + set a1 [after 5000 {set x timeout}] # This connect should fail set s [socket -async localhost [randport]] fileevent $s readable {set x readable} vwait x + set x +} -cleanup { catch {close $s} after cancel $a1 - set x -} readable +} -result readable test socket_$af-9.1 {testing spurious events} -constraints [list socket supported_$af] -setup { set len 0 @@ -1602,8 +1604,8 @@ test socket_$af-12.2 {testing inheritance of client sockets} -setup { close $f # If the socket doesn't hit end-of-file in 10 seconds, the script1 process # must have inherited the client. - set failed 0 - set after [after 10000 [list set failed 1]] + set timeout 0 + set after [after 10000 {set x "client socket was inherited"}] } -constraints [list socket supported_$af stdio exec] -body { # Create the server socket set server [socket -server accept -myaddr $localhost 0] @@ -1613,26 +1615,20 @@ test socket_$af-12.2 {testing inheritance of client sockets} -setup { close $server fileevent $file readable [list getdata $file] fconfigure $file -buffering line -blocking 0 + set ::f $file } proc getdata { file } { # Read handler on the accepted socket. - global x failed + global x set status [catch {read $file} data] if {$status != 0} { - set x {read failed, error was $data} - catch { close $file } + set x "read failed, error was $data" } elseif {$data ne ""} { } elseif {[fblocked $file]} { } elseif {[eof $file]} { - if {$failed} { - set x {client socket was inherited} - } else { - set x {client socket was not inherited} - } - catch { close $file } + set x "client socket was not inherited" } else { - set x {impossible case} - catch { close $file } + set x "impossible case" } } # Launch the script2 process @@ -1642,6 +1638,8 @@ test socket_$af-12.2 {testing inheritance of client sockets} -setup { vwait x return $x } -cleanup { + fconfigure $f -blocking 1 + close $f after cancel $after close $p } -result {client socket was not inherited} @@ -1683,35 +1681,30 @@ test socket_$af-12.3 {testing inheritance of accepted sockets} -setup { # If the socket is still open after 5 seconds, the script1 process must # have inherited the accepted socket. set failed 0 - set after [after 5000 [list set failed 1]] + set after [after 5000 [list set x "accepted socket was inherited"]] proc getdata { file } { # Read handler on the client socket. global x global failed set status [catch {read $file} data] if {$status != 0} { - set x {read failed, error was $data} - catch { close $file } + set x "read failed, error was $data" } elseif {[string compare {} $data]} { } elseif {[fblocked $file]} { } elseif {[eof $file]} { - if {$failed} { - set x {accepted socket was inherited} - } else { - set x {accepted socket was not inherited} - } - catch { close $file } + set x "accepted socket was not inherited" } else { - set x {impossible case} - catch { close $file } + set x "impossible case" } return } vwait x - return $x + set x } -cleanup { + fconfigure $f -blocking 1 + close $f after cancel $after - catch {close $p} + close $p } -result {accepted socket was not inherited} test socket_$af-13.1 {Testing use of shared socket between two threads} -body { -- cgit v0.12 From f0c184a069af5733133ae8b053918986b4cff221 Mon Sep 17 00:00:00 2001 From: max Date: Fri, 4 Apr 2014 15:56:48 +0000 Subject: Move tests 8.2 and 8.3 out of the IPv4/IPv6 loop to 14.13 and 14.14. --- tests/socket.test | 63 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/tests/socket.test b/tests/socket.test index 927e544..d36d2b3 100644 --- a/tests/socket.test +++ b/tests/socket.test @@ -998,37 +998,6 @@ test socket_$af-8.1 {testing -async flag on sockets} -constraints [list socket s close $s1 } -result bye -test socket_$af-8.2 {testing writable event when quick failure} -constraints [list socket win supported_$af] -body { - # Test for bug 336441ed59 where a quick background fail was ignored - - # Test only for windows as socket -async 255.255.255.255 fails - # directly on unix - - # The following connect should fail very quickly - set a1 [after 2000 {set x timeout}] - set s [socket -async $localhost 43434] - fileevent $s writable {set x writable} - vwait x - set x -} -cleanup { - catch {close $s} - after cancel $a1 -} -result writable - -test socket_$af-8.3 {testing fileevent readable on failed async socket connect} -constraints [list socket supported_$af] -body { - # Test for bug 581937ab1e - - set a1 [after 5000 {set x timeout}] - # This connect should fail - set s [socket -async localhost [randport]] - fileevent $s readable {set x readable} - vwait x - set x -} -cleanup { - catch {close $s} - after cancel $a1 -} -result readable - test socket_$af-9.1 {testing spurious events} -constraints [list socket supported_$af] -setup { set len 0 set spurious 0 @@ -2225,6 +2194,38 @@ test socket-14.12 {[socket -async] background progress triggered by [fconfigure unset x s } -result {connection refused} +test socket-14.13 {testing writable event when quick failure} -constraints {socket win supported_inet} -body { + # Test for bug 336441ed59 where a quick background fail was ignored + + # Test only for windows as socket -async 255.255.255.255 fails + # directly on unix + + # The following connect should fail very quickly + set a1 [after 2000 {set x timeout}] + set s [socket -async 255.255.255.255 43434] + fileevent $s writable {set x writable} + vwait x + set x +} -cleanup { + catch {close $s} + after cancel $a1 +} -result writable + +test socket-14.14 {testing fileevent readable on failed async socket connect} -constraints [list socket] -body { + # Test for bug 581937ab1e + + set a1 [after 5000 {set x timeout}] + # This connect should fail + set s [socket -async localhost [randport]] + fileevent $s readable {set x readable} + vwait x + set x +} -cleanup { + catch {close $s} + after cancel $a1 +} -result readable + + ::tcltest::cleanupTests flush stdout return -- cgit v0.12