From e0ea457f4f9e9dd8a7836e826cc9d2a5e607e698 Mon Sep 17 00:00:00 2001 From: Steve Bennett Date: Tue, 9 May 2023 23:02:53 +1000 Subject: 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 --- jim.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/jim.c b/jim.c index c752312..11f4efb 100644 --- a/jim.c +++ b/jim.c @@ -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); -- cgit v1.1