fix(scheduler): free registry entries after their tables at core teardown; fix dup_val and the unmeet re-init leak (bug-1884, part 5)

A failed key_add() runs the table's datakiller on the rejected value, and
callers keep using it (JOBS_PUSH merges a duplicate job into the existing
one; sched_init_queues() re-adds every queue on each config apply), so the
job, queue, worker and resource datakillers must stay shallow. Part 4 made
kill_sched_job() free the whole job; that is reverted. Instead
xce_sched_core_fini() collects each table's entries, destroys the table,
then frees each entry with a full destructor (core.c). The resource table
is released the same way (a reference per resobj).

Also:
- dup_val() tested which == XCE_VAL_STRING (0, the resource value type,
  equal to Value_u_ivalue32): real string values were shallow-copied and a
  nonzero int32 went to makeString() as a pointer. It now tests
  Value_u_svalue and strdup()s, as free_Value() expects.
- The shared/host satisfy checks re-initialize the unmeet vector they are
  given; the allocators passed the ctx's live one, dropping its buffers on
  every candidate host. The callers finalize it first.
- add_vres() registers a resobj via makeResource(), like every other
  resource, instead of a bare calloc(); test_limit.c drops it with
  dereference().
- plugin_register_core() rejects a duplicate name before init_fn/key_add,
  since a failed add now finalizes (frees) the plugin and callers free it
  on failure.
- sharedInUse gets kill_sched_resval, as put_resvals() fills it.

Exit-time leak on the reproduction replay 7,469 -> 928 bytes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-09-29 09:28:08 +00:00
parent ebfe4794f0
commit c1cd8f917d
Signed by untrusted user: rshen
GPG key ID: 80533536B0EB651C
11 changed files with 216 additions and 122 deletions

View file

@ -221,7 +221,6 @@ extern int sched_ctx_get_uncomit_shared(xvec_t**, xce_sched_ctx_t*);
extern int sched_ctx_get_uncomit_host(xvec_t**, xce_sched_ctx_t*, int);
extern int sched_ctx_uncommit_host(xce_sched_ctx_t*, int, xvec_idval_t*);
extern void reset_sched_obj(xce_sched_obj_t*);
extern void kill_sched_obj(xce_sched_obj_t*);
/* item killer for xce_sched_obj_t.hlimits: frees one per-worker xlist_t
* (never its vres entries, which the limit plugin's instance table owns). */
extern void kill_hlimits_list(void*);