summaryrefslogtreecommitdiffstats
path: root/generic/tclIORChan.c
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2014-07-22 16:44:38 (GMT)
committerdgp <dgp@users.sourceforge.net>2014-07-22 16:44:38 (GMT)
commitb48cbaeccb8ec71c06c18c3eec115aad92346c38 (patch)
treed0755c019c6357cbc87c99043b33aad94417f527 /generic/tclIORChan.c
parent4a913825d6e04adfddffb4f70cd7d35ae6b92efb (diff)
downloadtcl-b48cbaeccb8ec71c06c18c3eec115aad92346c38.zip
tcl-b48cbaeccb8ec71c06c18c3eec115aad92346c38.tar.gz
tcl-b48cbaeccb8ec71c06c18c3eec115aad92346c38.tar.bz2
[12b0997ce7] Plug memleak in iocmd.tf-32.0 .bug_12b0997ce7
Diffstat (limited to 'generic/tclIORChan.c')
-rw-r--r--generic/tclIORChan.c63
1 files changed, 40 insertions, 23 deletions
diff --git a/generic/tclIORChan.c b/generic/tclIORChan.c
index ff602c6..3506a44 100644
--- a/generic/tclIORChan.c
+++ b/generic/tclIORChan.c
@@ -436,6 +436,7 @@ static ReflectedChannelMap * GetReflectedChannelMap(Tcl_Interp *interp);
static void DeleteReflectedChannelMap(ClientData clientData,
Tcl_Interp *interp);
static int ErrnoReturn(ReflectedChannel *rcPtr, Tcl_Obj *resObj);
+static void MarkDead(ReflectedChannel *rcPtr);
/*
* Global constant strings (messages). ==================
@@ -1146,7 +1147,6 @@ ReflectClose(
if (result != TCL_OK) {
FreeReceivedError(&p);
}
- return EOK;
}
#endif
@@ -1217,17 +1217,14 @@ ReflectClose(
if (hPtr) {
Tcl_DeleteHashEntry(hPtr);
}
+ }
#endif
-
- tctPtr = ((Channel *)rcPtr->chan)->typePtr;
- if (tctPtr && tctPtr != &tclRChannelType) {
+ tctPtr = ((Channel *)rcPtr->chan)->typePtr;
+ if (tctPtr && tctPtr != &tclRChannelType) {
ckfree((char *)tctPtr);
((Channel *)rcPtr->chan)->typePtr = NULL;
- }
- Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
-#ifdef TCL_THREADS
}
-#endif
+ Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
return (result == TCL_OK) ? EOK : EINVAL;
}
@@ -2192,9 +2189,15 @@ FreeReflectedChannel(
Channel *chanPtr = (Channel *) rcPtr->chan;
Tcl_Release(chanPtr);
- Tcl_DecrRefCount(rcPtr->name);
- Tcl_DecrRefCount(rcPtr->methods);
- Tcl_DecrRefCount(rcPtr->cmd);
+ if (rcPtr->name) {
+ Tcl_DecrRefCount(rcPtr->name);
+ }
+ if (rcPtr->methods) {
+ Tcl_DecrRefCount(rcPtr->methods);
+ }
+ if (rcPtr->cmd) {
+ Tcl_DecrRefCount(rcPtr->cmd);
+ }
ckfree(rcPtr);
}
@@ -2460,6 +2463,28 @@ GetReflectedChannelMap(
*/
static void
+MarkDead(
+ ReflectedChannel *rcPtr)
+{
+ if (rcPtr->dead) {
+ return;
+ }
+ if (rcPtr->name) {
+ Tcl_DecrRefCount(rcPtr->name);
+ rcPtr->name = NULL;
+ }
+ if (rcPtr->methods) {
+ Tcl_DecrRefCount(rcPtr->methods);
+ rcPtr->methods = NULL;
+ }
+ if (rcPtr->cmd) {
+ Tcl_DecrRefCount(rcPtr->cmd);
+ rcPtr->cmd = NULL;
+ }
+ rcPtr->dead = 1;
+}
+
+static void
DeleteReflectedChannelMap(
ClientData clientData, /* The per-interpreter data structure. */
Tcl_Interp *interp) /* The interpreter being deleted. */
@@ -2494,7 +2519,7 @@ DeleteReflectedChannelMap(
chan = Tcl_GetHashValue(hPtr);
rcPtr = Tcl_GetChannelInstanceData(chan);
- rcPtr->dead = 1;
+ MarkDead(rcPtr);
Tcl_DeleteHashEntry(hPtr);
}
Tcl_DeleteHashTable(&rcmPtr->map);
@@ -2577,7 +2602,7 @@ DeleteReflectedChannelMap(
continue;
}
- rcPtr->dead = 1;
+ MarkDead(rcPtr);
Tcl_DeleteHashEntry(hPtr);
}
#endif
@@ -2724,7 +2749,7 @@ DeleteThreadReflectedChannelMap(
Tcl_Channel chan = Tcl_GetHashValue(hPtr);
ReflectedChannel *rcPtr = Tcl_GetChannelInstanceData(chan);
- rcPtr->dead = 1;
+ MarkDead(rcPtr);
Tcl_DeleteHashEntry(hPtr);
}
ckfree(rcmPtr);
@@ -2907,8 +2932,6 @@ ForwardProc(
* No parameters/results.
*/
- const Tcl_ChannelType *tctPtr;
-
if (InvokeTclMethod(rcPtr, METH_FINAL, NULL, NULL, &resObj)!=TCL_OK) {
ForwardSetObjError(paramPtr, resObj);
}
@@ -2932,13 +2955,7 @@ ForwardProc(
hPtr = Tcl_FindHashEntry(&rcmPtr->map,
Tcl_GetChannelName(rcPtr->chan));
Tcl_DeleteHashEntry(hPtr);
-
- tctPtr = ((Channel *)rcPtr->chan)->typePtr;
- if (tctPtr && tctPtr != &tclRChannelType) {
- ckfree((char *)tctPtr);
- ((Channel *)rcPtr->chan)->typePtr = NULL;
- }
- Tcl_EventuallyFree(rcPtr, (Tcl_FreeProc *) FreeReflectedChannel);
+ MarkDead(rcPtr);
break;
}