diff options
author | dgp <dgp@users.sourceforge.net> | 2016-09-09 12:42:09 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2016-09-09 12:42:09 (GMT) |
commit | f52c111f3b4848a8a63d505513bcdc0ea5c14930 (patch) | |
tree | 4aa39b66a85f72f4485c7c81543729c01d8c8090 /generic | |
parent | dfe46aaba1d57b828a9378ec10f20818087a70c8 (diff) | |
parent | f26a4a0948cbd769519cf1e79ea027511051b2bd (diff) | |
download | tcl-f52c111f3b4848a8a63d505513bcdc0ea5c14930.zip tcl-f52c111f3b4848a8a63d505513bcdc0ea5c14930.tar.gz tcl-f52c111f3b4848a8a63d505513bcdc0ea5c14930.tar.bz2 |
merge trunk
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclNamesp.c | 20 | ||||
-rw-r--r-- | generic/tclVar.c | 49 |
2 files changed, 29 insertions, 40 deletions
diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c index fc2d63d..7aacf7f 100644 --- a/generic/tclNamesp.c +++ b/generic/tclNamesp.c @@ -399,6 +399,19 @@ Tcl_PopCallFrame( register CallFrame *framePtr = iPtr->framePtr; Namespace *nsPtr; + /* + * It's important to remove the call frame from the interpreter's stack of + * call frames before deleting local variables, so that traces invoked by + * the variable deletion don't see the partially-deleted frame. + */ + + if (framePtr->callerPtr) { + iPtr->framePtr = framePtr->callerPtr; + iPtr->varFramePtr = framePtr->callerVarPtr; + } else { + /* Tcl_PopCallFrame: trying to pop rootCallFrame! */ + } + if (framePtr->varTablePtr != NULL) { TclDeleteVars(iPtr, framePtr->varTablePtr); ckfree(framePtr->varTablePtr); @@ -426,13 +439,6 @@ Tcl_PopCallFrame( } framePtr->nsPtr = NULL; - if (framePtr->callerPtr) { - iPtr->framePtr = framePtr->callerPtr; - iPtr->varFramePtr = framePtr->callerVarPtr; - } else { - /* Tcl_PopCallFrame: trying to pop rootCallFrame! */ - } - if (framePtr->tailcallPtr) { TclSetTailcall(interp, framePtr->tailcallPtr); } diff --git a/generic/tclVar.c b/generic/tclVar.c index 3db2e2c..92ca81c 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -5064,44 +5064,27 @@ TclDeleteVars( TclVarHashTable *tablePtr) /* Hash table containing variables to * delete. */ { + Tcl_Interp *interp = (Tcl_Interp *) iPtr; Tcl_HashSearch search; register Var *varPtr; + int flags; + Namespace *currNsPtr = (Namespace *) TclGetCurrentNamespace(interp); - for (varPtr = VarHashFirstVar(tablePtr, &search); varPtr != NULL; - varPtr = VarHashFirstVar(tablePtr, &search)) { - VarHashRefCount(varPtr)++; - - UnsetVarStruct(varPtr, NULL, iPtr, VarHashGetKey(varPtr), - NULL, TCL_TRACE_UNSETS, -1); - - if (TclIsVarTraced(varPtr)) { - Tcl_HashEntry *tPtr = Tcl_FindHashEntry(&iPtr->varTraces, varPtr); - VarTrace *tracePtr = Tcl_GetHashValue(tPtr); - ActiveVarTrace *activePtr; - - while (tracePtr) { - VarTrace *prevPtr = tracePtr; - - tracePtr = tracePtr->nextPtr; - prevPtr->nextPtr = NULL; - Tcl_EventuallyFree(prevPtr, TCL_DYNAMIC); - } - Tcl_DeleteHashEntry(tPtr); - varPtr->flags &= ~VAR_ALL_TRACES; - for (activePtr = iPtr->activeVarTracePtr; activePtr != NULL; - activePtr = activePtr->nextPtr) { - if (activePtr->varPtr == varPtr) { - activePtr->nextTracePtr = NULL; - } - } - } + /* + * Determine what flags to pass to the trace callback functions. + */ - if (!TclIsVarUndefined(varPtr)) { - UnsetVarStruct(varPtr, NULL, iPtr, VarHashGetKey(varPtr), - NULL, TCL_TRACE_UNSETS, -1); - } + flags = TCL_TRACE_UNSETS; + if (tablePtr == &iPtr->globalNsPtr->varTable) { + flags |= TCL_GLOBAL_ONLY; + } else if (tablePtr == &currNsPtr->varTable) { + flags |= TCL_NAMESPACE_ONLY; + } - VarHashRefCount(varPtr)--; + for (varPtr = VarHashFirstVar(tablePtr, &search); varPtr != NULL; + varPtr = VarHashFirstVar(tablePtr, &search)) { + UnsetVarStruct(varPtr, NULL, iPtr, VarHashGetKey(varPtr), NULL, flags, + -1); VarHashDeleteEntry(varPtr); } VarHashDeleteTable(tablePtr); |