summaryrefslogtreecommitdiffstats
path: root/generic/tclIO.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2022-04-26 07:29:02 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2022-04-26 07:29:02 (GMT)
commita4c35fb82f99d990ca1ef877cb9917c7f55151ff (patch)
treecdd02327448cf2c0393cbf3cea4fd48bb17e52c4 /generic/tclIO.c
parent81a213ed4ce77b15fbc6d5d97cc1235b689ad482 (diff)
parente12b1646c6f675cf09d5f1a72d4ecdffa5da7396 (diff)
downloadtcl-a4c35fb82f99d990ca1ef877cb9917c7f55151ff.zip
tcl-a4c35fb82f99d990ca1ef877cb9917c7f55151ff.tar.gz
tcl-a4c35fb82f99d990ca1ef877cb9917c7f55151ff.tar.bz2
Merge 8.7
Diffstat (limited to 'generic/tclIO.c')
-rw-r--r--generic/tclIO.c51
1 files changed, 31 insertions, 20 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c
index 2d2f2fc..b504369 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.c
@@ -103,7 +103,7 @@ typedef struct CopyState {
Tcl_Interp *interp; /* Interp that started the copy. */
Tcl_Obj *cmdPtr; /* Command to be invoked at completion. */
int bufSize; /* Size of appended buffer. */
- char buffer[1]; /* Copy buffer, this must be the last
+ char buffer[TCLFLEXARRAY]; /* Copy buffer, this must be the last
* field. */
} CopyState;
@@ -2711,6 +2711,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
@@ -2879,8 +2880,8 @@ FlushChannel(
* queued.
*/
- DiscardOutputQueued(statePtr);
ReleaseChannelBuffer(bufPtr);
+ DiscardOutputQueued(statePtr);
break;
} else {
/*
@@ -2891,20 +2892,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". */
/*
@@ -4363,7 +4376,6 @@ Write(
bufPtr->nextAdded += saved;
saved = 0;
}
- PreserveChannelBuffer(bufPtr);
dst = InsertPoint(bufPtr);
dstLen = SpaceLeft(bufPtr);
@@ -4383,7 +4395,6 @@ Write(
* We're reading from invalid/incomplete UTF-8.
*/
- ReleaseChannelBuffer(bufPtr);
if (total == 0) {
Tcl_SetErrno(EILSEQ);
return -1;
@@ -4457,7 +4468,6 @@ Write(
if (IsBufferFull(bufPtr)) {
if (FlushChannel(NULL, chanPtr, 0) != 0) {
- ReleaseChannelBuffer(bufPtr);
return -1;
}
flushed += statePtr->bufSize;
@@ -4477,7 +4487,6 @@ Write(
needNlFlush = 0;
}
}
- ReleaseChannelBuffer(bufPtr);
}
if ((flushed < total) && (GotFlag(statePtr, CHANNEL_UNBUFFERED) ||
(needNlFlush && GotFlag(statePtr, CHANNEL_LINEBUFFERED)))) {
@@ -6961,15 +6970,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;
}
@@ -9246,7 +9257,7 @@ TclCopyChannel(
* completed.
*/
- csPtr = (CopyState *)ckalloc(sizeof(CopyState) + !moveBytes * inStatePtr->bufSize);
+ csPtr = (CopyState *)ckalloc(offsetof(CopyState, buffer) + 1U + !moveBytes * inStatePtr->bufSize);
csPtr->bufSize = !moveBytes * inStatePtr->bufSize;
csPtr->readPtr = inPtr;
csPtr->writePtr = outPtr;
@@ -11068,7 +11079,7 @@ FixLevelCode(
* information. Hence an error means that we've got serious breakage.
*/
- res = Tcl_ListObjGetElements(NULL, msg, &lc, &lv);
+ res = TclListObjGetElements(NULL, msg, &lc, &lv);
if (res != TCL_OK) {
Tcl_Panic("Tcl_SetChannelError: bad syntax of message");
}