myxce/.wolf/bugs/bug-1929.md
Rongsong Shen c3cdf2f515
docs(buglog): bug-1928, bug-1929, bug-1930 fixed (ba6f42cd)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-09 03:37:04 +00:00

8.6 KiB

id status status_updated status_note component severity timestamp last_seen occurrences files tags related fix_commits
bug-1929 fixed 2026-10-09 scheduler wrong-result 2026-10-09T03:21:26Z 2026-10-09T03:21:26Z 1
src/scheduler/src/repl_rollup.c
src/scheduler/src/repl_break.c
src/scheduler/src/repl_internal.h
src/scheduler/testsuite/test_repl_round_rollup.c
src/scheduler/testsuite/test_repl_trace_emit.c
src/scheduler/testsuite/test_repl_trace_wiring.c
src/scheduler/testsuite/fixtures/repl_trace_baseline/transcript.txt
repl
sim
rollup
continue
output
bug-1610
bug-1611
ba6f42cd

bug-1929: xce_scheduler --sim REPL continue round summary prints empty jobids= for a dispatch-only round

Description

Observed: in continue mode a round whose only decision is a dispatch prints a round summary with an empty job list, with tracing off as well as on. From the 6.3 trace-equivalence harness (XCE_TRACE_EQUIV_DUMP=1, extra replay, 8 occurrences):

[sim] round 1-1 (1 round(s), t=1970-01-01T00:00:00Z..1970-01-01T00:00:00Z): 4 dispatch, 1 pend, 0 preempt -- jobids=0-0-0-202
[sim] round 2-2 (1 round(s), t=1970-01-01T00:00:00Z..1970-01-01T00:00:00Z): 1 dispatch, 0 pend, 0 preempt -- jobids=

With the 1.1 contention fixture the dispatched job is missing even when a pend job is listed (round 8 dispatched 0-0-0-108):

[sim] round 8-8 (1 round(s), t=1970-01-01T00:00:00Z..1970-01-01T00:00:00Z): 1 dispatch, 1 pend, 0 preempt -- jobids=0-0-0-107

Expected: "jobids=" names the jobs the round's decisions affected (scheduler-sim-repl-verbosity Requirement 2.1: "the count of each decision type and the identifiers of the jobs affected"), so the dispatched (and preempted) jobs are listed: jobids=0-0-0-202 (the job pending in round 1 and dispatched in round 2) and jobids=0-0-0-107,0-0-0-108. Impact: wrong/misleading REPL output only: the operator cannot see which job a round dispatched or preempted. A second effect of the same cause: rounds with the same counts and pend set but different dispatched jobs collapse into one range (Requirement 3.2 says a range needs the same affected job identifiers). Scheduling decisions are not affected. Found by: scheduler-sim-decision-trace validation (rollup output in the 6.1/6.3 e2e and equivalence harness dumps).

Environment

  • OS: no /etc/os-release; Docker container; NixOS kernel; kernel Linux 6.18.33 x86_64
  • libc: glibc 2.42-47 (interpreter /nix/store/wb6rhpznjfczwlwx23zmdrrw74bayxw4-glibc-2.42-47/lib/ld-linux-x86-64.so.2)
  • Toolchain: gcc (GCC) 15.2.0, meson 1.9.1
  • Build: asan (xce.build), tests run with ASAN_OPTIONS=detect_leaks=0 (suite convention for these binaries); the symptom does not depend on sanitizer options or on tracing
  • Code: scheduler-framework @ 5ca59dc9-dirty
  • Deployment: standalone simulator only (xce_scheduler --sim ... --interactive), no controller, no workers; single dev host

Reproduction

  1. Build: bash src/tools/xce-build.sh scheduler --jobs 12 --incremental at the Environment commit.
  2. cd src/xce.build/scheduler/testsuite && XCE_TRACE_EQUIV_DUMP=1 ASAN_OPTIONS=detect_leaks=0 ./sched_trace_equivalence_test 2>&1 | grep 'jobids=$' -- 8 lines ... 1 dispatch, 0 pend, 0 preempt -- jobids=.
  3. Contention fixture: printf 'continue\nquit\n' | TERM=dumb src/xce.build/scheduler/xce_scheduler --sim src/scheduler/testsuite/fixtures/repl_trace_baseline/contention.replay --interactive --logfile <tmp>/sched.log (repo root; with bug-1928 unfixed add ASAN_OPTIONS=detect_leaks=0) -- round 8-8 lists only 0-0-0-107; rounds 1-1 and 5-5 list only the pend set.
  4. Smallest: test_round_summary_lists_dispatched_jobids_golden in test_repl_round_rollup.c (drives xce_repl_on_begin_round/xce_repl_on_decision/repl_round_rollup_process directly).
  • Frequency: deterministic (every run, 2026-10-09)
  • Evidence: /home/claude/tmp/bug-1929/ -- equiv-dump-red.txt / equiv-dump-green.txt, e2e-dump-red.txt, contention-continue-red.txt / contention-continue-green.txt, rollup-red.txt, transcript.diff, fixture-backup/ (the baseline fixtures before regeneration)

Root cause

repl_round_emit() (src/scheduler/src/repl_rollup.c:178, listing built at :201-202 before the fix) built the "jobids=" listing from pend_jobids only, and repl_round_rollup_process() (repl_rollup.c:285) only ever collected the pend set (repl_query_pend_jobids(), a walk of core->jobs for JOB_IS_PEND jobs). The dispatch and preempt decisions were counted in xce_repl_on_decision() (src/scheduler/src/repl_break.c:953-959, last_n_dispatch/last_n_preempt) but their job ids were never recorded anywhere. A dispatched job is no longer pending after the round, so a dispatch-only round has an empty pend set and printed jobids= with nothing after it; in mixed rounds the dispatched jobs were silently left out. The same pend-only fingerprint made rounds that dispatched different jobs compare equal and collapse.

Since: 921c72bb (scheduler-sim-repl-verbosity task 2.2, Round Rollup), written while bug-1611 meant the simulator produced no DISPATCH decisions, so the pend set was the only affected-job information then.

Scope: the traced-round path (scheduler-sim-decision-trace 7.3/7.4) and the allocation-failure fallback go through the same repl_round_emit(); step mode prints per-decision lines and was not affected.

Fix

  • src/scheduler/src/repl_internal.h: new state in xce_sched_repl_state_s -- round_decided_jobids/round_n_decided/round_cap_decided/round_decided_lost (this round's dispatch/preempt jobids) and collapse_decided_jobids/collapse_n_decided_jobids (the active range's); declarations of repl_round_note_decided()/repl_round_reset_decided().
  • src/scheduler/src/repl_break.c: xce_repl_on_decision() records the jobid of each DISPATCH and PREEMPT decision (a decision with no body, jobid 0, is skipped); xce_repl_on_begin_round() resets the per-round list.
  • src/scheduler/src/repl_rollup.c: repl_round_rollup_process() takes over the round's list (sorted, de-duplicated) and makes it part of the fingerprint next to the counts and the pend set, so rounds collapse only when the affected jobs match; repl_round_emit() lists the union of the pend set and the dispatch/preempt set (repl_fmt_affected(), through the existing repl_fmt_jobid_range() compressor) and takes the pend count separately; repl_round_collapse_flush() frees the new list. If the per-round list cannot grow (out of memory) or the pend set cannot be built, the round is reported on its own with jobids=(unavailable) instead of an empty or partial list.
  • Tests: test_repl_trace_emit.c and test_repl_trace_wiring.c teardowns free the new lists (both run with leak detection on).
  • src/scheduler/testsuite/fixtures/repl_trace_baseline/transcript.txt regenerated (XCE_REPL_BASELINE_REGEN=1, .replay fixtures restored from the backup): exactly two lines change, both jobids= lines -- round 5-5 jobids=0-0-0-107 -> jobids=0-0-0-104,0-0-0-105,0-0-0-106,0-0-0-107 and round 8-8 jobids=0-0-0-107 -> jobids=0-0-0-107,0-0-0-108.

Output format change: "jobids=" now means every job the range's decisions affected (Requirement 2.1), not only the jobs left pending; the counts are unchanged.

Verification

  • Test: test_round_summary_lists_dispatched_jobids_golden in src/scheduler/testsuite/test_repl_round_rollup.c (exact golden lines for two dispatch-only rounds of different jobs, and a dispatch+preempt round): RED before the fix -- Expected '[sim] round 1-1 ...: 1 dispatch, 0 pend, 0 preempt -- jobids=0-0-0-5101\n[sim] round 2-2 ...: 1 dispatch, 0 pend, 0 preempt -- jobids=0-0-0-5102\n' Was '[sim] round 1-2 (2 round(s), ...): 1 dispatch, 0 pend, 0 preempt -- jobids=\n' -- GREEN after (8 Tests 0 Failures). scheduler repl trace baseline test with the regenerated transcript: GREEN (4 Tests 0 Failures, leak detection on).
  • Harness: equivalence dump (XCE_TRACE_EQUIV_DUMP=1) has 8 empty jobids= lines before and 0 after; all 8 dispatch-only rounds now read round 2-2 ... 1 dispatch, 0 pend, 0 preempt -- jobids=0-0-0-202 (equiv-dump-green.txt).
  • Suites: bash src/tools/xce-build.sh scheduler --jobs 12 --incremental: scheduler suite 118/118 OK, asan (log: /home/claude/tmp/bug-1929/gate-scheduler-suite.log).
  • Live: standalone contention run (Reproduction step 3) after the fix: round 8-8 jobids=0-0-0-107,0-0-0-108, round 1-1 lists 101-107 (contention-continue-green.txt).

References

  • Related: bug-1611 (no DISPATCH decisions in sim at the time the rollup was written), bug-1610 (rollup introduced to replace per-decision lines)
  • Docs: .kiro/specs/scheduler-sim-repl-verbosity/requirements.md (Requirement 2.1, 3.2); src/scheduler/testsuite/fixtures/repl_trace_baseline/transcript.txt