diff options
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 d65f6e6..edce09b 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -3219,6 +3219,9 @@ CutChannel( */ ChanThreadAction((Channel *) chan, TCL_CHANNEL_THREAD_REMOVE); + + /* Channel is not managed by any thread */ + statePtr->managingThread = NULL; } void @@ -3263,6 +3266,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; } /* @@ -8390,6 +8396,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. @@ -8423,6 +8436,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; + } } /* @@ -8440,6 +8460,7 @@ Tcl_NotifyChannel( UpdateInterest(chanPtr); } +done: Tcl_Release(statePtr); TclChannelRelease(channel); @@ -8939,6 +8960,11 @@ TclChannelEventScriptInvoker( int result; /* Result of call to eval script. */ /* + * 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. |
