summaryrefslogtreecommitdiffstats
path: root/generic/tclIO.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2022-04-26 07:19:51 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2022-04-26 07:19:51 (GMT)
commit77a24f6300a1d703cbf6d3173563eec904a56b2f (patch)
tree1c73d3154d6139a0d4954a1325f445c47b88a749 /generic/tclIO.c
parentaabe2cbb3311da41bfe8cf2f7a421303757ea1d2 (diff)
parent43b9a878d5dd76a2a90477dc723a81ffb7897043 (diff)
downloadtcl-77a24f6300a1d703cbf6d3173563eec904a56b2f.zip
tcl-77a24f6300a1d703cbf6d3173563eec904a56b2f.tar.gz
tcl-77a24f6300a1d703cbf6d3173563eec904a56b2f.tar.bz2
Merge 9.0
Diffstat (limited to 'generic/tclIO.c')
-rw-r--r--generic/tclIO.c45
1 files changed, 28 insertions, 17 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c
index 98675da..57e1a66 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.c
@@ -2685,6 +2685,7 @@ FlushChannel(
int wroteSome = 0; /* Set to one if any data was written to the
* driver. */
+ int bufExists;
/*
* Prevent writing on a dead channel -- a channel that has been closed but
* not yet deallocated. This can occur if the exit handler for the channel
@@ -2853,8 +2854,8 @@ FlushChannel(
* queued.
*/
- DiscardOutputQueued(statePtr);
ReleaseChannelBuffer(bufPtr);
+ DiscardOutputQueued(statePtr);
break;
} else {
/*
@@ -2865,20 +2866,32 @@ FlushChannel(
wroteSome = 1;
}
- bufPtr->nextRemoved += written;
+ bufExists = bufPtr->refCount > 1;
+ ReleaseChannelBuffer(bufPtr);
+ if (bufExists) {
+ /* There is still a reference to this buffer other than the one
+ * this routine just released, meaning that final cleanup of the
+ * buffer hasn't been ordered by, e.g. by a reflected channel
+ * closing the channel from within one of its handler scripts (not
+ * something one would expecte, but it must be considered). Normal
+ * operations on the buffer can proceed.
+ */
- /*
- * If this buffer is now empty, recycle it.
- */
+ bufPtr->nextRemoved += written;
- if (IsBufferEmpty(bufPtr)) {
- statePtr->outQueueHead = bufPtr->nextPtr;
- if (statePtr->outQueueHead == NULL) {
- statePtr->outQueueTail = NULL;
+ /*
+ * If this buffer is now empty, recycle it.
+ */
+
+ if (IsBufferEmpty(bufPtr)) {
+ statePtr->outQueueHead = bufPtr->nextPtr;
+ if (statePtr->outQueueHead == NULL) {
+ statePtr->outQueueTail = NULL;
+ }
+ RecycleBuffer(statePtr, bufPtr, 0);
}
- RecycleBuffer(statePtr, bufPtr, 0);
}
- ReleaseChannelBuffer(bufPtr);
+
} /* Closes "while". */
/*
@@ -4329,7 +4342,6 @@ Write(
bufPtr->nextAdded += saved;
saved = 0;
}
- PreserveChannelBuffer(bufPtr);
dst = InsertPoint(bufPtr);
dstLen = SpaceLeft(bufPtr);
@@ -4349,7 +4361,6 @@ Write(
* We're reading from invalid/incomplete UTF-8.
*/
- ReleaseChannelBuffer(bufPtr);
if (total == 0) {
Tcl_SetErrno(EILSEQ);
return -1;
@@ -4423,7 +4434,6 @@ Write(
if (IsBufferFull(bufPtr)) {
if (FlushChannel(NULL, chanPtr, 0) != 0) {
- ReleaseChannelBuffer(bufPtr);
return -1;
}
flushed += statePtr->bufSize;
@@ -4443,7 +4453,6 @@ Write(
needNlFlush = 0;
}
}
- ReleaseChannelBuffer(bufPtr);
}
if ((flushed < total) && (GotFlag(statePtr, CHANNEL_UNBUFFERED) ||
(needNlFlush && GotFlag(statePtr, CHANNEL_LINEBUFFERED)))) {
@@ -6931,15 +6940,17 @@ GetInput(
PreserveChannelBuffer(bufPtr);
nread = ChanRead(chanPtr, InsertPoint(bufPtr), toRead);
+ ReleaseChannelBuffer(bufPtr);
if (nread < 0) {
result = Tcl_GetErrno();
} else {
result = 0;
- bufPtr->nextAdded += nread;
+ if (statePtr->inQueueTail != NULL) {
+ statePtr->inQueueTail->nextAdded += nread;
+ }
}
- ReleaseChannelBuffer(bufPtr);
return result;
}