Tcl Source Code

Attachment Details
Login
Overview

Artifact ID: 21bd60234fc5979cbd21fa982309292db957cc13b521182b30d0800fb443e0ba
Ticket: f583715154c6f33d621418e8c9f6dfae5cc5ebc4
Date: 2020-01-10 12:14:48
User: sbron
Artifact Attached: 085d26018a3df2447faa3e58715220bbaedb7062eece7b3ea91a66ff8009e707
Filename:patch.txt
Description:Proposal for a fix.
Content:
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
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