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 /generic/tclIO.c | |
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 'generic/tclIO.c')
-rw-r--r-- | generic/tclIO.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c index 67264a0..ab8d8ac 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -3189,6 +3189,9 @@ CutChannel( */ ChanThreadAction((Channel *) chan, TCL_CHANNEL_THREAD_REMOVE); + + /* Channel is not managed by any thread */ + statePtr->managingThread = NULL; } void @@ -3233,6 +3236,9 @@ Tcl_CutChannel( for (; chanPtr != NULL ; chanPtr = chanPtr->upChanPtr) { ChanThreadAction(chanPtr, TCL_CHANNEL_THREAD_REMOVE); } + + /* Channel is not managed by any thread */ + statePtr->managingThread = NULL; } /* @@ -8382,6 +8388,13 @@ Tcl_NotifyChannel( Tcl_Preserve(statePtr); /* + * Avoid processing if the channel owner has been changed. + */ + if (statePtr->managingThread != Tcl_GetCurrentThread()) { + goto done; + } + + /* * If we are flushing in the background, be sure to call FlushChannel for * writable events. Note that we have to discard the writable event so we * don't call any write handlers before the flush is complete. @@ -8415,6 +8428,13 @@ Tcl_NotifyChannel( } else { chPtr = chPtr->nextPtr; } + + /* + * Stop if the channel owner has been changed in-between. + */ + if (chanPtr->state->managingThread != Tcl_GetCurrentThread()) { + goto done; + } } /* @@ -8432,6 +8452,7 @@ Tcl_NotifyChannel( UpdateInterest(chanPtr); } +done: Tcl_Release(statePtr); TclChannelRelease(channel); @@ -8909,6 +8930,11 @@ TclChannelEventScriptInvoker( interp = esPtr->interp; /* + * Be sure event executed in managed channel (covering bugs similar [f583715154]). + */ + assert(chanPtr->state->managingThread == Tcl_GetCurrentThread()); + + /* * We must preserve the interpreter so we can report errors on it later. * Note that we do not need to preserve the channel because that is done * by Tcl_NotifyChannel before calling channel handlers. |