summaryrefslogtreecommitdiffstats
path: root/generic/tclNamesp.c
diff options
context:
space:
mode:
authorMiguel Sofer <miguel.sofer@gmail.com>2010-01-03 20:29:11 (GMT)
committerMiguel Sofer <miguel.sofer@gmail.com>2010-01-03 20:29:11 (GMT)
commit10428413079058e0f75d48d4f976493454730d0b (patch)
treedce88a02399c32caf6d59948227d30e00d697a4d /generic/tclNamesp.c
parentd20cf874f1303bf21f722abb01c7d1f08a9dc251 (diff)
downloadtcl-10428413079058e0f75d48d4f976493454730d0b.zip
tcl-10428413079058e0f75d48d4f976493454730d0b.tar.gz
tcl-10428413079058e0f75d48d4f976493454730d0b.tar.bz2
* generic/tclBasic.c: Fix lerak of coroutines on namespace
* generic/tclCompile.h: deletion, [Bug 2724403]. Added a test * generic/tclNamesp.c: for this leak, and also a test for * tests/coroutine.test: leaks on namespace deletion. * tests/namespace.test:
Diffstat (limited to 'generic/tclNamesp.c')
-rw-r--r--generic/tclNamesp.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c
index 507007d..f8ee460 100644
--- a/generic/tclNamesp.c
+++ b/generic/tclNamesp.c
@@ -23,7 +23,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclNamesp.c,v 1.198 2009/12/13 17:11:47 msofer Exp $
+ * RCS: @(#) $Id: tclNamesp.c,v 1.199 2010/01/03 20:29:11 msofer Exp $
*/
#include "tclInt.h"
@@ -956,7 +956,31 @@ Tcl_DeleteNamespace(
Namespace *globalNsPtr = (Namespace *)
TclGetGlobalNamespace((Tcl_Interp *) iPtr);
Tcl_HashEntry *entryPtr;
+ Tcl_HashSearch search;
+ Command *cmdPtr;
+
+ /*
+ * Delete all coroutine commands now: break the circular ref cycle between
+ * the namespace and the coroutine command [Bug 2724403]. This code is
+ * essentially duplicated in TclTeardownNamespace() for all other
+ * commands. Don't optimize to Tcl_NextHashEntry() because of traces.
+ *
+ * NOTE: we could avoid traversing the ns's command list by keeping a
+ * separate list of coros.
+ */
+ for (entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
+ entryPtr != NULL;) {
+ cmdPtr = (Command *) Tcl_GetHashValue(entryPtr);
+ if (cmdPtr->nreProc == NRInterpCoroutine) {
+ Tcl_DeleteCommandFromToken((Tcl_Interp *) iPtr, (Tcl_Command)cmdPtr);
+ entryPtr = Tcl_FirstHashEntry(&nsPtr->cmdTable, &search);
+ } else {
+ entryPtr = entryPtr->nextPtr;
+ }
+ }
+
+
/*
* If the namespace has associated ensemble commands, delete them first.
* This leaves the actual contents of the namespace alone (unless they are