xce_core_push_events() WARNed on every JOBS_PUSH resync redelivery
(sched_add_job rc=-EEXIST), which is the expected outcome under
on_scheduler_join()'s full resync or the array-push dedup race
(bug-1734/bug-1714) and flooded operational logs. Only that case now
logs via a new DBG() macro (utils.h); any other add_rc (e.g. -ENOMEM)
still WARNs. DBG is named to avoid colliding with the build's own
-DDEBUG command-line define (debug/asan buildtypes).
Also collapsed hash_string()'s duplicated djb2 loop to delegate to
hash_block(), which already implements the same RUN_HASH loop.
Logged as bug-1809 in .wolf/buglog.json.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
Adds xce_compose_version_ex() as a sibling of the existing, completely
untouched xce_compose_version(): when dirty_fingerprint is non-empty, it
strips a trailing -dirty from the commit field (anchored tail-slice
strcmp, not a substring search) and appends -<dirty_fingerprint> instead;
when empty/NULL, it delegates directly to the original function, so
output is structurally guaranteed byte-identical -- including the
Requirement 5.2 fallback case (dirty tree, fingerprint computation
failed) where commit_id's own pre-existing -dirty suffix already signals
"modified" with no new sentinel needed.
No main.c call sites touched -- consuming daemons (tasks 3.2/3.3) still
call the original xce_compose_version() and will switch to the new
function themselves.
Verified independently by review, full lib suite on both debug and ASAN
profiles: 301 tests, 0 failures, 0 ignored; suffix-anchoring, buffer
safety, and the empty-fingerprint delegation path all confirmed correct
by hand-tracing the implementation, not just trusting the test results.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds xce_version_field()/xce_compose_version() (utils.h/utils.c) to
compose a version string carrying commit id + build time, rendering
"unknown" for either field when its underlying meson-supplied define is
empty -- ready for controller/scheduler/worker to consume.
MK_VERSION/STR (the pre-existing, compile-time-only macro pair) can't
express this empty-to-"unknown" substitution at the preprocessor level,
so this is a runtime mechanism instead. Round 1 review REJECTED an
earlier version of this task for silently orphaning MK_VERSION/STR
(the task explicitly asked to "extend" them) and for leaving an
undocumented architectural trap: argp_program_version is a file-scope
const char* initialized at compile time, which cannot call a runtime
function -- consuming code must instead compute into a static buffer
inside main() and assign the pointer before argp_parse() runs. Round 2
adds an explicit SUPERSEDED doc comment on MK_VERSION/STR plus NOTE FOR
CALLERS guidance covering both points, and was APPROVED.
Also expands task 3.2's boundary to include controller/testsuite/test.c
(a third MK_VERSION/STR call site discovered during review) so no
caller of the superseded macro survives implementation.
5 new unit tests in test_utils.c (RED->GREEN, TDD).
Task 3.1/13 of build-time-versioning.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The E_XCE_* enum (errnox.h) gained NOMASTER/REDIRECT/NOT_READY/STANDBY
(10011-10014) but xce_err_str[] still had only 10 strings + NULL, while the
bounds check used E_XCE_MAX. Formatting any of those codes ran off the array:
NOMASTER -> strncpy(NULL) deref; NOT_READY (10013, returned by ctrlstatus on a
failover-exhausted cluster) -> read 8 bytes past the 88-byte table = the ASAN
global-buffer-overflow at utils.c:335.
Fix: fill the table for all 14 codes; bound xce_strerror_r against the actual
array size + NULL (degrade to 'unknown error', never OOB); add a _Static_assert
tying the table length to E_XCE_MAX so any future enum drift fails the build.
Pre-existing foundation bug surfaced (not caused) by controller-status 6.4.
RED: test_strerror_all_xce_codes SEGV'd at utils.c:335 under ASAN; GREEN: lib
suite Ok:1 Fail:0. New tests in test_error.c cover all in-range + out-of-range codes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Crash: encode_NameValue_list called with count=21, s=NULL on worker
rejoin, causing SIGSEGV in persist_worker_hook_fun.
Root cause: free_name_val_list(xce_name_val_t***, int) accepted count by
value. It zeroed *vals (resvals_to_sched = NULL) but could not zero
nresvals_to_sched. Any caller that freed the scheduler resource snapshot
(opget.c workerlist, reply.c clusterconf, dataex.c, sched.c dispatch)
left nresvals_to_sched stale. When the worker later rejoined and the
WAL HOOK fired, the WAL encoder read count=21 with a NULL pointer.
Fix: change signature to free_name_val_list(xce_name_val_t***, int*)
so both fields are zeroed atomically. Update all 7 call sites.
- Fix issue to xce_get() api cause client side crash
- add parse resreq section
- add rusage parser
- parse resreq with basic support alternative & compound, still miss select