diff options
author | dgp <dgp@users.sourceforge.net> | 2014-04-21 20:01:49 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2014-04-21 20:01:49 (GMT) |
commit | cff1d5a3e7658bac7935cd60c96b85de225ed46e (patch) | |
tree | 1cafbbde11aea4a2ecdb5142e57feefe56292331 /generic/tclIO.c | |
parent | 1fa3d23817b3242fb5a8cad38f75b2d4b9f6f1f5 (diff) | |
parent | a07adf4d6d28771d9aa74ef06526e5fb3035f5c1 (diff) | |
download | tcl-cff1d5a3e7658bac7935cd60c96b85de225ed46e.zip tcl-cff1d5a3e7658bac7935cd60c96b85de225ed46e.tar.gz tcl-cff1d5a3e7658bac7935cd60c96b85de225ed46e.tar.bz2 |
merge 8.5
Diffstat (limited to 'generic/tclIO.c')
-rw-r--r-- | generic/tclIO.c | 50 |
1 files changed, 42 insertions, 8 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c index 2b0a28b..bffdae4 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -164,6 +164,8 @@ typedef struct CloseCallback { */ static ChannelBuffer * AllocChannelBuffer(int length); +static void PreserveChannelBuffer(ChannelBuffer *bufPtr); +static void ReleaseChannelBuffer(ChannelBuffer *bufPtr); static void ChannelTimerProc(ClientData clientData); static int CheckChannelErrors(ChannelState *statePtr, int direction); @@ -352,6 +354,7 @@ ChanRead( int *errnoPtr) { if (WillRead(chanPtr) < 0) { + *errnoPtr = Tcl_GetErrno(); return -1; } @@ -2216,8 +2219,26 @@ AllocChannelBuffer( bufPtr->nextRemoved = BUFFER_PADDING; bufPtr->bufLength = length + BUFFER_PADDING; bufPtr->nextPtr = NULL; + bufPtr->refCount = 1; return bufPtr; } + +static void +PreserveChannelBuffer( + ChannelBuffer *bufPtr) +{ + bufPtr->refCount++; +} + +static void +ReleaseChannelBuffer( + ChannelBuffer *bufPtr) +{ + if (--bufPtr->refCount) { + return; + } + ckfree((char *) bufPtr); +} /* *---------------------------------------------------------------------- @@ -2250,7 +2271,7 @@ RecycleBuffer( */ if (mustDiscard) { - ckfree((char *) bufPtr); + ReleaseChannelBuffer(bufPtr); return; } @@ -2261,7 +2282,7 @@ RecycleBuffer( */ if ((bufPtr->bufLength - BUFFER_PADDING) != statePtr->bufSize) { - ckfree((char *) bufPtr); + ReleaseChannelBuffer(bufPtr); return; } @@ -2296,7 +2317,7 @@ RecycleBuffer( * If we reached this code we return the buffer to the OS. */ - ckfree((char *) bufPtr); + ReleaseChannelBuffer(bufPtr); return; keepBuffer: @@ -2470,6 +2491,7 @@ FlushChannel( * Produce the output on the channel. */ + PreserveChannelBuffer(bufPtr); toWrite = BytesLeft(bufPtr); if (toWrite == 0) { written = 0; @@ -2597,6 +2619,7 @@ FlushChannel( } RecycleBuffer(statePtr, bufPtr, 0); } + ReleaseChannelBuffer(bufPtr); } /* Closes "while (1)". */ /* @@ -2681,7 +2704,7 @@ CloseChannel( */ if (statePtr->curOutPtr != NULL) { - ckfree((char *) statePtr->curOutPtr); + ReleaseChannelBuffer(statePtr->curOutPtr); statePtr->curOutPtr = NULL; } @@ -3566,6 +3589,11 @@ static void WillWrite(Channel *chanPtr) static int WillRead(Channel *chanPtr) { + if (chanPtr->typePtr == NULL) { + /* Prevent read attempts on a closed channel */ + Tcl_SetErrno(EINVAL); + return -1; + } if ((chanPtr->typePtr->seekProc != NULL) && (Tcl_OutputBuffered((Tcl_Channel) chanPtr) > 0)) { if ((chanPtr->state->curOutPtr != NULL) @@ -3652,6 +3680,7 @@ Write( bufPtr->nextAdded += saved; saved = 0; } + PreserveChannelBuffer(bufPtr); dst = InsertPoint(bufPtr); dstLen = SpaceLeft(bufPtr); @@ -3665,6 +3694,7 @@ Write( if ((result != TCL_OK) && (srcRead + dstWrote == 0)) { /* We're reading from invalid/incomplete UTF-8 */ + ReleaseChannelBuffer(bufPtr); if (total == 0) { Tcl_SetErrno(EINVAL); return -1; @@ -3746,6 +3776,7 @@ Write( needNlFlush = 0; } } + ReleaseChannelBuffer(bufPtr); } if ((flushed < total) && (statePtr->flags & CHANNEL_UNBUFFERED || (needNlFlush && statePtr->flags & CHANNEL_LINEBUFFERED))) { @@ -5887,7 +5918,7 @@ DiscardInputQueued( */ if (discardSavedBuffers && statePtr->saveInBufPtr != NULL) { - ckfree((char *) statePtr->saveInBufPtr); + ReleaseChannelBuffer(statePtr->saveInBufPtr); statePtr->saveInBufPtr = NULL; } } @@ -5978,7 +6009,7 @@ GetInput( if ((bufPtr != NULL) && (bufPtr->bufLength - BUFFER_PADDING != statePtr->bufSize)) { - ckfree((char *) bufPtr); + ReleaseChannelBuffer(bufPtr); bufPtr = NULL; } @@ -6008,8 +6039,10 @@ GetInput( return 0; } + PreserveChannelBuffer(bufPtr); nread = ChanRead(chanPtr, InsertPoint(bufPtr), toRead, &result); if (nread > 0) { + result = 0; bufPtr->nextAdded += nread; /* @@ -6023,6 +6056,7 @@ GetInput( SetFlag(statePtr, CHANNEL_BLOCKED); } } else if (nread == 0) { + result = 0; SetFlag(statePtr, CHANNEL_EOF); statePtr->inputEncodingFlags |= TCL_ENCODING_END; } else if (nread < 0) { @@ -6031,9 +6065,9 @@ GetInput( result = EAGAIN; } Tcl_SetErrno(result); - return result; } - return 0; + ReleaseChannelBuffer(bufPtr); + return result; } /* |