diff options
author | sebres <sebres@users.sourceforge.net> | 2020-03-31 20:04:53 (GMT) |
---|---|---|
committer | sebres <sebres@users.sourceforge.net> | 2020-03-31 20:04:53 (GMT) |
commit | a43b4a80fa5e24ec35b325b0e5709033b40226e9 (patch) | |
tree | c8b3b7176454fa07ca716aabd29fc83d47ac8809 /unix | |
parent | 4258dcc3acd1ffc9d3dec78cb9eef89ace9ac7f5 (diff) | |
download | tcl-a43b4a80fa5e24ec35b325b0e5709033b40226e9.zip tcl-a43b4a80fa5e24ec35b325b0e5709033b40226e9.tar.gz tcl-a43b4a80fa5e24ec35b325b0e5709033b40226e9.tar.bz2 |
fixes [f583715154] - tclUnixSock.c: introduced ThreadActionProc considering a transfer of async-connecting channel between threads; cherry-picked some prevention against invalid thread owner addressed in [815e246806]
Diffstat (limited to 'unix')
-rw-r--r-- | unix/tclUnixSock.c | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c index 1901c8b..4d7a8fb 100644 --- a/unix/tclUnixSock.c +++ b/unix/tclUnixSock.c @@ -118,6 +118,7 @@ struct TcpState { * 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); @@ -134,6 +135,7 @@ static int TcpInputProc(ClientData instanceData, char *buf, int toRead, int *errorCode); static int TcpOutputProc(ClientData instanceData, const char *buf, int toWrite, int *errorCode); +static void TcpThreadActionProc(ClientData instanceData, int action); static void TcpWatchProc(ClientData instanceData, int mask); static int WaitForConnect(TcpState *statePtr, int *errorCodePtr); static void WrapNotify(ClientData clientData, int mask); @@ -159,7 +161,7 @@ static const Tcl_ChannelType tcpChannelType = { NULL, /* flush proc. */ NULL, /* handler proc. */ NULL, /* wide seek proc. */ - NULL, /* thread action proc. */ + TcpThreadActionProc, /* thread action proc. */ NULL /* truncate proc. */ }; @@ -958,6 +960,51 @@ TcpGetOptionProc( /* * ---------------------------------------------------------------------- * + * TcpThreadActionProc -- + * + * Handles detach/attach for asynchronously connecting socket. + * + * Reassigning the file handler associated with thread-related channel + * notification, responsible for callbacks (signaling that asynchronous + * connection attempt has succeeded or failed). + * + * Results: + * None. + * + * ---------------------------------------------------------------------- + */ + +static void +TcpThreadActionProc( + ClientData instanceData, + int action) +{ + TcpState *statePtr = (TcpState *)instanceData; + + if (GOT_BITS(statePtr->flags, TCP_ASYNC_CONNECT)) { + /* + * Async-connecting socket must get reassigned handler if it have been + * transferred to another thread. Remove the handler if the socket is + * not managed by this thread anymore and create new handler (TSD related) + * so the callback will run in the correct thread, bug [f583715154]. + */ + switch (action) { + case TCL_CHANNEL_THREAD_REMOVE: + CLEAR_BITS(statePtr->flags, TCP_ASYNC_PENDING); + Tcl_DeleteFileHandler(statePtr->fds.fd); + break; + case TCL_CHANNEL_THREAD_INSERT: + Tcl_CreateFileHandler(statePtr->fds.fd, + TCL_WRITABLE | TCL_EXCEPTION, TcpAsyncCallback, statePtr); + SET_BITS(statePtr->flags, TCP_ASYNC_PENDING); + break; + } + } +} + +/* + * ---------------------------------------------------------------------- + * * TcpWatchProc -- * * Initialize the notifier to watch the fd from this channel. |