summaryrefslogtreecommitdiffstats
path: root/generic/tclIO.c
diff options
context:
space:
mode:
authorpooryorick <com.digitalsmarties@pooryorick.com>2019-04-27 07:19:49 (GMT)
committerpooryorick <com.digitalsmarties@pooryorick.com>2019-04-27 07:19:49 (GMT)
commit36073e502b5ea157b656d98ea6c86287f5fc855d (patch)
tree77c79ab55f98d4aa4ecf0c0422d5ff9593f7c09b /generic/tclIO.c
parent35396a7f5c0759d9cf20079bdf1700d0e55dba78 (diff)
downloadtcl-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/tclIO.c')
-rw-r--r--generic/tclIO.c38
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);
}
/*