--- id: "bug-1801" status: "fixed" status_updated: "2026-09-24" status_note: "" component: "scheduler" severity: "unknown" timestamp: "2026-09-11T08:35:00Z" last_seen: "2026-09-19T09:00:00Z" occurrences: 1 files: ["src/scheduler/src/resource.c"] tags: ["scheduler", "resource-accounting", "resInUse", "sched_account_jobs", "sched_update_account", "worker-rejoin-resync", "IS_WORKER_RECONCILING", "IS_WORKER_UNAVAIL", "over-commit", "slots", "bug-1751-interaction", "tdd", "user-requested"] related: ["bug-1799", "bug-1751", "bug-1739", "bug-1734", "bug-1624", "bug-1727"] legacy: true gitea_issue: 270 gitea_synced_status: "fixed" --- # bug-1801: Follow-up fix for bug-1799 (user asked to 'fix bug-1799', this session): the resInUse over-commit… ## Description Follow-up fix for bug-1799 (user asked to 'fix bug-1799', this session): the resInUse over-commit caused by core_reset_workers()'s RECONCILING/UNAVAIL reset-skip (bug-1751) having no matching skip in sched_account_jobs()'s per-round re-derive pass. ## Environment _Not recorded (migrated from buglog.json)._ ## Reproduction _Not recorded (migrated from buglog.json)._ ## Root cause See bug-1799's own entry for the full mechanism. Confirmed exactly as diagnosed: sched_update_account() (resource.c, the function both sched_charge_account() and sched_account_jobs()'s per-round resum ultimately call) had no IS_WORKER_UNAVAIL/IS_WORKER_RECONCILING check in its per-host charge loop, so a job on a worker mid-resync got its charge re-added every round on top of the not-reset total. ## Fix FIXED (2026-09-11). Added `if (IS_WORKER_UNAVAIL(w->status) || IS_WORKER_RECONCILING(w->status)) { continue; }` to sched_update_account()'s per-host loop (resource.c), right after resolving the worker `w`, before the sched_update_res_accounts() charge call -- the exact same combined status check core_reset_workers()/sched_reset_worker_() already use for the reset half (bug-1751), restoring the 'resum only what reset also touched' symmetry. Scoped to the per-host branch only: core->sharedInUse's own reset (core_reset_shared_resval()) is unconditional with no per-worker gating, so the shared-resource charge is untouched. This is a single-point fix (sched_update_account() backs both sched_charge_account()/sched_uncharge_account()), so it also applies (harmlessly/defensively -- a RECONCILING/UNAVAIL worker should never be a fresh DISPATCH target per the existing bug-1745/1751 candidate-filter exclusion) to the dispatch-time charge path via sched_commit_job_alloc(). TDD: added test_charge_account_skips_reconciling_or_unavail_worker_host_charge (test_resource_accounting.c) -- charges a job account against a worker flagged RECONCILING then UNAVAIL (per-host resInUse must stay 0 both times, shared resInUse still charges normally), then clears the status bit and re-charges (must resume normally on the very next call, proving this is a per-call skip, not a permanent block). RED confirmed by temporarily reverting the skip and rebuilding (`xce-build.sh scheduler asan xce.build --incremental`): exactly this one new test failed (`Expected 0 Was 2.5`), 76 other tests green. GREEN confirmed after restoring the fix: 77/77 Ok, zero regressions. ## Verification _Not recorded (migrated from buglog.json)._ ## References - Related: bug-1799, bug-1751, bug-1739, bug-1734, bug-1624, bug-1727 - Gitea: #270