diff options
author | Steve Bennett <steveb@workware.net.au> | 2023-05-09 23:02:53 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2023-05-09 23:06:07 +1000 |
commit | e0ea457f4f9e9dd8a7836e826cc9d2a5e607e698 (patch) | |
tree | 8b1e911f7bfa7c4583dab41b8fb56dc9034730b4 | |
parent | 0c855d13af706bbf9c6b7a53a5161c50d562b269 (diff) | |
download | jimtcl-e0ea457f4f9e9dd8a7836e826cc9d2a5e607e698.zip jimtcl-e0ea457f4f9e9dd8a7836e826cc9d2a5e607e698.tar.gz jimtcl-e0ea457f4f9e9dd8a7836e826cc9d2a5e607e698.tar.bz2 |
core: avoid rare crash on shutdown
If deferred commands run on shutdown as stack frames
are unwound, it is possible that a command
is deleted but a later command still has a reference to it.
So instead of trying to optimise this case by freeing immediately,
cache deleted commands and let the be freed once all stack frames
are destroyed.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r-- | jim.c | 25 |
1 files changed, 11 insertions, 14 deletions
@@ -3828,20 +3828,16 @@ static void JimDecrCmdRefCount(Jim_Interp *interp, Jim_Cmd *cmdPtr) JimDecrCmdRefCount(interp, cmdPtr->prevCmd); } - if (interp->quitting) { - Jim_Free(cmdPtr); - } - else { - /* Preserve the structure with inUse = 0 so that - * cached references will continue to work. - * These will be discarding at the next procEpoch increment - * or once 1000 have been accumulated. - */ - cmdPtr->prevCmd = interp->oldCmdCache; - interp->oldCmdCache = cmdPtr; - if (++interp->oldCmdCacheSize >= 1000) { - Jim_InterpIncrProcEpoch(interp); - } + /* Preserve the structure with inUse = 0 so that + * cached references will continue to work. + * These will be discarding at the next procEpoch increment + * or once 1000 have been accumulated (unless quitting + * since we can only be unwinding in that case). + */ + cmdPtr->prevCmd = interp->oldCmdCache; + interp->oldCmdCache = cmdPtr; + if (!interp->quitting && ++interp->oldCmdCacheSize >= 1000) { + Jim_InterpIncrProcEpoch(interp); } } } @@ -5756,6 +5752,7 @@ void Jim_FreeInterp(Jim_Interp *i) Jim_DecrRefCount(i, i->currentScriptObj); Jim_DecrRefCount(i, i->nullScriptObj); + /* This will disard any cached commands */ Jim_InterpIncrProcEpoch(i); Jim_FreeHashTable(&i->commands); |