fix(scheduler): sim mode picker never learns about the initial snapshot's own jobs/queues (bug-1567)

xce_scheduler -i -s <replay>: WARN "failed to resolve job picker
plugin (rc=-2)" on load, and every job already present in the
replay file's INITIAL snapshot stayed PEND forever -- never even
reached the picker, let alone got dispatched.

Root cause: sched_sim_driver_start() (sim.c) loads the initial
snapshot via xce_sched_core_load_snapshot() BEFORE any picker
plugin is registered (sim.h's own documented "Known scope
boundary" -- only the picker's NAME is threaded through from the
ReplayHeader). sched_resolve_job_picker() therefore always returns
-ENOENT there, and xce_sched_core_load_snapshot()'s own
picker-rebuild walk (on_queue_update/on_job_push per queue/job) is
silently skipped. The real builtin_fcfs picker only gets registered
moments later in sched_sim_driver_run() -- but nothing then replayed
that rebuild walk, so any job/queue from the INITIAL snapshot (as
opposed to one arriving later via a ReplayEvent, which correctly
reaches the picker through xce_core_push_events()'s own picker!=NULL
check) was permanently invisible to next_job().

Fixed by a new file, sim_picker.c: sim_bootstrap_picker() (replacing
sim_loop.c's sim_register_default_picker(), moved out because
sim_loop.c was already at its own documented 800-line "zero
line-budget headroom" cap) registers the picker AND then replays the
missed rebuild walk against it. Wired into scheduler_srcs,
sched_sim_isolation_lib, and all 9 white-box test TUs that #include
sim_loop.c directly.

New regression test (test_sim_event_loop.c): a job baked into a
fixture's INITIAL snapshot (not a ReplayEvent) now gets a live PEND
decision. RED confirmed by temporarily no-op'ing the rebuild walk
(test failed as expected), GREEN with the real fix. Full scheduler
suite green (41/41, excluding the pre-existing unrelated bug-1560).

Note: sim mode still never DISPATCHes (only PENDs) -- that is a
separate, intentionally out-of-scope gap (real resource-matching
allocation belongs to the not-yet-designed scheduler-allocation
spec), not addressed here.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-08-17 10:21:11 +00:00
parent 0f1df4998e
commit 0c8e417bda
Signed by: rshen
SSH key fingerprint: SHA256:8Vf2pZ3h6rJa7EhGK+WaAQ9Mta/apZvteW6g9U/WKKk
14 changed files with 395 additions and 93 deletions

View file

@ -524,7 +524,8 @@ sched_sim_event_loop_test = executable(
# boundary doc comment legitimately names xcecli_ctx_t/xce_cluster_config_t
# in prose). link_with establishes the build-order dependency on
# sched_sim_isolation_lib (parent meson.build -- sim.c + sim_loop.c +
# sim_record.c compiled together, isolated from the rest of the scheduler);
# sim_picker.c (bug-1567's sim_loop.c-cap-driven sibling) + sim_record.c
# compiled together, isolated from the rest of the scheduler);
# XCE_SIM_*_PATH bake in absolute paths the same way XCE_CORE_*_PATH does
# above.
sched_sim_isolation_test = executable(
@ -542,6 +543,9 @@ sched_sim_isolation_test = executable(
'-DXCE_SIM_LOOP_C_PATH="'
+ (meson.current_source_dir() / '..' / 'src' / 'sim_loop.c')
+ '"',
'-DXCE_SIM_PICKER_C_PATH="'
+ (meson.current_source_dir() / '..' / 'src' / 'sim_picker.c')
+ '"',
'-DXCE_SIM_RECORD_C_PATH="'
+ (meson.current_source_dir() / '..' / 'src' / 'sim_record.c')
+ '"',