From f03ef4e180132f71c77f3071312bb7bb9bbbc0f5 Mon Sep 17 00:00:00 2001 From: Nick Anderson Date: Thu, 4 Jun 2026 14:26:19 -0500 Subject: [PATCH 1/2] Fix memory leak of existing_info in EvalContextHeapPersistentSave existing_info was allocated via xcalloc but never freed on the early-return (preserve) path, the early-return (read error) path, or the normal fall-through path. (cherry picked from commit 9eaebefc0618336d2ff44ffe1a98b3c5b9080eae) --- libpromises/eval_context.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libpromises/eval_context.c b/libpromises/eval_context.c index f13c502213..3fc565cde9 100644 --- a/libpromises/eval_context.c +++ b/libpromises/eval_context.c @@ -723,6 +723,7 @@ void EvalContextHeapPersistentSave(EvalContext *ctx, const char *name, unsigned Log(LOG_LEVEL_VERBOSE, "Persistent class '%s' is already in a preserved state -- %jd minutes to go", key, (intmax_t)((existing_info->expires - now) / 60)); CloseDB(dbp); + free(existing_info); free(key); free(new_info); return; @@ -732,10 +733,12 @@ void EvalContextHeapPersistentSave(EvalContext *ctx, const char *name, unsigned { Log(LOG_LEVEL_ERR, "While persisting class '%s', error reading existing value", key); CloseDB(dbp); + free(existing_info); free(key); free(new_info); return; } + free(existing_info); } } From 52b786588076e52e54bf6c9b5bff7c366d6f1be4 Mon Sep 17 00:00:00 2001 From: Nick Anderson Date: Thu, 4 Jun 2026 14:26:50 -0500 Subject: [PATCH 2/2] Improve persistent class logging in EvalContextHeapPersistentSave Replace the generic "Updating persistent class" verbose message with context-aware messages that distinguish between: - Creating a new persistent class (no prior DB record) - Resetting a timer (existing record, policy=reset) - Updating a preserved class (tags changed or class expired) This makes it easier to diagnose persistent class timer behavior from verbose logs without needing to add custom debugging builds. Ticket: ENT-3868 Changelog: Title (cherry picked from commit 51650ed31fc8e6e461ba796a5a9bff20187d8875) --- libpromises/eval_context.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/libpromises/eval_context.c b/libpromises/eval_context.c index 3fc565cde9..dd3b5beb80 100644 --- a/libpromises/eval_context.c +++ b/libpromises/eval_context.c @@ -728,6 +728,18 @@ void EvalContextHeapPersistentSave(EvalContext *ctx, const char *name, unsigned free(new_info); return; } + else if (policy == CONTEXT_STATE_POLICY_RESET) + { + Log(LOG_LEVEL_VERBOSE, + "Resetting persistent class '%s' timer to %u minutes (was %jd minutes remaining)", + key, ttl_minutes, (intmax_t)((existing_info->expires - now) / 60)); + } + else + { + Log(LOG_LEVEL_VERBOSE, + "Updating persistent class '%s' (%u minutes, policy preserve)", + key, ttl_minutes); + } } else { @@ -740,10 +752,15 @@ void EvalContextHeapPersistentSave(EvalContext *ctx, const char *name, unsigned } free(existing_info); } + else + { + Log(LOG_LEVEL_VERBOSE, + "Creating persistent class '%s' (%u minutes, policy %s)", + key, ttl_minutes, + policy == CONTEXT_STATE_POLICY_PRESERVE ? "preserve" : "reset"); + } } - Log(LOG_LEVEL_VERBOSE, "Updating persistent class '%s'", key); - WriteDB(dbp, key, new_info, new_info_size); CloseDB(dbp);