summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authorandreas_kupries <akupries@shaw.ca>2010-03-17 16:35:40 (GMT)
committerandreas_kupries <akupries@shaw.ca>2010-03-17 16:35:40 (GMT)
commit5d7a1c17873ac12e80410c4cf4fef6ace21565f6 (patch)
treedfdcaaa61a49d34ef382c0b90bb0a91fe6c009ab /generic
parent0cf955ab149d4c4221bdafaaab80d53352ac4446 (diff)
downloadtcl-5d7a1c17873ac12e80410c4cf4fef6ace21565f6.zip
tcl-5d7a1c17873ac12e80410c4cf4fef6ace21565f6.tar.gz
tcl-5d7a1c17873ac12e80410c4cf4fef6ace21565f6.tar.bz2
* generic/tclIORTrans.c (ReflectInput, ReflectOutput,
ReflectSeekWide): [Bug 2921116]: Added missing TclEventuallyFree calls for preserved ReflectedTransform* structures. Reworked ReflectInput to preserve the structure for its whole life, not only in InvokeTclMethod. * generic/tclIO.c (Tcl_GetsObj): [Bug 2921116]: Regenerate topChan, may have been changed by a self-modifying transformation. * tests/ioTrans/test (iortrans-4.8, iortrans-4.9, iortrans-5.11, iortrans-7.4, iortrans-8.3): New test cases.
Diffstat (limited to 'generic')
-rw-r--r--generic/tclIO.c30
-rw-r--r--generic/tclIORTrans.c56
2 files changed, 65 insertions, 21 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c
index 7ed714c..bc94bb6 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclIO.c,v 1.172 2010/02/24 10:45:04 dkf Exp $
+ * RCS: @(#) $Id: tclIO.c,v 1.173 2010/03/17 16:35:42 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -4715,6 +4715,13 @@ Tcl_GetsObj(
*/
gotEOL:
+ /*
+ * Regenerate the top channel, in case it was changed due to
+ * self-modifying reflected transforms.
+ */
+
+ chanPtr = statePtr->topChanPtr;
+
bufPtr = gs.bufPtr;
if (bufPtr == NULL) {
Tcl_Panic("Tcl_GetsObj: gotEOL reached with bufPtr==NULL");
@@ -4743,6 +4750,13 @@ Tcl_GetsObj(
*/
restore:
+ /*
+ * Regenerate the top channel, in case it was changed due to
+ * self-modifying reflected transforms.
+ */
+
+ chanPtr = statePtr->topChanPtr;
+
bufPtr = statePtr->inQueueHead;
if (bufPtr == NULL) {
Tcl_Panic("Tcl_GetsObj: restore reached with bufPtr==NULL");
@@ -4778,6 +4792,13 @@ Tcl_GetsObj(
*/
done:
+ /*
+ * Regenerate the top channel, in case it was changed due to
+ * self-modifying reflected transforms.
+ */
+
+ chanPtr = statePtr->topChanPtr;
+
UpdateInterest(chanPtr);
return copiedTotal;
}
@@ -5776,6 +5797,13 @@ DoReadChars(
*/
done:
+ /*
+ * Regenerate the top channel, in case it was changed due to
+ * self-modifying reflected transforms.
+ */
+
+ chanPtr = statePtr->topChanPtr;
+
UpdateInterest(chanPtr);
return copied;
}
diff --git a/generic/tclIORTrans.c b/generic/tclIORTrans.c
index eb40ce5..801f5fb 100644
--- a/generic/tclIORTrans.c
+++ b/generic/tclIORTrans.c
@@ -15,7 +15,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclIORTrans.c,v 1.14 2010/03/05 22:50:32 dkf Exp $
+ * RCS: @(#) $Id: tclIORTrans.c,v 1.15 2010/03/17 16:35:42 andreas_kupries Exp $
*/
#include <tclInt.h>
@@ -721,7 +721,7 @@ TclChanPushObjCmd(
* structure.
*/
- FreeReflectedTransform(rtPtr);
+ Tcl_EventuallyFree (rtPtr, (Tcl_FreeProc *) FreeReflectedTransform);
return TCL_ERROR;
#undef CHAN
@@ -931,7 +931,7 @@ ReflectClose(
}
#endif
- FreeReflectedTransform(rtPtr);
+ Tcl_EventuallyFree (rtPtr, (Tcl_FreeProc *) FreeReflectedTransform);
return EOK;
}
@@ -1030,7 +1030,7 @@ ReflectClose(
}
#endif
- FreeReflectedTransform(rtPtr);
+ Tcl_EventuallyFree (rtPtr, (Tcl_FreeProc *) FreeReflectedTransform);
return (result == TCL_OK) ? EOK : EINVAL;
}
@@ -1072,8 +1072,9 @@ ReflectInput(
return -1;
}
- gotBytes = 0;
+ Tcl_Preserve(rtPtr);
+ gotBytes = 0;
while (toRead > 0) {
/*
* Loop until the request is satisfied (or no data available from
@@ -1086,7 +1087,7 @@ ReflectInput(
gotBytes += copied;
if (toRead == 0) {
- return gotBytes;
+ goto stop;
}
/*
@@ -1109,10 +1110,10 @@ ReflectInput(
int maxRead = -1;
if (!TransformLimit(rtPtr, errorCodePtr, &maxRead)) {
- return -1;
+ goto error;
}
if (maxRead == 0) {
- return gotBytes;
+ goto stop;
} else if (maxRead > 0) {
if (maxRead < toRead) {
toRead = maxRead;
@@ -1121,7 +1122,7 @@ ReflectInput(
}
if (toRead <= 0) {
- return gotBytes;
+ goto stop;
}
readBytes = Tcl_ReadRaw(rtPtr->parent, buf, toRead);
@@ -1137,11 +1138,11 @@ ReflectInput(
* we report that instead of the request to re-try.
*/
- return gotBytes;
+ goto stop;
}
*errorCodePtr = Tcl_GetErrno();
- return -1;
+ goto error;
}
if (readBytes == 0) {
@@ -1162,16 +1163,16 @@ ReflectInput(
if ((gotBytes == 0) && rtPtr->nonblocking) {
*errorCodePtr = EWOULDBLOCK;
- return -1;
+ goto error;
}
- return gotBytes;
+ goto stop;
} else {
/*
* Eof in parent.
*/
if (rtPtr->readIsDrained) {
- return gotBytes;
+ goto stop;
}
/*
@@ -1181,7 +1182,7 @@ ReflectInput(
if (HAS(rtPtr->methods, METH_DRAIN)) {
if (!TransformDrain(rtPtr, errorCodePtr)) {
- return -1;
+ goto error;
}
}
@@ -1190,7 +1191,7 @@ ReflectInput(
* The drain delivered nothing.
*/
- return gotBytes;
+ goto stop;
}
/*
@@ -1209,11 +1210,17 @@ ReflectInput(
*/
if (!TransformRead(rtPtr, errorCodePtr, UCHARP(buf), readBytes)) {
- return -1;
+ goto error;
}
} /* while toRead > 0 */
+ stop:
+ Tcl_Release(rtPtr);
return gotBytes;
+
+ error:
+ gotBytes = -1;
+ goto stop;
}
/*
@@ -1266,6 +1273,8 @@ ReflectOutput(
* we do when explicitly seeking as well.
*/
+ Tcl_Preserve(rtPtr);
+
if ((rtPtr->methods & FLAG(METH_CLEAR))) {
TransformClear(rtPtr);
}
@@ -1277,10 +1286,12 @@ ReflectOutput(
*/
if (!TransformWrite(rtPtr, errorCodePtr, UCHARP(buf), toWrite)) {
+ Tcl_Release(rtPtr);
return -1;
}
*errorCodePtr = EOK;
+ Tcl_Release(rtPtr);
return toWrite;
}
@@ -1331,6 +1342,8 @@ ReflectSeekWide(
* request down and the result back up unchanged.
*/
+ Tcl_Preserve(rtPtr);
+
if (((seekMode != SEEK_CUR) || (offset != 0))
&& (HAS(rtPtr->methods, METH_CLEAR)
|| HAS(rtPtr->methods, METH_FLUSH))) {
@@ -1353,6 +1366,7 @@ ReflectSeekWide(
if (HAS(rtPtr->methods, METH_FLUSH)) {
if (!TransformFlush(rtPtr, errorCodePtr, FLUSH_DISCARD)) {
+ Tcl_Release(rtPtr);
return -1;
}
}
@@ -1382,6 +1396,7 @@ ReflectSeekWide(
}
*errorCodePtr = EOK;
+ Tcl_Release(rtPtr);
return curPos;
}
@@ -1971,7 +1986,7 @@ InvokeTclMethod(
*/
sr = Tcl_SaveInterpState(rtPtr->interp, 0 /* Dummy */);
- Tcl_Preserve(rtPtr->interp);
+ Tcl_Preserve(rtPtr);
result = Tcl_EvalObjv(rtPtr->interp, cmdc, rtPtr->argv, TCL_EVAL_GLOBAL);
/*
@@ -2016,7 +2031,7 @@ InvokeTclMethod(
Tcl_IncrRefCount(resObj);
}
Tcl_RestoreInterpState(rtPtr->interp, sr);
- Tcl_Release(rtPtr->interp);
+ Tcl_Release(rtPtr);
/*
* Cleanup of the dynamic parts of the command.
@@ -2531,7 +2546,8 @@ ForwardProc(
rtmPtr = GetThreadReflectedTransformMap();
hPtr = Tcl_FindHashEntry(&rtmPtr->map, Tcl_GetString(rtPtr->handle));
Tcl_DeleteHashEntry(hPtr);
- FreeReflectedTransform(rtPtr);
+
+ Tcl_EventuallyFree (rtPtr, (Tcl_FreeProc *) FreeReflectedTransform);
break;
case ForwardedInput: {