diff options
| author | dgp <dgp@users.sourceforge.net> | 2016-09-07 18:09:30 (GMT) |
|---|---|---|
| committer | dgp <dgp@users.sourceforge.net> | 2016-09-07 18:09:30 (GMT) |
| commit | 35141afcc9ca65b400d055d491a343b74b133e15 (patch) | |
| tree | ee41ace108164ac84cf9846a9512b9b7290abcd3 /generic/tclVar.c | |
| parent | 4ef0c69aaadaecd18748067dce66645646fcbd88 (diff) | |
| parent | 6053836b9780c7e74540700e2e2ea602b6c30101 (diff) | |
| download | tcl-35141afcc9ca65b400d055d491a343b74b133e15.zip tcl-35141afcc9ca65b400d055d491a343b74b133e15.tar.gz tcl-35141afcc9ca65b400d055d491a343b74b133e15.tar.bz2 | |
[4dbdd9af14] Plug mem leak when var unset trace re-creates namespace var. Thanks mr_calvin for report and fix.
Diffstat (limited to 'generic/tclVar.c')
| -rw-r--r-- | generic/tclVar.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/generic/tclVar.c b/generic/tclVar.c index 20bc208..48e09f6 100644 --- a/generic/tclVar.c +++ b/generic/tclVar.c @@ -4956,13 +4956,16 @@ TclDeleteNamespaceVars( VarHashRefCount(varPtr)++; /* Make sure we get to remove from * hash. */ Tcl_GetVariableFullName(interp, (Tcl_Var) varPtr, objPtr); - UnsetVarStruct(varPtr, NULL, iPtr, /* part1 */ objPtr, NULL, flags, - -1); - Tcl_DecrRefCount(objPtr); /* Free no longer needed obj */ + UnsetVarStruct(varPtr, NULL, iPtr, /* part1 */ objPtr, + NULL, flags, -1); /* - * Remove the variable from the table and force it undefined in case - * an unset trace brought it back from the dead. + * We just unset the variable. However, an unset trace might + * have re-set it, or might have re-established traces on it. + * This namespace and its vartable are going away unconditionally, + * so we cannot let such things linger. That would be a leak. + * + * First we destroy all traces. ... */ if (TclIsVarTraced(varPtr)) { @@ -4986,6 +4989,17 @@ TclDeleteNamespaceVars( } } } + + /* + * ...and then, if the variable still holds a value, we unset it + * again. This time with no traces left, we're sure it goes away. + */ + + if (!TclIsVarUndefined(varPtr)) { + UnsetVarStruct(varPtr, NULL, iPtr, /* part1 */ objPtr, + NULL, flags, -1); + } + Tcl_DecrRefCount(objPtr); /* free no longer needed obj */ VarHashRefCount(varPtr)--; VarHashDeleteEntry(varPtr); } |
