Tcl Source Code

Artifact [085d26018a]
Login

Artifact 085d26018a3df2447faa3e58715220bbaedb7062eece7b3ea91a66ff8009e707:

Attachment "patch.txt" to ticket [f583715154] added by sbron 2020-01-10 12:14:48. (unpublished)
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