diff options
| author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2022-04-26 07:19:51 (GMT) |
|---|---|---|
| committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2022-04-26 07:19:51 (GMT) |
| commit | 77a24f6300a1d703cbf6d3173563eec904a56b2f (patch) | |
| tree | 1c73d3154d6139a0d4954a1325f445c47b88a749 /generic/tclIO.c | |
| parent | aabe2cbb3311da41bfe8cf2f7a421303757ea1d2 (diff) | |
| parent | 43b9a878d5dd76a2a90477dc723a81ffb7897043 (diff) | |
| download | tcl-77a24f6300a1d703cbf6d3173563eec904a56b2f.zip tcl-77a24f6300a1d703cbf6d3173563eec904a56b2f.tar.gz tcl-77a24f6300a1d703cbf6d3173563eec904a56b2f.tar.bz2 | |
Merge 9.0
Diffstat (limited to 'generic/tclIO.c')
| -rw-r--r-- | generic/tclIO.c | 45 |
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; } |
