Merge pull request 'runtime: state_get leaked its value on every call' (#140) from fix/state-get-leak into dev
El SDK CI - dev / build-and-test (push) Failing after 14m5s

This commit was merged in pull request #140.
This commit is contained in:
2026-08-16 13:09:58 +00:00
+16 -3
View File
@@ -5168,10 +5168,23 @@ el_val_t state_get(el_val_t key) {
if (!k) return el_wrap_str(el_strdup(""));
pthread_mutex_lock(&_state_mu);
StateEntry* e = state_find(k);
char* result = el_strdup_persist(e ? e->value : "");
/* ONE arena-tracked copy, taken under the lock.
*
* This used to make TWO copies: an el_strdup_persist temporary, then an
* arena-tracked copy of that temporary. The persistent one was never
* returned and never freed el_strdup_persist bypasses the arena by
* design ("state_set, engram internals"), so arena-pop could not reclaim
* it. Every state_get therefore leaked its full value string, permanently.
*
* The soul's awareness loop has 68 state_get call sites and ticks every
* 200ms; measured leak was ~1.1 MB per tick, about 19 GB/hour. It went
* unnoticed for as long as the soul restarted often enough to mask it.
*
* el_strdup tracks into the thread-local arena, which touches no shared
* state, so doing it under _state_mu is safe and removes the need for the
* temporary entirely. */
char* copy = el_strdup(e ? e->value : "");
pthread_mutex_unlock(&_state_mu);
/* wrap in arena-tracked copy for the caller's request lifetime */
char* copy = el_strdup(result);
return el_wrap_str(copy);
}