Index: generic/tclIO.c ================================================================== --- generic/tclIO.c +++ generic/tclIO.c @@ -3249,10 +3249,14 @@ prevCSPtr->nextCSPtr = statePtr->nextCSPtr; } statePtr->nextCSPtr = NULL; + /* Channel is not managed by any thread */ + statePtr->managingThread = NULL; + UpdateInterest(chanPtr); + /* * TIP #218, Channel Thread Actions * For all transformations and the base channel. */ @@ -3338,10 +3342,11 @@ * Note: 'Tcl_GetCurrentThread' returns sensible values even for * a non-threaded core. */ statePtr->managingThread = Tcl_GetCurrentThread(); + UpdateInterest(chanPtr); /* * TIP #218, Channel Thread Actions * For all transformations and the base channel. */ Index: unix/tclUnixSock.c ================================================================== --- unix/tclUnixSock.c +++ unix/tclUnixSock.c @@ -127,10 +127,11 @@ /* * Static routines for this file: */ +static void TcpAsyncCallback(ClientData clientData, int mask); static int TcpConnect(Tcl_Interp *interp, TcpState *state); static void TcpAccept(ClientData data, int mask); static int TcpBlockModeProc(ClientData data, int mode); static int TcpCloseProc(ClientData instanceData, Tcl_Interp *interp); @@ -1060,10 +1061,36 @@ * Async sockets use a FileHandler internally while connecting, so we * need to cache this request until the connection has succeeded. */ statePtr->filehandlers = mask; + + /* + * Remove the FileHandler if the socket is not managed by any thread + * Otherwise the handler is likely to run in the wrong thread, + * possibly leading to all kinds of ugly issues. + */ + + if (!Tcl_GetChannelThread(statePtr->channel)) { + CLEAR_BITS(statePtr->flags, TCP_ASYNC_PENDING); + Tcl_DeleteFileHandler(statePtr->fds.fd); + } + } else if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) { + + /* + * An async socket without an async event pending must just have been + * transferred from another thread. Reestablish the FileHandler here + * so the callback will run in the correct thread. + */ + + Tcl_CreateFileHandler(statePtr->fds.fd, + TCL_WRITABLE | TCL_EXCEPTION, TcpAsyncCallback, + statePtr); + SET_BITS(statePtr->flags, TCP_ASYNC_PENDING); + + /* Cache the current request until the connection has succeeded */ + statePtr->filehandlers = mask; } else if (mask) { /* * Whether it is a bug or feature or otherwise, it is a fact of life * that on at least some Linux kernels select() fails to report that a