Subject: Broken intermediate state.

From: max <[email-masked]>
Date: Fri, 28 Feb 2014 10:47:53 +0000

Calling back to CreateClientSocket() from the event loop works, but
the final failed or succeeded state of an asyncronous socket does not
get notified to the channel correctly.
---
 unix/tclUnixSock.c |  15 +++
 win/tclWinSock.c   | 365 ++++++++++++++++++++++++++++++++---------------------
 2 files changed, 234 insertions(+), 146 deletions(-)

diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c
index 49a6460..c866903 100644
--- a/unix/tclUnixSock.c
+++ b/unix/tclUnixSock.c
@@ -163,6 +163,18 @@ static TclInitProcessGlobalValueProc InitializeHostName;
 static ProcessGlobalValue hostName =
 	{0, 0, NULL, NULL, InitializeHostName, NULL, NULL};
 
+void printaddrinfo(struct addrinfo *addrlist, char *prefix)
+{
+    char host[NI_MAXHOST], port[NI_MAXSERV];
+    struct addrinfo *ai;
+    for (ai = addrlist; ai != NULL; ai = ai->ai_next) {
+	getnameinfo(ai->ai_addr, ai->ai_addrlen,
+		    host, sizeof(host),
+		    port, sizeof(port),
+		    NI_NUMERICHOST|NI_NUMERICSERV);
+	fprintf(stderr,"%s: %s:%s\n", prefix, host, port);
+    }
+}
 /*
  *----------------------------------------------------------------------
  *
@@ -1160,6 +1172,9 @@ Tcl_OpenTcpClient(
         return NULL;
     }
 
+    printaddrinfo(myaddrlist, "local");
+    printaddrinfo(addrlist, "remote");
+
     /*
      * Allocate a new TcpState for this socket.
      */
diff --git a/win/tclWinSock.c b/win/tclWinSock.c
index 958e4ac..6afa094 100644
--- a/win/tclWinSock.c
+++ b/win/tclWinSock.c
@@ -47,6 +47,12 @@
 
 #include "tclWinInt.h"
 
+#if 1
+#define DEBUG(x) fprintf(stderr, ">>> %s(%d): %s<<<\n", __FUNCTION__, __LINE__, x)
+#else
+#define DEBUG(x)
+#endif
+
 /*
  * Which version of the winsock API do we want?
  */
@@ -76,7 +82,7 @@
 
 /* "sock" + a pointer in hex + \0 */
 #define SOCK_CHAN_LENGTH        (4 + sizeof(void *) * 2 + 1)
-#define SOCK_TEMPLATE           "sock%lx"
+#define SOCK_TEMPLATE           "sock%p"
 
 /*
  * The following variable is used to tell whether this module has been
@@ -156,6 +162,12 @@ struct SocketInfo {
     Tcl_TcpAcceptProc *acceptProc;
 				/* Proc to call on accept. */
     ClientData acceptProcData;	/* The data for the accept proc. */
+    struct addrinfo *addrlist;	/* Addresses to connect to. */
+    struct addrinfo *addr;	/* Iterator over addrlist. */
+    struct addrinfo *myaddrlist;/* Local address. */
+    struct addrinfo *myaddr;	/* Iterator over myaddrlist. */
+    int status;                 /* Cache status of async socket. */
+    int cachedBlocking;         /* Cache blocking mode of async socket. */
     int lastError;		/* Error code from last message. */
     struct SocketInfo *nextPtr;	/* The next socket on the per-thread socket
 				 * list. */
@@ -214,9 +226,7 @@ static WNDCLASS windowClass;
  * Static functions defined in this file.
  */
 
-static SocketInfo *	CreateClientSocket(Tcl_Interp *interp, int port,
-			    const char *host, const char *myaddr,
-			    int myport, int async);
+static int		CreateClientSocket(Tcl_Interp *interp, SocketInfo *infoPtr);
 static void		InitSockets(void);
 static SocketInfo *	NewSocketInfo(SOCKET socket);
 static void		SocketExitHandler(ClientData clientData);
@@ -267,6 +277,22 @@ static const Tcl_ChannelType tcpChannelType = {
     TcpThreadActionProc,    /* thread action proc */
     NULL		    /* truncate */
 };
+void printaddrinfo(struct addrinfo *ai, char *prefix)
+{
+    char host[NI_MAXHOST], port[NI_MAXSERV];
+    getnameinfo(ai->ai_addr, ai->ai_addrlen,
+		host, sizeof(host),
+		port, sizeof(port),
+		NI_NUMERICHOST|NI_NUMERICSERV);
+    fprintf(stderr,"%s: [%s]:%s\n", prefix, host, port);
+}
+void printaddrinfolist(struct addrinfo *addrlist, char *prefix)
+{
+    struct addrinfo *ai;
+    for (ai = addrlist; ai != NULL; ai = ai->ai_next) {
+	printaddrinfo(ai, prefix);
+    }
+}
 
 /*
  *----------------------------------------------------------------------
@@ -699,6 +725,8 @@ SocketEventProc(
     address addr;
     int len;
 
+    DEBUG("xxx");
+
     if (!(flags & TCL_FILE_EVENTS)) {
 	return 0;
     }
@@ -841,20 +869,18 @@ SocketEventProc(
 		    (WPARAM) SELECT, (LPARAM) infoPtr);
 	}
     }
-    if (events & (FD_WRITE | FD_CONNECT)) {
+    if (events & FD_WRITE) {
 	mask |= TCL_WRITABLE;
-	if (events & FD_CONNECT && infoPtr->lastError != NO_ERROR) {
-	    /*
-	     * Connect errors should also fire the readable handler.
-	     */
-
-	    mask |= TCL_READABLE;
-	}
     }
-
+    if (events & FD_CONNECT) {
+	DEBUG("Calling CreateClientSocket...");
+	CreateClientSocket(NULL, infoPtr);
+    }
     if (mask) {
+	DEBUG("Calling Tcl_NotifyChannel...");
 	Tcl_NotifyChannel(infoPtr->channel, mask);
     }
+    DEBUG("returning...");
     return 1;
 }
 
@@ -944,6 +970,13 @@ TcpCloseProc(
 	}
     }
 
+    if (infoPtr->addrlist != NULL) {
+        freeaddrinfo(infoPtr->addrlist);
+    }
+    if (infoPtr->myaddrlist != NULL) {
+        freeaddrinfo(infoPtr->myaddrlist);
+    }
+
     /*
      * TIP #218. Removed the code removing the structure from the global
      * socket list. This is now done by the thread action callbacks, and only
@@ -1072,22 +1105,11 @@ AddSocketInfoFd(
  */
 
 static SocketInfo *
-NewSocketInfo(
-    SOCKET socket)
+NewSocketInfo(SOCKET socket)
 {
     SocketInfo *infoPtr = ckalloc(sizeof(SocketInfo));
 
-    /* ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); */
-    infoPtr->channel = 0;
-    infoPtr->sockets = NULL;
-    infoPtr->flags = 0;
-    infoPtr->watchEvents = 0;
-    infoPtr->readyEvents = 0;
-    infoPtr->selectEvents = 0;
-    infoPtr->acceptEventCount = 0;
-    infoPtr->acceptProc = NULL;
-    infoPtr->acceptProcData = NULL;
-    infoPtr->lastError = 0;
+    memset(infoPtr, 0, sizeof(SocketInfo));
 
     /*
      * TIP #218. Removed the code inserting the new structure into the global
@@ -1095,8 +1117,6 @@ NewSocketInfo(
      * there.
      */
 
-    infoPtr->nextPtr = NULL;
-
     AddSocketInfoFd(infoPtr, socket);
 
     return infoPtr;
@@ -1107,193 +1127,189 @@ NewSocketInfo(
  *
  * CreateClientSocket --
  *
- *	This function opens a new client socket and initializes the
- *	SocketInfo structure.
+ *	This function opens a new socket in client mode.
  *
  * Results:
- *	Returns a new SocketInfo, or NULL with an error in interp.
+ *      TCL_OK, if the socket was successfully connected or an asynchronous
+ *      connection is in progress. If an error occurs, TCL_ERROR is returned
+ *      and an error message is left in interp.
  *
  * Side effects:
- *	None, except for allocation of memory.
+ *	Opens a socket.
+ *
+ * Remarks:
+ *	A single host name may resolve to more than one IP address, e.g. for
+ *	an IPv4/IPv6 dual stack host. For handling asyncronously connecting
+ *	sockets in the background for such hosts, this function can act as a
+ *	coroutine. On the first call, it sets up the control variables for the
+ *	two nested loops over the local and remote addresses. Once the first
+ *	connection attempt is in progress, it sets up itself as a writable
+ *	event handler for that socket, and returns. When the callback occurs,
+ *	control is transferred to the "reenter" label, right after the initial
+ *	return and the loops resume as if they had never been interrupted.
+ *	For syncronously connecting sockets, the loops work the usual way.
  *
  *----------------------------------------------------------------------
  */
 
-static SocketInfo *
+static int
 CreateClientSocket(
     Tcl_Interp *interp,		/* For error reporting; can be NULL. */
-    int port,			/* Port number to open. */
-    const char *host,		/* Name of host on which to open port. */
-    const char *myaddr,		/* Optional client-side address */
-    int myport,			/* Optional client-side port */
-    int async)			/* If nonzero, connect client socket
-				 * asynchronously. */
+    SocketInfo *infoPtr)
 {
     u_long flag = 1;		/* Indicates nonblocking mode. */
-    int asyncConnect = 0;	/* Will be 1 if async connect is in
-				 * progress. */
-    unsigned short chosenport = 0;
-    struct addrinfo *addrlist = NULL, *addrPtr;
-				/* Socket address to connect to. */
-    struct addrinfo *myaddrlist = NULL, *myaddrPtr;
-				/* Socket address for our side. */
-    const char *errorMsg = NULL;
-    SOCKET sock = INVALID_SOCKET;
-    SocketInfo *infoPtr = NULL;	/* The returned value. */
-    ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey);
-
-    /*
-     * Check that WinSock is initialized; do not call it if not, to prevent
-     * system crashes. This can happen at exit time if the exit handler for
-     * WinSock ran before other exit handlers that want to use sockets.
-     */
+    int async_callback = (infoPtr->addr != NULL);
+    int connected = 0;
+    int async = infoPtr->flags & SOCKET_ASYNC_CONNECT;
 
-    if (!SocketsEnabled()) {
-	return NULL;
+    DEBUG(async_callback ? "subsequent" : "first");
+    DEBUG(async ? "async" : "sync");
+    if (async_callback) {
+        goto reenter;
     }
+    
+    for (infoPtr->addr = infoPtr->addrlist; infoPtr->addr != NULL;
+	 infoPtr->addr = infoPtr->addr->ai_next) {
+	
+        for (infoPtr->myaddr = infoPtr->myaddrlist; infoPtr->myaddr != NULL;
+	     infoPtr->myaddr = infoPtr->myaddr->ai_next) {
 
-    /*
-     * Construct the addresses for each end of the socket.
-     */
-
-    if (!TclCreateSocketAddress(interp, &addrlist, host, port, 0,
-	    &errorMsg)) {
-	goto error;
-    }
-    if (!TclCreateSocketAddress(interp, &myaddrlist, myaddr, myport, 1,
-	    &errorMsg)) {
-	goto error;
-    }
+	    DEBUG("inner loop");
 
-    for (addrPtr = addrlist; addrPtr != NULL;
-	 addrPtr = addrPtr->ai_next) {
-	for (myaddrPtr = myaddrlist; myaddrPtr != NULL;
-	     myaddrPtr = myaddrPtr->ai_next) {
 	    /*
 	     * No need to try combinations of local and remote addresses
 	     * of different families.
 	     */
 
-	    if (myaddrPtr->ai_family != addrPtr->ai_family) {
+	    if (infoPtr->myaddr->ai_family != infoPtr->addr->ai_family) {
+		DEBUG("family mismatch");
 		continue;
 	    }
 
-	    sock = socket(myaddrPtr->ai_family, SOCK_STREAM, 0);
-	    if (sock == INVALID_SOCKET) {
+	    DEBUG(infoPtr->myaddr->ai_family == AF_INET ? "IPv4" : "IPv6");
+	    printaddrinfo(infoPtr->myaddr, "~~ from");
+	    printaddrinfo(infoPtr->addr,   "~~   to");
+
+            /*
+             * Close the socket if it is still open from the last unsuccessful
+             * iteration.
+             */
+
+	    if (infoPtr->sockets->fd != INVALID_SOCKET) {
+		DEBUG("closesocket");
+		closesocket(infoPtr->sockets->fd);
+	    }
+
+	    infoPtr->sockets->fd = socket(infoPtr->myaddr->ai_family, SOCK_STREAM, 0);
+	    if (infoPtr->sockets->fd == INVALID_SOCKET) {
+		DEBUG("socket() failed");
 		TclWinConvertError((DWORD) WSAGetLastError());
 		continue;
 	    }
-
+	    
 	    /*
 	     * Win-NT has a misfeature that sockets are inherited in child
 	     * processes by default. Turn off the inherit bit.
 	     */
 
-	    SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0);
+	    SetHandleInformation((HANDLE) infoPtr->sockets->fd, HANDLE_FLAG_INHERIT, 0);
 
 	    /*
 	     * Set kernel space buffering
 	     */
 
-	    TclSockMinimumBuffers((void *)sock, TCP_BUFFER_SIZE);
+	    TclSockMinimumBuffers((void *) infoPtr->sockets->fd, TCP_BUFFER_SIZE);
 
 	    /*
 	     * Try to bind to a local port.
 	     */
 
-	    if (bind(sock, myaddrPtr->ai_addr, myaddrPtr->ai_addrlen)
-		== SOCKET_ERROR) {
+	    if (bind(infoPtr->sockets->fd, infoPtr->myaddr->ai_addr,
+			infoPtr->myaddr->ai_addrlen) == SOCKET_ERROR) {
+		DEBUG("bind() failed");
 		TclWinConvertError((DWORD) WSAGetLastError());
-		goto looperror;
+		continue;
 	    }
 	    /*
 	     * Set the socket into nonblocking mode if the connect should
 	     * be done in the background.
 	     */
-	    if (async && ioctlsocket(sock, (long) FIONBIO, &flag)
+	    if (async && ioctlsocket(infoPtr->sockets->fd, (long) FIONBIO, &flag)
 		== SOCKET_ERROR) {
+		DEBUG("FIONBIO");
 		TclWinConvertError((DWORD) WSAGetLastError());
-		goto looperror;
+		continue;
 	    }
 
 	    /*
 	     * Attempt to connect to the remote socket.
 	     */
 
-	    if (connect(sock, addrPtr->ai_addr, addrPtr->ai_addrlen)
-		== SOCKET_ERROR) {
+	    if (connect(infoPtr->sockets->fd, infoPtr->addr->ai_addr,
+			    infoPtr->addr->ai_addrlen) == SOCKET_ERROR) {
 		DWORD error = (DWORD) WSAGetLastError();
-		if (error != WSAEWOULDBLOCK) {
+
+		DEBUG("connect()");
+		// fprintf(stderr,"error = %lu\n", error);
+		if (error == WSAEWOULDBLOCK) {
+		    ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey);
+		    DEBUG("WSAEWOULDBLOCK");
+		    infoPtr->flags |= SOCKET_ASYNC_CONNECT;
+		    infoPtr->selectEvents |= FD_CONNECT;
+
+		    ioctlsocket(infoPtr->sockets->fd, (long) FIONBIO, &flag);
+		    SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT,
+				(LPARAM) infoPtr);
+		    return TCL_OK;
+		} else {
+		    DEBUG("ELSE");
 		    TclWinConvertError(error);
-		    goto looperror;
+		    continue;
 		}
-		
+	    reenter:
+		DEBUG("reenter");
+		fprintf(stderr, "lastError: %d\n", infoPtr->lastError);
 		/*
 		 * The connection is progressing in the background.
 		 */
-
-		asyncConnect = 1;
-	    }
-	    goto connected;
-	    
-	looperror:
-	    if (sock != INVALID_SOCKET) {
-		closesocket(sock);
-		sock = INVALID_SOCKET;
+		// infoPtr->selectEvents &= ~(FD_CONNECT);
+	    } else {
+		connected = 1;
+		goto connected;
 	    }
 	}
     }
     goto error;
+connected:
+    DEBUG("connected");
+    /*
+     * Set up the select mask for read/write events. If the connect
+     * attempt has not completed, include connect events.
+     */
+    
+    infoPtr->selectEvents = FD_READ | FD_WRITE | FD_CLOSE;
 
-    connected:
-	/*
-	 * Add this socket to the global list of sockets.
-	 */
-
-	infoPtr = NewSocketInfo(sock);
-
-	/*
-	 * Set up the select mask for read/write events. If the connect
-	 * attempt has not completed, include connect events.
-	 */
-
-	infoPtr->selectEvents = FD_READ | FD_WRITE | FD_CLOSE;
-	if (asyncConnect) {
-	    infoPtr->flags |= SOCKET_ASYNC_CONNECT;
-	    infoPtr->selectEvents |= FD_CONNECT;
-	}
-
-  error:
-    if (addrlist != NULL) {
-	freeaddrinfo(addrlist);
-    }
-    if (myaddrlist != NULL) {
-	freeaddrinfo(myaddrlist);
-    }
-
+error:
     /*
      * Register for interest in events in the select mask. Note that this
      * automatically places the socket into non-blocking mode.
      */
 
-    if (infoPtr != NULL) {
-	ioctlsocket(sock, (long) FIONBIO, &flag);
+    if (connected) {
+	ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey);
+
+	ioctlsocket(infoPtr->sockets->fd, (long) FIONBIO, &flag);
 	SendMessage(tsdPtr->hwnd, SOCKET_SELECT, (WPARAM) SELECT,
 		(LPARAM) infoPtr);
-
-	return infoPtr;
+	return TCL_OK;
     }
 
     if (interp != NULL) {
         Tcl_SetObjResult(interp, Tcl_ObjPrintf(
-		"couldn't open socket: %s",
-		(errorMsg ? errorMsg : Tcl_PosixError(interp))));
+		"couldn't open socket: %s", Tcl_PosixError(interp)));
     }
 
-    if (sock != INVALID_SOCKET) {
-	closesocket(sock);
-    }
-    return NULL;
+    return TCL_ERROR;
 }
 
 /*
@@ -1390,18 +1406,57 @@ Tcl_OpenTcpClient(
 				 * asynchronously. */
 {
     SocketInfo *infoPtr;
-    char channelName[16 + TCL_INTEGER_SPACE];
+    const char *errorMsg = NULL;
+    struct addrinfo *addrlist = NULL;
+    struct addrinfo *myaddrlist = NULL;
+    char channelName[SOCK_CHAN_LENGTH];
 
     if (TclpHasSockets(interp) != TCL_OK) {
 	return NULL;
     }
 
     /*
-     * Create a new client socket and wrap it in a channel.
+     * Check that WinSock is initialized; do not call it if not, to prevent
+     * system crashes. This can happen at exit time if the exit handler for
+     * WinSock ran before other exit handlers that want to use sockets.
+     */
+
+    if (!SocketsEnabled()) {
+	return NULL;
+    }
+
+    /*
+     * Do the name lookups for the local and remote addresses.
      */
 
-    infoPtr = CreateClientSocket(interp, port, host, myaddr, myport, async);
-    if (infoPtr == NULL) {
+    if (!TclCreateSocketAddress(interp, &addrlist, host, port, 0, &errorMsg)
+            || !TclCreateSocketAddress(interp, &myaddrlist, myaddr, myport, 1,
+                    &errorMsg)) {
+        if (addrlist != NULL) {
+            freeaddrinfo(addrlist);
+        }
+        if (interp != NULL) {
+            Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+                    "couldn't open socket: %s", errorMsg));
+        }
+        return NULL;
+    }
+    printaddrinfolist(myaddrlist, "local");
+    printaddrinfolist(addrlist, "remote");
+
+    infoPtr = NewSocketInfo(INVALID_SOCKET);
+    infoPtr->addrlist = addrlist;
+    infoPtr->myaddrlist = myaddrlist;
+    if (async) {
+	infoPtr->flags |= SOCKET_ASYNC_CONNECT;
+    }
+
+    /*
+     * Create a new client socket and wrap it in a channel.
+     */
+    
+    if (CreateClientSocket(interp, infoPtr) != TCL_OK) {
+	TcpCloseProc(infoPtr, NULL);
 	return NULL;
     }
 
@@ -1444,7 +1499,7 @@ Tcl_MakeTcpClientChannel(
     ClientData sock)		/* The socket to wrap up into a channel. */
 {
     SocketInfo *infoPtr;
-    char channelName[16 + TCL_INTEGER_SPACE];
+    char channelName[SOCK_CHAN_LENGTH];
     ThreadSpecificData *tsdPtr;
 
     if (TclpHasSockets(NULL) != TCL_OK) {
@@ -1506,7 +1561,7 @@ Tcl_OpenTcpServer(
     unsigned short chosenport = 0;
     struct addrinfo *addrPtr;	/* Socket address to listen on. */
     SocketInfo *infoPtr = NULL;	/* The returned value. */
-    void *addrlist = NULL;
+    struct addrinfo *addrlist = NULL;
     char channelName[SOCK_CHAN_LENGTH];
     u_long flag = 1;		/* Indicates nonblocking mode. */
     const char *errorMsg = NULL;
@@ -1694,7 +1749,7 @@ TcpAccept(
     SocketInfo *newInfoPtr;
     SocketInfo *infoPtr = fds->infoPtr;
     int len = sizeof(addr);
-    char channelName[16 + TCL_INTEGER_SPACE];
+    char channelName[SOCK_CHAN_LENGTH];
     char host[NI_MAXHOST], port[NI_MAXSERV];
     ThreadSpecificData *tsdPtr = TclThreadDataKeyGet(&dataKey);
 
@@ -2512,10 +2567,12 @@ SocketProc(
 
     switch (message) {
     default:
+	    DEBUG("default");
 	return DefWindowProc(hwnd, message, wParam, lParam);
 	break;
 
     case WM_CREATE:
+	    DEBUG("CREATE");
 	/*
 	 * Store the initial tsdPtr, it's from a different thread, so it's not
 	 * directly accessible, but needed.
@@ -2531,10 +2588,12 @@ SocketProc(
 	break;
 
     case WM_DESTROY:
+	    DEBUG("DESTROY");
 	PostQuitMessage(0);
 	break;
 
     case SOCKET_MESSAGE:
+	    DEBUG("SOCKET_MESSAGE");
 	event = WSAGETSELECTEVENT(lParam);
 	error = WSAGETSELECTERROR(lParam);
 	socket = (SOCKET) wParam;
@@ -2549,6 +2608,11 @@ SocketProc(
 		infoPtr = infoPtr->nextPtr) {
 	    for (fds = infoPtr->sockets; fds != NULL; fds = fds->next) {
 		if (fds->fd == socket) {
+		    if (event & FD_READ) 
+			DEBUG("|->FD_READ");
+		    if (event & FD_WRITE) 
+			DEBUG("|->FD_WRITE");
+
 		    /*
 		     * Update the socket state.
 		     *
@@ -2558,19 +2622,22 @@ SocketProc(
 		     */
 
 		    if (event & FD_CLOSE) {
+			DEBUG("FD_CLOSE");
 			infoPtr->acceptEventCount = 0;
 			infoPtr->readyEvents &= ~(FD_WRITE|FD_ACCEPT);
 		    } else if (event & FD_ACCEPT) {
-			infoPtr->acceptEventCount++;
+			DEBUG("FD_ACCEPT");
+			    infoPtr->acceptEventCount++;
 		    }
 
 		    if (event & FD_CONNECT) {
+			DEBUG("FD_CONNECT");
 			/*
 			 * The socket is now connected, clear the async connect
 			 * flag.
 			 */
 
-			infoPtr->flags &= ~(SOCKET_ASYNC_CONNECT);
+			//infoPtr->flags &= ~(SOCKET_ASYNC_CONNECT);
 
 			/*
 			 * Remember any error that occurred so we can report
@@ -2582,15 +2649,17 @@ SocketProc(
 			    infoPtr->lastError = Tcl_GetErrno();
 			}
 		    }
-
+#if 0
 		    if (infoPtr->flags & SOCKET_ASYNC_CONNECT) {
-			infoPtr->flags &= ~(SOCKET_ASYNC_CONNECT);
+			DEBUG("SOCKET_ASYNC_CONNECT");
+			// infoPtr->flags &= ~(SOCKET_ASYNC_CONNECT);
 			if (error != ERROR_SUCCESS) {
 			    TclWinConvertError((DWORD) error);
 			    infoPtr->lastError = Tcl_GetErrno();
 			}
 			infoPtr->readyEvents |= FD_WRITE;
 		    }
+#endif
 		    infoPtr->readyEvents |= event;
 
 		    /*
@@ -2607,10 +2676,12 @@ SocketProc(
 	break;
 
     case SOCKET_SELECT:
+	    DEBUG("SOCKET_SELECT");
 	infoPtr = (SocketInfo *) lParam;
 	for (fds = infoPtr->sockets; fds != NULL; fds = fds->next) {
 	    infoPtr = (SocketInfo *) lParam;
 	    if (wParam == SELECT) {
+		DEBUG("SELECT");
 		WSAAsyncSelect(fds->fd, hwnd,
 			SOCKET_MESSAGE, infoPtr->selectEvents);
 	    } else {
@@ -2618,12 +2689,14 @@ SocketProc(
 		 * Clear the selection mask
 		 */
 
+		DEBUG("!SELECT");
 		WSAAsyncSelect(fds->fd, hwnd, 0, 0);
 	    }
 	}
 	break;
 
     case SOCKET_TERMINATE:
+	    DEBUG("SOCKET_TERMINATE");
 	DestroyWindow(hwnd);
 	break;
     }
-- 
cgit v0.12