diff options
author | dgp <dgp@users.sourceforge.net> | 2014-04-21 20:02:39 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2014-04-21 20:02:39 (GMT) |
commit | 80299d811c1d9072b7aa16812efa92261169cc98 (patch) | |
tree | 3fb1e729f90fb050de4bcc1fb0829f7ba5b6475a /generic/tclIO.c | |
parent | eff70f42a20d07ad259305cd44a5aaaa8e544ce0 (diff) | |
parent | 5407657340a624d763a1c122624a5b5da218f911 (diff) | |
download | tcl-80299d811c1d9072b7aa16812efa92261169cc98.zip tcl-80299d811c1d9072b7aa16812efa92261169cc98.tar.gz tcl-80299d811c1d9072b7aa16812efa92261169cc98.tar.bz2 |
merge trunk
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 e4f82be..edccf41 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); @@ -388,6 +390,7 @@ ChanRead( int *errnoPtr) { if (WillRead(chanPtr) < 0) { + *errnoPtr = Tcl_GetErrno(); return -1; } @@ -2289,8 +2292,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(bufPtr); +} /* *---------------------------------------------------------------------- @@ -2323,7 +2344,7 @@ RecycleBuffer( */ if (mustDiscard) { - ckfree(bufPtr); + ReleaseChannelBuffer(bufPtr); return; } @@ -2334,7 +2355,7 @@ RecycleBuffer( */ if ((bufPtr->bufLength - BUFFER_PADDING) != statePtr->bufSize) { - ckfree(bufPtr); + ReleaseChannelBuffer(bufPtr); return; } @@ -2369,7 +2390,7 @@ RecycleBuffer( * If we reached this code we return the buffer to the OS. */ - ckfree(bufPtr); + ReleaseChannelBuffer(bufPtr); return; keepBuffer: @@ -2545,6 +2566,7 @@ FlushChannel( * Produce the output on the channel. */ + PreserveChannelBuffer(bufPtr); toWrite = BytesLeft(bufPtr); if (toWrite == 0) { written = 0; @@ -2668,6 +2690,7 @@ FlushChannel( } RecycleBuffer(statePtr, bufPtr, 0); } + ReleaseChannelBuffer(bufPtr); } /* Closes "while (1)". */ /* @@ -2769,7 +2792,7 @@ CloseChannel( */ if (statePtr->curOutPtr != NULL) { - ckfree(statePtr->curOutPtr); + ReleaseChannelBuffer(statePtr->curOutPtr); statePtr->curOutPtr = NULL; } @@ -3978,6 +4001,11 @@ 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) @@ -4064,6 +4092,7 @@ Write( bufPtr->nextAdded += saved; saved = 0; } + PreserveChannelBuffer(bufPtr); dst = InsertPoint(bufPtr); dstLen = SpaceLeft(bufPtr); @@ -4077,6 +4106,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; @@ -4158,6 +4188,7 @@ Write( needNlFlush = 0; } } + ReleaseChannelBuffer(bufPtr); } if ((flushed < total) && (GotFlag(statePtr, CHANNEL_UNBUFFERED) || (needNlFlush && GotFlag(statePtr, CHANNEL_LINEBUFFERED)))) { @@ -6329,7 +6360,7 @@ DiscardInputQueued( */ if (discardSavedBuffers && statePtr->saveInBufPtr != NULL) { - ckfree(statePtr->saveInBufPtr); + ReleaseChannelBuffer(statePtr->saveInBufPtr); statePtr->saveInBufPtr = NULL; } } @@ -6420,7 +6451,7 @@ GetInput( if ((bufPtr != NULL) && (bufPtr->bufLength - BUFFER_PADDING != statePtr->bufSize)) { - ckfree(bufPtr); + ReleaseChannelBuffer(bufPtr); bufPtr = NULL; } @@ -6450,8 +6481,10 @@ GetInput( return 0; } + PreserveChannelBuffer(bufPtr); nread = ChanRead(chanPtr, InsertPoint(bufPtr), toRead, &result); if (nread > 0) { + result = 0; bufPtr->nextAdded += nread; /* @@ -6465,6 +6498,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) { @@ -6473,9 +6507,9 @@ GetInput( result = EAGAIN; } Tcl_SetErrno(result); - return result; } - return 0; + ReleaseChannelBuffer(bufPtr); + return result; } /* |