Attachment "tcl86.2921116.diff-wu.patch" to
ticket [2921116fff]
added by
andreas_kupries
2010-01-20 02:20:41.
? LOG
Index: ChangeLog
===================================================================
RCS file: /cvsroot/tcl/tcl/ChangeLog,v
retrieving revision 1.4916
diff -w -u -r1.4916 ChangeLog
--- ChangeLog 18 Jan 2010 22:19:11 -0000 1.4916
+++ ChangeLog 19 Jan 2010 19:19:05 -0000
@@ -1,5 +1,16 @@
2010-01-18 Andreas Kupries <[email protected]>
+ * generic/tclIORTrans.c (ReflectInput, et al): [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.
+
+ Note: This is incomplete, all channel driver functions should
+ preserve the structure or we can crash them in an equivalent
+ manner.
+
* generic/tclIO.c (CreateScriptRecord): [Bug 2918110]: Initialize
the EventScriptRecord (esPtr) fully before handing it to
Tcl_CreateChannelHandler for registration. Otherwise a reflected
Index: generic/tclIO.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIO.c,v
retrieving revision 1.171
diff -w -u -r1.171 tclIO.c
--- generic/tclIO.c 18 Jan 2010 22:19:11 -0000 1.171
+++ generic/tclIO.c 19 Jan 2010 19:19:12 -0000
@@ -4765,6 +4765,13 @@
*/
done:
+ /*
+ * Regenerate the top channel, in case it was changed due to
+ * self-modifying reflected transforms.
+ */
+
+ chanPtr = statePtr->topChanPtr;
+
UpdateInterest(chanPtr);
return copiedTotal;
}
Index: generic/tclIORTrans.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIORTrans.c,v
retrieving revision 1.11
diff -w -u -r1.11 tclIORTrans.c
--- generic/tclIORTrans.c 10 Jan 2010 22:58:40 -0000 1.11
+++ generic/tclIORTrans.c 19 Jan 2010 19:19:13 -0000
@@ -719,7 +719,7 @@
* structure.
*/
- FreeReflectedTransform(rtPtr);
+ Tcl_EventuallyFree (rtPtr, FreeReflectedTransform);
return TCL_ERROR;
#undef CHAN
@@ -929,7 +929,7 @@
}
#endif
- FreeReflectedTransform(rtPtr);
+ Tcl_EventuallyFree (rtPtr, FreeReflectedTransform);
return EOK;
}
@@ -1028,7 +1028,7 @@
}
#endif
- FreeReflectedTransform(rtPtr);
+ Tcl_EventuallyFree (rtPtr, FreeReflectedTransform);
return (result == TCL_OK) ? EOK : EINVAL;
}
@@ -1070,8 +1070,9 @@
return -1;
}
- gotBytes = 0;
+ Tcl_Preserve(rtPtr);
+ gotBytes = 0;
while (toRead > 0) {
/*
* Loop until the request is satisfied (or no data available from
@@ -1084,7 +1085,7 @@
gotBytes += copied;
if (toRead == 0) {
- return gotBytes;
+ goto stop;
}
/*
@@ -1107,10 +1108,10 @@
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;
@@ -1119,7 +1120,7 @@
}
if (toRead <= 0) {
- return gotBytes;
+ goto stop;
}
read = Tcl_ReadRaw(rtPtr->parent, buf, toRead);
@@ -1135,11 +1136,11 @@
* we report that instead of the request to re-try.
*/
- return gotBytes;
+ goto stop;
}
*errorCodePtr = Tcl_GetErrno();
- return -1;
+ goto error;
}
if (read == 0) {
@@ -1160,16 +1161,16 @@
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;
}
/*
@@ -1179,7 +1180,7 @@
if (HAS(rtPtr->methods, METH_DRAIN)) {
if (!TransformDrain(rtPtr, errorCodePtr)) {
- return -1;
+ goto error;
}
}
@@ -1188,7 +1189,7 @@
* The drain delivered nothing.
*/
- return gotBytes;
+ goto stop;
}
/*
@@ -1207,11 +1208,17 @@
*/
if (!TransformRead(rtPtr, errorCodePtr, UCHARP(buf), read)) {
- return -1;
+ goto error;
}
} /* while toRead > 0 */
+ stop:
+ Tcl_Release(rtPtr);
return gotBytes;
+
+ error:
+ gotBytes = -1;
+ goto stop;
}
/*
@@ -1264,6 +1271,8 @@
* we do when explicitly seeking as well.
*/
+ Tcl_Preserve(rtPtr);
+
if ((rtPtr->methods & FLAG(METH_CLEAR))) {
TransformClear(rtPtr);
}
@@ -1275,10 +1284,12 @@
*/
if (!TransformWrite(rtPtr, errorCodePtr, UCHARP(buf), toWrite)) {
+ Tcl_Release(rtPtr);
return -1;
}
*errorCodePtr = EOK;
+ Tcl_Release(rtPtr);
return toWrite;
}
@@ -1329,6 +1340,8 @@
* 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))){
/*
@@ -1350,6 +1363,7 @@
if (HAS(rtPtr->methods, METH_FLUSH)) {
if (!TransformFlush(rtPtr, errorCodePtr, FLUSH_DISCARD)) {
+ Tcl_Release(rtPtr);
return -1;
}
}
@@ -1379,6 +1393,7 @@
}
*errorCodePtr = EOK;
+ Tcl_Release(rtPtr);
return curPos;
}
@@ -1968,7 +1983,7 @@
*/
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);
/*
@@ -2013,7 +2028,7 @@
Tcl_IncrRefCount(resObj);
}
Tcl_RestoreInterpState(rtPtr->interp, sr);
- Tcl_Release(rtPtr->interp);
+ Tcl_Release(rtPtr);
/*
* Cleanup of the dynamic parts of the command.
@@ -2528,7 +2543,8 @@
rtmPtr = GetThreadReflectedTransformMap();
hPtr = Tcl_FindHashEntry(&rtmPtr->map, Tcl_GetString(rtPtr->handle));
Tcl_DeleteHashEntry(hPtr);
- FreeReflectedTransform(rtPtr);
+
+ Tcl_EventuallyFree (rtPtr, FreeReflectedTransform);
break;
case ForwardedInput: {