aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2023-05-09 23:02:53 +1000
committerSteve Bennett <steveb@workware.net.au>2023-05-09 23:06:07 +1000
commite0ea457f4f9e9dd8a7836e826cc9d2a5e607e698 (patch)
tree8b1e911f7bfa7c4583dab41b8fb56dc9034730b4
parent0c855d13af706bbf9c6b7a53a5161c50d562b269 (diff)
downloadjimtcl-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.c25
1 files 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);