summaryrefslogtreecommitdiffstats
path: root/generic/tclIO.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2024-05-29 09:44:42 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2024-05-29 09:44:42 (GMT)
commit9c67485399e06d2ff47ac586c855151a8b59b89a (patch)
tree45027a5ff506315533004894404c61f22b48b014 /generic/tclIO.c
parent575f460ac1d75b9043d9469e5e8016b6a030ed79 (diff)
parent640db582e6fa3d39d1ea265cca917c685b6fc6fa (diff)
downloadtcl-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.c91
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);
}
/*