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