Fix remove cached eval scripts on engine unregister (#3503)

Remove eval script cache entries that belong to a scripting engine when
that engine is unregistered. This prevents the eval cache from retaining
dangling engine pointers and keeps the tracked script memory in sync
after engine shutdown.

The scripting engine unregister path now invokes a new eval cleanup
helper, which scans the cached scripts, drops matching entries from the
LRU list and dictionary, and adjusts cache memory accounting accordingly.

* scripting engine
* eval cache

Signed-off-by: Eran Ifrah <eifrah@amazon.com>
This commit is contained in:
eifrah-aws
2026-04-27 06:29:20 +03:00
committed by GitHub
parent 28ecbd204f
commit 6dbb7f81a9
3 changed files with 25 additions and 0 deletions
+20
View File
@@ -181,6 +181,26 @@ void evalRelease(int async) {
}
}
/* Remove all cached eval scripts associated with the given scripting engine.
* Called when a scripting engine is unregistered to avoid dangling engine
* pointers in the eval script cache. */
void evalRemoveScriptsFromEngine(scriptingEngine *engine) {
dictIterator *iter = dictGetSafeIterator(evalCtx.scripts);
dictEntry *entry;
while ((entry = dictNext(iter))) {
evalScript *es = dictGetVal(entry);
if (es->engine == engine) {
sds sha = dictGetKey(entry);
evalCtx.scripts_mem -= sdsAllocSize(sha) + getStringObjectSdsUsedMemory(es->body);
if (es->node) {
listDelNode(evalCtx.scripts_lru_list, es->node);
}
dictDelete(evalCtx.scripts, sha);
}
}
dictReleaseIterator(iter);
}
void evalReset(int async) {
evalRelease(async);
evalInit();
+3
View File
@@ -1,8 +1,11 @@
#ifndef _EVAL_H_
#define _EVAL_H_
typedef struct scriptingEngine scriptingEngine;
void evalInit(void);
void evalReset(int async);
void evalRemoveScriptsFromEngine(scriptingEngine *engine);
void *evalActiveDefragScript(void *ptr);
#endif /* _EVAL_H_ */
+2
View File
@@ -7,6 +7,7 @@
#include "scripting_engine.h"
#include "bio.h"
#include "dict.h"
#include "eval.h"
#include "functions.h"
#include "module.h"
#include "server.h"
@@ -178,6 +179,7 @@ int scriptingEngineManagerUnregister(const char *engine_name) {
scriptingEngine *e = dictGetVal(entry);
functionsRemoveLibFromEngine(e);
evalRemoveScriptsFromEngine(e);
engineMemoryInfo mem_info = scriptingEngineCallGetMemoryInfo(e, VMSE_ALL);
engineMgr.total_memory_overhead -= zmalloc_size(e) +