? generic/tclCoroutine.c
? generic/tclExecute.c.cvs
? generic/tclExecute.c.new
? unix/0valgrind
? unix/ERR
? unix/autom4te.cache
? unix/config.status.lineno
? unix/dltest.marker
? unix/httpd_10227
? unix/httpd_10297
? unix/httpd_14990
? unix/res
? unix/tcl.pc
? unix/tclsh-new
? unix/tclsh-orig
Index: generic/tclBasic.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclBasic.c,v
retrieving revision 1.394
diff -u -r1.394 tclBasic.c
--- generic/tclBasic.c	8 May 2009 08:48:19 -0000	1.394
+++ generic/tclBasic.c	9 May 2009 16:40:15 -0000
@@ -1446,7 +1446,6 @@
     Tcl_PopCallFrame(interp);
     ckfree((char *) iPtr->rootFramePtr);
     iPtr->rootFramePtr = NULL;
-    Tcl_DeleteNamespace((Tcl_Namespace *) iPtr->globalNsPtr);
 
     /*
      * Free up the result *after* deleting variables, since variable deletion
Index: generic/tclInt.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.h,v
retrieving revision 1.423
diff -u -r1.423 tclInt.h
--- generic/tclInt.h	8 May 2009 08:48:19 -0000	1.423
+++ generic/tclInt.h	9 May 2009 16:40:18 -0000
@@ -241,15 +241,11 @@
     long nsId;			/* Unique id for the namespace. */
     Tcl_Interp *interp;		/* The interpreter containing this
 				 * namespace. */
-    int flags;			/* OR-ed combination of the namespace status
-				 * flags NS_DYING and NS_DEAD listed below. */
-    int activationCount;	/* Number of "activations" or active call
-				 * frames for this namespace that are on the
-				 * Tcl call stack. The namespace won't be
-				 * freed until activationCount becomes zero. */
+    int flags;			/* 0R-ed combination of values below. */
     int refCount;		/* Count of references by namespaceName
-				 * objects. The namespace can't be freed until
-				 * refCount becomes zero. */
+				 * objects, CallFrames and the parent
+				 * namespace. The namespace can't be freed
+				 * until refCount becomes zero. */
     Tcl_HashTable cmdTable;	/* Contains all the commands currently
 				 * registered in the namespace. Indexed by
 				 * strings; values have type (Command *).
@@ -346,20 +342,6 @@
 /*
  * Flags used to represent the status of a namespace:
  *
- * NS_DYING -	1 means Tcl_DeleteNamespace has been called to delete the
- *		namespace but there are still active call frames on the Tcl
- *		stack that refer to the namespace. When the last call frame
- *		referring to it has been popped, it's variables and command
- *		will be destroyed and it will be marked "dead" (NS_DEAD). The
- *		namespace can no longer be looked up by name.
- * NS_DEAD -	1 means Tcl_DeleteNamespace has been called to delete the
- *		namespace and no call frames still refer to it. Its variables
- *		and command have already been destroyed. This bit allows the
- *		namespace resolution code to recognize that the namespace is
- *		"deleted". When the last namespaceName object in any byte code
- *		unit that refers to the namespace has been freed (i.e., when
- *		the namespace's refCount is 0), the namespace's storage will
- *		be freed.
  * NS_KILLED -	1 means that TclTeardownNamespace has already been called on
  *		this namespace and it should not be called again [Bug 1355942]
  * NS_SUPPRESS_COMPILATION -
@@ -367,9 +349,14 @@
  *		forcing them to be looked up every time.
  */
 
-#define NS_DYING	0x01
-#define NS_DEAD		0x02
-#define NS_KILLED	0x04
+/* NS_DYING and NS_DEAD are the same now; both names kept for back compat */
+
+#define NS_DYING	0x01 /* deprecated */
+#define NS_DEAD	        0x02 /* deprecated */
+
+#define NS_KILLED       0x07 /* 0x4; set also (NS_DYING|NS_DEAD) for compat
+			      * with extensions that may have used them */
+
 #define NS_SUPPRESS_COMPILATION	0x08
 
 /*
Index: generic/tclNamesp.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclNamesp.c,v
retrieving revision 1.191
diff -u -r1.191 tclNamesp.c
--- generic/tclNamesp.c	21 Mar 2009 12:24:49 -0000	1.191
+++ generic/tclNamesp.c	9 May 2009 16:40:22 -0000
@@ -396,22 +396,13 @@
     } else {
 	nsPtr = (Namespace *) namespacePtr;
 
-	/*
-	 * TODO: Examine whether it would be better to guard based on NS_DYING
-	 * or NS_KILLED. It appears that these are not tested because they can
-	 * be set in a global interp that has been [namespace delete]d, but
-	 * which never really completely goes away because of lingering global
-	 * things like ::errorInfo and [::unknown] and hidden commands.
-	 * Review of those designs might permit stricter checking here.
-	 */
-
-	if (nsPtr->flags & NS_DEAD) {
+	if (nsPtr->flags & NS_KILLED) {
 	    Tcl_Panic("Trying to push call frame for dead namespace");
 	    /*NOTREACHED*/
 	}
     }
 
-    nsPtr->activationCount++;
+    nsPtr->refCount++;
     framePtr->nsPtr = nsPtr;
     framePtr->isProcCallFrame = isProcCallFrame;
     framePtr->objc = 0;
@@ -455,7 +446,8 @@
  * Side effects:
  *	Modifies the call stack of the interpreter. Resets various fields of
  *	the popped call frame. If a namespace has been deleted and has no more
- *	activations on the call stack, the namespace is destroyed.
+ *	references (including activations on the call stack), the namespace is
+ *	destroyed.
  *      Schedules a tailcall if one is present. 
  *
  *----------------------------------------------------------------------
@@ -502,10 +494,9 @@
      */
 
     nsPtr = framePtr->nsPtr;
-    nsPtr->activationCount--;
-    if ((nsPtr->flags & NS_DYING)
-	    && (nsPtr->activationCount - (nsPtr == iPtr->globalNsPtr) == 0)) {
-	Tcl_DeleteNamespace((Tcl_Namespace *) nsPtr);
+    nsPtr->refCount--;
+    if ((nsPtr->flags & NS_KILLED) && (nsPtr->refCount == 0)) {
+	NamespaceFree(nsPtr);
     }
     framePtr->nsPtr = NULL;
 
@@ -845,8 +836,7 @@
     nsPtr->nsId = ++(tsdPtr->numNsCreated);
     nsPtr->interp = interp;
     nsPtr->flags = 0;
-    nsPtr->activationCount = 0;
-    nsPtr->refCount = 0;
+    nsPtr->refCount = (parentPtr != NULL);
     Tcl_InitHashTable(&nsPtr->cmdTable, TCL_STRING_KEYS);
     TclInitVarHashTable(&nsPtr->varTable, nsPtr);
     nsPtr->exportArrayPtr = NULL;
@@ -968,117 +958,36 @@
     Interp *iPtr = (Interp *) nsPtr->interp;
     Namespace *globalNsPtr = (Namespace *)
 	    TclGetGlobalNamespace((Tcl_Interp *) iPtr);
-    Tcl_HashEntry *entryPtr;
 
     /*
-     * If the namespace has associated ensemble commands, delete them first.
-     * This leaves the actual contents of the namespace alone (unless they are
-     * linked ensemble commands, of course). Note that this code is actually
-     * reentrant so command delete traces won't purturb things badly.
+     * Delete the namespace and everything in it. If this is the global
+     * namespace, then clear it but don't free its storage unless the
+     * interpreter is being torn down. Set the NS_KILLED flag to avoid
+     * recursive calls here - if the namespace is really in the process of
+     * being deleted, ignore any second call.
      */
-
-    while (nsPtr->ensembles != NULL) {
-	EnsembleConfig *ensemblePtr = (EnsembleConfig *) nsPtr->ensembles;
-
+    
+    TclTeardownNamespace(nsPtr);
+    
+    if (nsPtr->refCount == 0) {
+	NamespaceFree(nsPtr);
+    } else if ((nsPtr == globalNsPtr) && !(iPtr->flags & DELETED)) {
 	/*
-	 * Splice out and link to indicate that we've already been killed.
+	 * Restore the ::errorInfo and ::errorCode traces.
 	 */
-
-	nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr->next;
-	ensemblePtr->next = ensemblePtr;
-	Tcl_DeleteCommandFromToken(nsPtr->interp, ensemblePtr->token);
-    }
-
-    /*
-     * If the namespace has a registered unknown handler (TIP 181), then free
-     * it here.
-     */
-
-    if (nsPtr->unknownHandlerPtr != NULL) {
-	Tcl_DecrRefCount(nsPtr->unknownHandlerPtr);
-	nsPtr->unknownHandlerPtr = NULL;
-    }
-
-    /*
-     * If the namespace is on the call frame stack, it is marked as "dying"
-     * (NS_DYING is OR'd into its flags): the namespace can't be looked up by
-     * name but its commands and variables are still usable by those active
-     * call frames. When all active call frames referring to the namespace
-     * have been popped from the Tcl stack, Tcl_PopCallFrame will call this
-     * function again to delete everything in the namespace. If no nsName
-     * objects refer to the namespace (i.e., if its refCount is zero), its
-     * commands and variables are deleted and the storage for its namespace
-     * structure is freed. Otherwise, if its refCount is nonzero, the
-     * namespace's commands and variables are deleted but the structure isn't
-     * freed. Instead, NS_DEAD is OR'd into the structure's flags to allow the
-     * namespace resolution code to recognize that the namespace is "deleted".
-     * The structure's storage is freed by FreeNsNameInternalRep when its
-     * refCount reaches 0.
-     */
-
-    if (nsPtr->activationCount - (nsPtr == globalNsPtr) > 0) {
-	nsPtr->flags |= NS_DYING;
-	if (nsPtr->parentPtr != NULL) {
-	    entryPtr = Tcl_FindHashEntry(&nsPtr->parentPtr->childTable,
-		    nsPtr->name);
-	    if (entryPtr != NULL) {
-		Tcl_DeleteHashEntry(entryPtr);
-	    }
-	}
-	nsPtr->parentPtr = NULL;
-    } else if (!(nsPtr->flags & NS_KILLED)) {
+	
+	EstablishErrorInfoTraces(NULL, nsPtr->interp, NULL, NULL, 0);
+	EstablishErrorCodeTraces(NULL, nsPtr->interp, NULL, NULL, 0);
+	
 	/*
-	 * Delete the namespace and everything in it. If this is the global
-	 * namespace, then clear it but don't free its storage unless the
-	 * interpreter is being torn down. Set the NS_KILLED flag to avoid
-	 * recursive calls here - if the namespace is really in the process of
-	 * being deleted, ignore any second call.
+	 * We didn't really kill it, so remove the KILLED marks, so it can
+	 * get killed later, avoiding mem leaks.
 	 */
 
-	nsPtr->flags |= (NS_DYING|NS_KILLED);
-
-	TclTeardownNamespace(nsPtr);
-
-	if ((nsPtr != globalNsPtr) || (iPtr->flags & DELETED)) {
-	    /*
-	     * If this is the global namespace, then it may have residual
-	     * "errorInfo" and "errorCode" variables for errors that occurred
-	     * while it was being torn down. Try to clear the variable list
-	     * one last time.
-	     */
-
-	    TclDeleteNamespaceVars(nsPtr);
-
-	    Tcl_DeleteHashTable(&nsPtr->childTable);
-	    Tcl_DeleteHashTable(&nsPtr->cmdTable);
-
-	    /*
-	     * If the reference count is 0, then discard the namespace.
-	     * Otherwise, mark it as "dead" so that it can't be used.
-	     */
-
-	    if (nsPtr->refCount == 0) {
-		NamespaceFree(nsPtr);
-	    } else {
-		nsPtr->flags |= NS_DEAD;
-	    }
-	} else {
-	    /*
-	     * Restore the ::errorInfo and ::errorCode traces.
-	     */
-
-	    EstablishErrorInfoTraces(NULL, nsPtr->interp, NULL, NULL, 0);
-	    EstablishErrorCodeTraces(NULL, nsPtr->interp, NULL, NULL, 0);
-
-	    /*
-	     * We didn't really kill it, so remove the KILLED marks, so it can
-	     * get killed later, avoiding mem leaks.
-	     */
-
-	    nsPtr->flags &= ~(NS_DYING|NS_KILLED);
-	}
+	nsPtr->flags &= ~NS_KILLED;
     }
 }
+
 
 /*
  *----------------------------------------------------------------------
@@ -1114,6 +1023,40 @@
     Tcl_Command cmd;
     int i;
 
+    if (nsPtr->flags & NS_KILLED) {
+	return;
+    }
+    nsPtr->flags |= NS_KILLED;
+
+    /*
+     * If the namespace has associated ensemble commands, delete them first.
+     * This leaves the actual contents of the namespace alone (unless they are
+     * linked ensemble commands, of course). Note that this code is actually
+     * reentrant so command delete traces won't purturb things badly.
+     */
+
+    while (nsPtr->ensembles != NULL) {
+	EnsembleConfig *ensemblePtr = (EnsembleConfig *) nsPtr->ensembles;
+
+	/*
+	 * Splice out and link to indicate that we've already been killed.
+	 */
+
+	nsPtr->ensembles = (Tcl_Ensemble *) ensemblePtr->next;
+	ensemblePtr->next = ensemblePtr;
+	Tcl_DeleteCommandFromToken(nsPtr->interp, ensemblePtr->token);
+    }
+
+    /*
+     * If the namespace has a registered unknown handler (TIP 181), then free
+     * it here.
+     */
+
+    if (nsPtr->unknownHandlerPtr != NULL) {
+	Tcl_DecrRefCount(nsPtr->unknownHandlerPtr);
+	nsPtr->unknownHandlerPtr = NULL;
+    }
+
     /*
      * Start by destroying the namespace's variable table, since variables
      * might trigger traces. Variable table should be cleared but not freed!
@@ -1150,8 +1093,9 @@
 	if (entryPtr != NULL) {
 	    Tcl_DeleteHashEntry(entryPtr);
 	}
+	nsPtr->refCount--;
+	nsPtr->parentPtr = NULL;
     }
-    nsPtr->parentPtr = NULL;
 
     /*
      * Delete the namespace path if one is installed.
@@ -1205,16 +1149,6 @@
     }
 
     /*
-     * Free any client data associated with the namespace.
-     */
-
-    if (nsPtr->deleteProc != NULL) {
-	nsPtr->deleteProc(nsPtr->clientData);
-    }
-    nsPtr->deleteProc = NULL;
-    nsPtr->clientData = NULL;
-
-    /*
      * Reset the namespace's id field to ensure that this namespace won't be
      * interpreted as valid by, e.g., the cache validation code for cached
      * command references in Tcl_GetCommandFromObj.
@@ -1245,6 +1179,16 @@
     register Namespace *nsPtr)	/* Points to the namespace to free. */
 {
     /*
+     * Free any client data associated with the namespace.
+     */
+
+    if (nsPtr->deleteProc != NULL) {
+	nsPtr->deleteProc(nsPtr->clientData);
+    }
+    nsPtr->deleteProc = NULL;
+    nsPtr->clientData = NULL;
+
+    /*
      * Most of the namespace's contents are freed when the namespace is
      * deleted by Tcl_DeleteNamespace. All that remains is to free its names
      * (for error messages), and the structure itself.
@@ -2489,7 +2433,7 @@
 		&simpleName);
 	if ((realNsPtr != NULL) && (simpleName != NULL)) {
 	    if ((cxtNsPtr == realNsPtr)
-		    || !(realNsPtr->flags & NS_DYING)) {
+		    || !(realNsPtr->flags & NS_KILLED)) {
 		entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
 		if (entryPtr != NULL) {
 		    cmdPtr = Tcl_GetHashValue(entryPtr);
@@ -2510,7 +2454,7 @@
 		    TCL_NAMESPACE_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr,
 		    &simpleName);
 	    if ((realNsPtr != NULL) && (simpleName != NULL)
-		    && !(realNsPtr->flags & NS_DYING)) {
+		    && !(realNsPtr->flags & NS_KILLED)) {
 		entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
 		if (entryPtr != NULL) {
 		    cmdPtr = Tcl_GetHashValue(entryPtr);
@@ -2528,7 +2472,7 @@
 		    TCL_GLOBAL_ONLY, &realNsPtr, &dummyNsPtr, &dummyNsPtr,
 		    &simpleName);
 	    if ((realNsPtr != NULL) && (simpleName != NULL)
-		    && !(realNsPtr->flags & NS_DYING)) {
+		    && !(realNsPtr->flags & NS_KILLED)) {
 		entryPtr = Tcl_FindHashEntry(&realNsPtr->cmdTable, simpleName);
 		if (entryPtr != NULL) {
 		    cmdPtr = Tcl_GetHashValue(entryPtr);
@@ -2549,7 +2493,8 @@
 	 */
 
 	for (search = 0;  (search < 2) && (cmdPtr == NULL);  search++) {
-	    if ((nsPtr[search] != NULL) && (simpleName != NULL)) {
+	    if ((nsPtr[search] != NULL) &&(simpleName != NULL)
+		    && !(nsPtr[search]->flags & NS_KILLED)) {
 		entryPtr = Tcl_FindHashEntry(&nsPtr[search]->cmdTable,
 			simpleName);
 		if (entryPtr != NULL) {
@@ -2775,7 +2720,7 @@
 	resNamePtr = (ResolvedNsName *) objPtr->internalRep.twoPtrValue.ptr1;
 	nsPtr = resNamePtr->nsPtr;
 	refNsPtr = resNamePtr->refNsPtr;
-	if (!(nsPtr->flags & NS_DYING) && (interp == nsPtr->interp) &&
+	if (!(nsPtr->flags & NS_KILLED) && (interp == nsPtr->interp) &&
 		(!refNsPtr || ((interp == refNsPtr->interp) &&
 		 (refNsPtr== (Namespace *) Tcl_GetCurrentNamespace(interp))))) {
 	    *nsPtrPtr = (Tcl_Namespace *) nsPtr;
@@ -3184,7 +3129,10 @@
      */
 
     currNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
-    if (currNsPtr == (Namespace *) TclGetGlobalNamespace(interp)) {
+    if (currNsPtr->flags & NS_KILLED) {
+	Tcl_SetObjResult(interp, Tcl_NewStringObj("Current namespace is deleted", -1));
+	return TCL_ERROR;	
+    } else if (currNsPtr == (Namespace *) TclGetGlobalNamespace(interp)) {
 	Tcl_SetObjResult(interp, Tcl_NewStringObj("::", 2));
     } else {
 	Tcl_SetObjResult(interp, Tcl_NewStringObj(currNsPtr->fullName, -1));
@@ -4693,7 +4641,7 @@
 
 	nsPtr = resNamePtr->nsPtr;
 	nsPtr->refCount--;
-	if ((nsPtr->refCount == 0) && (nsPtr->flags & NS_DEAD)) {
+	if (nsPtr->refCount == 0) {
 	    NamespaceFree(nsPtr);
 	}
 	ckfree((char *) resNamePtr);
@@ -4774,7 +4722,7 @@
      * that holds a reference to it.
      */
 
-    if ((nsPtr == NULL) || (nsPtr->flags & NS_DYING)) {
+    if ((nsPtr == NULL) || (nsPtr->flags & NS_KILLED)) {
 	/*
 	 * Our failed lookup proves any previously cached nsName intrep is no
 	 * longer valid. Get rid of it so we no longer waste memory storing
@@ -4858,7 +4806,7 @@
     int index;
 
     nsPtr = (Namespace *) TclGetCurrentNamespace(interp);
-    if (nsPtr == NULL || nsPtr->flags & NS_DYING) {
+    if (nsPtr == NULL || nsPtr->flags & NS_KILLED) {
 	if (!Tcl_InterpDeleted(interp)) {
 	    Tcl_AppendResult(interp,
 		    "tried to manipulate ensemble of deleted namespace", NULL);
@@ -6369,7 +6317,7 @@
 	return TCL_ERROR;
     }
 
-    if (ensemblePtr->nsPtr->flags & NS_DYING) {
+    if (ensemblePtr->nsPtr->flags & NS_KILLED) {
 	/*
 	 * Don't know how we got here, but make things give up quickly.
 	 */
@@ -6845,7 +6793,7 @@
 	Tcl_DecrRefCount(ensembleCmd->realPrefixObj);
 	ensembleCmd->nsPtr->refCount--;
 	if ((ensembleCmd->nsPtr->refCount == 0)
-		&& (ensembleCmd->nsPtr->flags & NS_DEAD)) {
+		&& (ensembleCmd->nsPtr->flags & NS_KILLED)) {
 	    NamespaceFree(ensembleCmd->nsPtr);
 	}
 	ckfree(ensembleCmd->fullSubcmdName);
@@ -7258,7 +7206,7 @@
     ckfree(ensembleCmd->fullSubcmdName);
     ensembleCmd->nsPtr->refCount--;
     if ((ensembleCmd->nsPtr->refCount == 0)
-	    && (ensembleCmd->nsPtr->flags & NS_DEAD)) {
+	    && (ensembleCmd->nsPtr->flags & NS_KILLED)) {
 	NamespaceFree(ensembleCmd->nsPtr);
     }
     ckfree((char *) ensembleCmd);
Index: generic/tclObj.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclObj.c,v
retrieving revision 1.152
diff -u -r1.152 tclObj.c
--- generic/tclObj.c	8 May 2009 02:21:09 -0000	1.152
+++ generic/tclObj.c	9 May 2009 16:40:24 -0000
@@ -3552,9 +3552,8 @@
     if ((objPtr->typePtr != &tclCmdNameType)
 	    || (resPtr == NULL)
 	    || (cmdPtr = resPtr->cmdPtr, cmdPtr->cmdEpoch != resPtr->cmdEpoch)
-	    || (interp != cmdPtr->nsPtr->interp)
 	    || (cmdPtr->flags & CMD_IS_DELETED)
-	    || (cmdPtr->nsPtr->flags & 	NS_DYING)
+	    || (interp != cmdPtr->nsPtr->interp)
 	    || ((resPtr->refNsPtr != NULL) &&
 		     (((refNsPtr = (Namespace *) TclGetCurrentNamespace(interp))
 			     != resPtr->refNsPtr)
Index: generic/tclVar.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclVar.c,v
retrieving revision 1.178
diff -u -r1.178 tclVar.c
--- generic/tclVar.c	24 Mar 2009 09:30:07 -0000	1.178
+++ generic/tclVar.c	9 May 2009 16:40:26 -0000
@@ -894,8 +894,9 @@
      * to continue onward, or it may signal an error.
      */
 
-    if ((cxtNsPtr->varResProc != NULL || iPtr->resolverPtr != NULL)
-	    && !(flags & AVOID_RESOLVERS)) {
+    if (!(cxtNsPtr->flags & NS_KILLED)
+	    && ((cxtNsPtr->varResProc != NULL || iPtr->resolverPtr != NULL)
+		    && !(flags & AVOID_RESOLVERS))) {
 	resPtr = iPtr->resolverPtr;
 	if (cxtNsPtr->varResProc) {
 	    result = cxtNsPtr->varResProc(interp, varName,
@@ -970,7 +971,8 @@
 	    if (create) {	/* Var wasn't found so create it. */
 		TclGetNamespaceForQualName(interp, varName, cxtNsPtr,
 			flags, &varNsPtr, &dummy1Ptr, &dummy2Ptr, &tail);
-		if (varNsPtr == NULL) {
+		if ((varNsPtr == NULL) ||
+			((varNsPtr != iPtr->globalNsPtr) && (varNsPtr->flags & NS_KILLED))) {
 		    *errMsgPtr = badNamespace;
 		    return NULL;
 		} else if (tail == NULL) {
@@ -4981,6 +4983,10 @@
 	cxtNsPtr = (Namespace *) TclGetCurrentNamespace(interp);
     }
 
+    if (cxtNsPtr->flags & NS_KILLED) {
+	return NULL;
+    }
+    
     if (!(flags & AVOID_RESOLVERS) &&
 	    (cxtNsPtr->varResProc != NULL || iPtr->resolverPtr != NULL)) {
 	resPtr = iPtr->resolverPtr;
