summaryrefslogtreecommitdiffstats
path: root/generic/tclIO.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2019-05-10 07:46:32 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2019-05-10 07:46:32 (GMT)
commit7b90ffbb489e5b0b09f23a6296f69f070127fd57 (patch)
treeb4b8b874d4101f811de99438daa6d037daa506f1 /generic/tclIO.c
parentf9eb1833d2785265d8dc52992750ef10d9cc1c19 (diff)
parentb1139d3d2099aad8ad1981deaa0f689e1b4c322a (diff)
downloadtcl-7b90ffbb489e5b0b09f23a6296f69f070127fd57.zip
tcl-7b90ffbb489e5b0b09f23a6296f69f070127fd57.tar.gz
tcl-7b90ffbb489e5b0b09f23a6296f69f070127fd57.tar.bz2
merge 8.7
Diffstat (limited to 'generic/tclIO.c')
-rw-r--r--generic/tclIO.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c
index 54742b3..40b32cc 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
+ && mask & TCL_WRITABLE
+ && GotFlag(statePtr, CHANNEL_NONBLOCKING)) {
+
+ statePtr->timer = Tcl_CreateTimerHandler(SYNTHETIC_EVENT_TIME,
+ ChannelTimerProc,chanPtr);
+ }
+
+
ChanWatch(chanPtr, mask);
}
@@ -8531,6 +8548,21 @@ ChannelTimerProc(
ChannelState *statePtr = chanPtr->state;
/* State info for channel */
+ Tcl_Preserve(statePtr);
+ statePtr->timer = NULL;
+ if (statePtr->interestMask & TCL_WRITABLE
+ && GotFlag(statePtr, CHANNEL_NONBLOCKING)
+ && !GotFlag(statePtr, BG_FLUSH_SCHEDULED)
+ ) {
+ /*
+ * 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 +8574,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);
}
/*