summaryrefslogtreecommitdiffstats
path: root/unix/tclUnixSock.c
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2020-04-01 12:37:52 (GMT)
committerdgp <dgp@users.sourceforge.net>2020-04-01 12:37:52 (GMT)
commit8ab2c9cf62965aff558352a4f02db0eb16c3e3b6 (patch)
tree66bb60cf1fdd4d321fce40ac56181630eb073968 /unix/tclUnixSock.c
parent6a1a8526f171c8a9a808de4f653436d86ecfc8b3 (diff)
parent14c6f5491be3cd441df1f7142510835c67f78e9d (diff)
downloadtcl-8ab2c9cf62965aff558352a4f02db0eb16c3e3b6.zip
tcl-8ab2c9cf62965aff558352a4f02db0eb16c3e3b6.tar.gz
tcl-8ab2c9cf62965aff558352a4f02db0eb16c3e3b6.tar.bz2
merge 8.7
Diffstat (limited to 'unix/tclUnixSock.c')
-rw-r--r--unix/tclUnixSock.c49
1 files changed, 48 insertions, 1 deletions
diff --git a/unix/tclUnixSock.c b/unix/tclUnixSock.c
index 67f8614..1bbf8e1 100644
--- a/unix/tclUnixSock.c
+++ b/unix/tclUnixSock.c
@@ -129,6 +129,7 @@ struct TcpState {
* Static routines for this file:
*/
+static void TcpAsyncCallback(void *clientData, int mask);
static int TcpConnect(Tcl_Interp *interp, TcpState *state);
static void TcpAccept(void *data, int mask);
static int TcpBlockModeProc(void *data, int mode);
@@ -145,6 +146,7 @@ static int TcpInputProc(void *instanceData, char *buf,
int toRead, int *errorCode);
static int TcpOutputProc(void *instanceData,
const char *buf, int toWrite, int *errorCode);
+static void TcpThreadActionProc(void *instanceData, int action);
static void TcpWatchProc(void *instanceData, int mask);
static int WaitForConnect(TcpState *statePtr, int *errorCodePtr);
static void WrapNotify(void *clientData, int mask);
@@ -170,7 +172,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. */
};
@@ -980,6 +982,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(
+ void *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.