summaryrefslogtreecommitdiffstats
path: root/generic/tclIORChan.c
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2011-09-19 14:41:22 (GMT)
committerdgp <dgp@users.sourceforge.net>2011-09-19 14:41:22 (GMT)
commitbd3d162f011f2a5728eaffba2ad513bf15d6d3e6 (patch)
tree18fe53f2cc827be721a313bc649c11a15c20ab58 /generic/tclIORChan.c
parent4e8954188850061d06183ad502d35b9b38db1f50 (diff)
downloadtcl-bd3d162f011f2a5728eaffba2ad513bf15d6d3e6.zip
tcl-bd3d162f011f2a5728eaffba2ad513bf15d6d3e6.tar.gz
tcl-bd3d162f011f2a5728eaffba2ad513bf15d6d3e6.tar.bz2
Plug leak of a ReflectedChannel in test iocmd.tf-32.0
Diffstat (limited to 'generic/tclIORChan.c')
-rw-r--r--generic/tclIORChan.c58
1 files changed, 36 insertions, 22 deletions
diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c
index acf7365..da6f642 100644
--- a/generic/tclIORChan.c
+++ b/generic/tclIORChan.c
@@ -1066,15 +1066,9 @@ ReflectClose(
ForwardOpToOwnerThread(rcPtr, ForwardedClose, &p);
result = p.base.code;
- /*
- * FreeReflectedChannel is done in the forwarded operation!, in
- * the other thread. rcPtr here is gone!
- */
-
if (result != TCL_OK) {
FreeReceivedError(&p);
}
- return EOK;
}
#endif
@@ -1105,10 +1099,7 @@ ReflectClose(
ForwardOpToOwnerThread(rcPtr, ForwardedClose, &p);
result = p.base.code;
- /*
- * FreeReflectedChannel is done in the forwarded operation!, in the
- * other thread. rcPtr here is gone!
- */
+ Tcl_EventuallyFree (rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
if (result != TCL_OK) {
PassReceivedErrorInterp(interp, &p);
@@ -2130,21 +2121,14 @@ NextHandle(void)
}
static void
-FreeReflectedChannel(
+FreeReflectedChannelArgs(
ReflectedChannel *rcPtr)
{
- Channel *chanPtr = (Channel *) rcPtr->chan;
- int i, n;
-
- if (chanPtr->typePtr != &tclRChannelType) {
- /*
- * Delete a cloned ChannelType structure.
- */
+ int i, n = rcPtr->argc - 2;
- ckfree(chanPtr->typePtr);
+ if (n < 0) {
+ return;
}
-
- n = rcPtr->argc - 2;
for (i=0; i<n; i++) {
Tcl_DecrRefCount(rcPtr->argv[i]);
}
@@ -2155,6 +2139,25 @@ FreeReflectedChannel(
Tcl_DecrRefCount(rcPtr->argv[n+1]);
+ rcPtr->argc = 1;
+}
+
+static void
+FreeReflectedChannel(
+ ReflectedChannel *rcPtr)
+{
+ Channel *chanPtr = (Channel *) rcPtr->chan;
+
+ if (chanPtr->typePtr != &tclRChannelType) {
+ /*
+ * Delete a cloned ChannelType structure.
+ */
+
+ ckfree(chanPtr->typePtr);
+ }
+
+ FreeReflectedChannelArgs(rcPtr);
+
ckfree(rcPtr->argv);
ckfree(rcPtr);
}
@@ -2506,6 +2509,11 @@ DeleteReflectedChannelMap(
*/
evPtr = resultPtr->evPtr;
+
+ /* Basic crash safety until this routine can get revised [3411310] */
+ if (evPtr == NULL) {
+ continue;
+ }
paramPtr = evPtr->param;
evPtr->resultPtr = NULL;
@@ -2639,6 +2647,11 @@ DeleteThreadReflectedChannelMap(
*/
evPtr = resultPtr->evPtr;
+
+ /* Basic crash safety until this routine can get revised [3411310] */
+ if (evPtr == NULL ) {
+ continue;
+ }
paramPtr = evPtr->param;
evPtr->resultPtr = NULL;
@@ -2665,6 +2678,7 @@ DeleteThreadReflectedChannelMap(
ReflectedChannel *rcPtr = Tcl_GetChannelInstanceData(chan);
rcPtr->interp = NULL;
+ FreeReflectedChannelArgs(rcPtr);
Tcl_DeleteHashEntry(hPtr);
}
ckfree(rcmPtr);
@@ -2862,7 +2876,7 @@ ForwardProc(
Tcl_GetChannelName(rcPtr->chan));
Tcl_DeleteHashEntry(hPtr);
- Tcl_EventuallyFree (rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
+ FreeReflectedChannelArgs(rcPtr);
break;
case ForwardedInput: {