summaryrefslogtreecommitdiffstats
path: root/unix
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2020-03-31 20:04:53 (GMT)
committersebres <sebres@users.sourceforge.net>2020-03-31 20:04:53 (GMT)
commita43b4a80fa5e24ec35b325b0e5709033b40226e9 (patch)
treec8b3b7176454fa07ca716aabd29fc83d47ac8809 /unix
parent4258dcc3acd1ffc9d3dec78cb9eef89ace9ac7f5 (diff)
downloadtcl-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.c49
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.