diff options
| author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2024-05-29 09:44:42 (GMT) |
|---|---|---|
| committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2024-05-29 09:44:42 (GMT) |
| commit | 9c67485399e06d2ff47ac586c855151a8b59b89a (patch) | |
| tree | 45027a5ff506315533004894404c61f22b48b014 /generic/tclIO.c | |
| parent | 575f460ac1d75b9043d9469e5e8016b6a030ed79 (diff) | |
| parent | 640db582e6fa3d39d1ea265cca917c685b6fc6fa (diff) | |
| download | tcl-9c67485399e06d2ff47ac586c855151a8b59b89a.zip tcl-9c67485399e06d2ff47ac586c855151a8b59b89a.tar.gz tcl-9c67485399e06d2ff47ac586c855151a8b59b89a.tar.bz2 | |
Fix [18f4a94d03], by reverting [9bcec7cd880540c3], which caused it.
See [https://core.tcl-lang.org/tcl/wiki?name=Rationale+for+rollback+of+refchan+event+generation+in+core|here] for motivation, approved by the TCT.
Diffstat (limited to 'generic/tclIO.c')
| -rw-r--r-- | generic/tclIO.c | 91 |
1 files changed, 21 insertions, 70 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c index 01fd586..0cf100c 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -168,7 +168,6 @@ static int CheckForDeadChannel(Tcl_Interp *interp, static void CheckForStdChannelsBeingClosed(Tcl_Channel chan); static void CleanupChannelHandlers(Tcl_Interp *interp, Channel *chanPtr); -static void CleanupTimerHandler(ChannelState *statePtr); static int CloseChannel(Tcl_Interp *interp, Channel *chanPtr, int errorCode); static int CloseChannelPart(Tcl_Interp *interp, Channel *chanPtr, @@ -3575,11 +3574,6 @@ Tcl_Close( Tcl_ClearChannelHandlers(chan); /* - * Cancel any outstanding timer. - */ - DeleteTimerHandler(statePtr); - - /* * Invoke the registered close callbacks and delete their records. */ @@ -8793,7 +8787,6 @@ UpdateInterest( { ChannelState *statePtr = chanPtr->state; /* State info for channel */ - ChannelBuffer *bufPtr = statePtr->outQueueHead; int mask = statePtr->interestMask; if (chanPtr->typePtr == NULL) { @@ -8871,20 +8864,6 @@ UpdateInterest( } } } - - if (!statePtr->timer - && (mask & TCL_WRITABLE) - && GotFlag(statePtr, CHANNEL_NONBLOCKING) - && bufPtr - && !IsBufferEmpty(bufPtr) - && !IsBufferFull(bufPtr) - ) { - TclChannelPreserve((Tcl_Channel)chanPtr); - statePtr->timerChanPtr = chanPtr; - statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, - ChannelTimerProc,chanPtr); - } - ChanWatch(chanPtr, mask); } @@ -8913,72 +8892,44 @@ ChannelTimerProc( /* State info for channel */ ChannelState *statePtr = chanPtr->state; - /* TclChannelPreserve() must be called before the current function was - * scheduled, is already in effect. In this function it guards against - * deallocation in Tcl_NotifyChannel and also keps the channel preserved - * until ChannelTimerProc is later called again. - */ - if (chanPtr->typePtr == NULL) { - CleanupTimerHandler(statePtr); - } else { - Tcl_Preserve(statePtr); statePtr->timer = NULL; - if (statePtr->interestMask & TCL_WRITABLE - && GotFlag(statePtr, CHANNEL_NONBLOCKING) - && !GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { + TclChannelRelease((Tcl_Channel)statePtr->timerChanPtr); + statePtr->timerChanPtr = NULL; + } else { + if (!GotFlag(statePtr, CHANNEL_NEED_MORE_DATA) + && (statePtr->interestMask & TCL_READABLE) + && (statePtr->inQueueHead != NULL) + && IsBufferReady(statePtr->inQueueHead)) { /* * Restart the timer in case a channel handler reenters the event loop * before UpdateInterest gets called by Tcl_NotifyChannel. */ statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, ChannelTimerProc,chanPtr); - Tcl_NotifyChannel((Tcl_Channel) chanPtr, TCL_WRITABLE); + Tcl_Preserve(statePtr); + Tcl_NotifyChannel((Tcl_Channel) chanPtr, TCL_READABLE); + Tcl_Release(statePtr); } else { - /* The channel may have just been closed from within Tcl_NotifyChannel */ - if (!GotFlag(statePtr, CHANNEL_INCLOSE)) { - if (!GotFlag(statePtr, CHANNEL_NEED_MORE_DATA) - && (statePtr->interestMask & TCL_READABLE) - && (statePtr->inQueueHead != NULL) - && IsBufferReady(statePtr->inQueueHead)) { - /* - * Restart the timer in case a channel handler reenters the event loop - * before UpdateInterest gets called by Tcl_NotifyChannel. - */ - - statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, - ChannelTimerProc,chanPtr); - Tcl_NotifyChannel((Tcl_Channel) chanPtr, TCL_READABLE); - } else { - CleanupTimerHandler(statePtr); - UpdateInterest(chanPtr); - } - } else { - CleanupTimerHandler(statePtr); - } + statePtr->timer = NULL; + UpdateInterest(chanPtr); + TclChannelRelease((Tcl_Channel)statePtr->timerChanPtr); + statePtr->timerChanPtr = NULL; } - Tcl_Release(statePtr); } } static void DeleteTimerHandler( - ChannelState *statePtr -) + ChannelState *statePtr) { if (statePtr->timer != NULL) { Tcl_DeleteTimerHandler(statePtr->timer); - CleanupTimerHandler(statePtr); + statePtr->timer = NULL; + TclChannelRelease((Tcl_Channel)statePtr->timerChanPtr); + statePtr->timerChanPtr = NULL; } } -static void -CleanupTimerHandler( - ChannelState *statePtr -){ - TclChannelRelease((Tcl_Channel)statePtr->timerChanPtr); - statePtr->timer = NULL; - statePtr->timerChanPtr = NULL; -} /* *---------------------------------------------------------------------- @@ -9957,7 +9908,7 @@ CopyData( || (csPtr->toRead > (Tcl_WideInt)csPtr->bufSize)) { sizeb = csPtr->bufSize; } else { - sizeb = (int) csPtr->toRead; + sizeb = csPtr->toRead; } if (inBinary || sameEncoding) { @@ -10306,7 +10257,7 @@ DoRead( while (!bufPtr || /* We got no buffer! OR */ (!IsBufferFull(bufPtr) && /* Our buffer has room AND */ - (BytesLeft(bufPtr) < bytesToRead))) { + ((Tcl_Size) BytesLeft(bufPtr) < bytesToRead))) { /* Not enough bytes in it yet * to fill the dst */ int code; @@ -10454,7 +10405,7 @@ DoRead( == (CHANNEL_EOF|CHANNEL_BLOCKED))); UpdateInterest(chanPtr); TclChannelRelease((Tcl_Channel)chanPtr); - return (int)(p - dst); + return (Tcl_Size)(p - dst); } /* |
