summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2014-11-05 20:34:03 (GMT)
committerdgp <dgp@users.sourceforge.net>2014-11-05 20:34:03 (GMT)
commit836a10622561a68136fe41a106892b55aafb9fc3 (patch)
treee1516420790845e1f6c6fb4a4a7682c3c428214e
parentdb0b450fcc8673487056f6292838cc14ffa54c5e (diff)
downloadtcl-836a10622561a68136fe41a106892b55aafb9fc3.zip
tcl-836a10622561a68136fe41a106892b55aafb9fc3.tar.gz
tcl-836a10622561a68136fe41a106892b55aafb9fc3.tar.bz2
Reflected Transform channel fix. Be sure each EOF on the base channel gets
passed up to become an eof of the transform before continuing on to additional ReadRaw() from the base channel. This way we don't miss fleeting EOFs.
-rw-r--r--generic/tclIORTrans.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/generic/tclIORTrans.c b/generic/tclIORTrans.c
index 8f3ef3c..8baa9ad 100644
--- a/generic/tclIORTrans.c
+++ b/generic/tclIORTrans.c
@@ -161,6 +161,7 @@ typedef struct {
int mode; /* Mask of R/W mode */
int nonblocking; /* Flag: Channel is blocking or not. */
int readIsDrained; /* Flag: Read buffers are flushed. */
+ int eofPending; /* Flag: EOF seen down, but not raised up */
int dead; /* Boolean signal that some operations
* should no longer be attempted. */
ResultBuffer result;
@@ -1082,6 +1083,10 @@ ReflectInput(
bufObj = Tcl_NewByteArrayObj(NULL, toRead);
Tcl_IncrRefCount(bufObj);
gotBytes = 0;
+ if (rtPtr->eofPending) {
+ goto stop;
+ }
+ rtPtr->readIsDrained = 0;
while (toRead > 0) {
/*
* Loop until the request is satisfied (or no data available from
@@ -1097,9 +1102,9 @@ ReflectInput(
goto stop;
}
- if (rtPtr->readIsDrained) {
- goto stop;
- }
+ if (rtPtr->eofPending) {
+ goto stop;
+ }
/*
@@ -1170,6 +1175,8 @@ ReflectInput(
* Zero returned from Tcl_ReadRaw() always indicates EOF
* on the down channel.
*/
+
+ rtPtr->eofPending = 1;
/*
* Now this is a bit different. The partial data waiting is
@@ -1212,6 +1219,9 @@ ReflectInput(
} /* while toRead > 0 */
stop:
+ if (gotBytes == 0) {
+ rtPtr->eofPending = 0;
+ }
Tcl_DecrRefCount(bufObj);
Tcl_Release(rtPtr);
return gotBytes;
@@ -1767,6 +1777,7 @@ NewReflectedTransform(
rtPtr->timer = NULL;
rtPtr->mode = 0;
rtPtr->readIsDrained = 0;
+ rtPtr->eofPending = 0;
rtPtr->nonblocking =
(((Channel *) parentChan)->state->flags & CHANNEL_NONBLOCKING);
rtPtr->dead = 0;
@@ -3319,6 +3330,7 @@ TransformClear(
(void) InvokeTclMethod(rtPtr, "clear", NULL, NULL, NULL);
rtPtr->readIsDrained = 0;
+ rtPtr->eofPending = 0;
ResultClear(&rtPtr->result);
}