diff options
author | pooryorick <com.digitalsmarties@pooryorick.com> | 2019-04-27 07:19:49 (GMT) |
---|---|---|
committer | pooryorick <com.digitalsmarties@pooryorick.com> | 2019-04-27 07:19:49 (GMT) |
commit | 36073e502b5ea157b656d98ea6c86287f5fc855d (patch) | |
tree | 77c79ab55f98d4aa4ecf0c0422d5ff9593f7c09b /generic | |
parent | 35396a7f5c0759d9cf20079bdf1700d0e55dba78 (diff) | |
download | tcl-36073e502b5ea157b656d98ea6c86287f5fc855d.zip tcl-36073e502b5ea157b656d98ea6c86287f5fc855d.tar.gz tcl-36073e502b5ea157b656d98ea6c86287f5fc855d.tar.bz2 |
Fix for de232b49f2, write-only nonblocking refchan and Tcl internal buffers.
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclIO.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c index cf91307..4775820 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -3463,6 +3463,11 @@ Tcl_Close( Tcl_ClearChannelHandlers(chan); /* + * Cancel any outstanding timer. + */ + Tcl_DeleteTimerHandler(statePtr->timer); + + /* * Invoke the registered close callbacks and delete their records. */ @@ -4447,6 +4452,8 @@ Write( } } + UpdateInterest(chanPtr); + return total; } @@ -8475,9 +8482,9 @@ UpdateInterest( * * - Tcl drops READABLE here, because it has data in its own * buffers waiting to be read by the extension. - * - A READABLE event is syntesized via timer. + * - A READABLE event is synthesized via timer. * - The OS still reports the EXCEPTION condition on the file. - * - And the extension gets the EXCPTION event first, and handles + * - And the extension gets the EXCEPTION event first, and handles * this as EOF. * * End result ==> Premature end of reading from a file. @@ -8503,6 +8510,16 @@ UpdateInterest( } } } + + if (statePtr->timer == NULL + && mask & TCL_WRITABLE + && GotFlag(statePtr, CHANNEL_NONBLOCKING)) { + + statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, + ChannelTimerProc,chanPtr); + } + + ChanWatch(chanPtr, mask); } @@ -8531,6 +8548,19 @@ ChannelTimerProc( ChannelState *statePtr = chanPtr->state; /* State info for channel */ + Tcl_Preserve(statePtr); + statePtr->timer = NULL; + if (statePtr->interestMask & TCL_WRITABLE + && GotFlag(statePtr, CHANNEL_NONBLOCKING)) { + /* + * 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); + } + if (!GotFlag(statePtr, CHANNEL_NEED_MORE_DATA) && (statePtr->interestMask & TCL_READABLE) && (statePtr->inQueueHead != NULL) @@ -8542,13 +8572,11 @@ ChannelTimerProc( statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME, ChannelTimerProc,chanPtr); - Tcl_Preserve(statePtr); Tcl_NotifyChannel((Tcl_Channel) chanPtr, TCL_READABLE); - Tcl_Release(statePtr); } else { - statePtr->timer = NULL; UpdateInterest(chanPtr); } + Tcl_Release(statePtr); } /* |