diff options
Diffstat (limited to 'unix/tclUnixSock.c')
| -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.  | 
