fix(scheduler): clock/resval/jobid-format fixes plus REPL live-operator gaps (task 12.5)
Bugs fixed, discovered across a day of live-operator testing against a real deployed cluster: - bug-1584: clock anchors never initialized to real wall-clock values, timestamps showed system uptime instead of Unix epoch. - bug-1585: heap-use-after-free in the normal-mode driver's periodic resval update path -- core_events.c's RESVALS_FULL/_DELTA handlers do a shallow zarray_put() of the wire-decoded xce_val_t*, but driver.c's release_translated_payload() unconditionally freed the same decoded array right after, so the next periodic report for the same worker+resource triggered a UAF read via kill_sched_resval(). New regression test: test_resval_ownership.c. - bug-1587/1588/1591: raw-ns/raw-uint64 jobid/timestamp prints across the REPL/SIM family converted to the same human-readable formatting already used elsewhere (fmt_jobid(), timestamp formatting). - bug-1590: repl_info.c's XCE_VAL_NUMERIC checks corrected to Value_u_fvalue, fixing `info worker`/`info resource` falling back to 0.00 for real numeric resvals. task 12.5 (Req 5.22 amendment) -- five REPL gaps surfaced by a live operator session, each with its own bug id: - bug-1594: `continue`/`step` reaching EOF with no breakpoint hit now re-enters the REPL via xce_repl_on_replay_complete() instead of exiting the process; step/continue issued after replay is already complete re-prompt instead of silently exiting. - bug-1595: `step`/`continue` now echo each input event (not just decisions) via repl_print_event_summary(), in real event/decision order. - bug-1593: `info resource <name>|all` now reports resource definition metadata restricted to XCE_RESF_GLOBAL/XCE_RESF_SHARED resources, read from core->sharedInst, instead of aggregating host-based resources across every worker. - bug-1596: repl_split_tokens() strips one matching pair of surrounding quote characters from each token. See requirements.md's Req 5 AC 22 "Amendment (2026-08-19)" for the full rationale on each of the five task 12.5 gaps. Full scheduler suite green (41/42; the one remaining failure, test_recordstart_symlink_escape_replies_error, is the pre-existing unrelated bug-1560).
This commit is contained in:
parent
515f4ca098
commit
c9acd502c0
32 changed files with 2547 additions and 295 deletions
|
|
@ -107,6 +107,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <unity/unity.h>
|
||||
|
|
@ -571,12 +572,14 @@ test_repl_step_continue_to_completion_matches_batch_decision_sequence(void)
|
|||
|
||||
make_tmp_dir(script_dir, sizeof(script_dir), "_script");
|
||||
snprintf(script_path, sizeof(script_path), "%s/script.txt", script_dir);
|
||||
write_text_file(script_path, "step 1\ncontinue\n");
|
||||
/* task 12.5 (bug-1594): trailing `quit` -- `continue` now re-enters
|
||||
* the REPL at replay completion instead of returning, so this side
|
||||
* must run in a FORKED child (matching test_repl_execution_control.c's
|
||||
* own Test 3 pattern); otherwise quit's exit(0) would tear down this
|
||||
* whole test binary before the batch-vs-REPL comparison below ever
|
||||
* runs. */
|
||||
write_text_file(script_path, "step 1\ncontinue\nquit\n");
|
||||
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(freopen(script_path, "r", stdin),
|
||||
"freopen of scripted stdin must succeed");
|
||||
|
||||
memset(&sim_repl, 0, sizeof(sim_repl));
|
||||
memset(&args_repl, 0, sizeof(args_repl));
|
||||
args_repl.replay_path = fixture_path;
|
||||
args_repl.sim_start_ts = SCHED_SIM_START_TS_LATEST;
|
||||
|
|
@ -584,8 +587,30 @@ test_repl_step_continue_to_completion_matches_batch_decision_sequence(void)
|
|||
args_repl.output_path = repl_out_path;
|
||||
args_repl.interactive = true;
|
||||
|
||||
rc = sched_sim_driver_run(&sim_repl, &args_repl);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
{
|
||||
pid_t pid = fork();
|
||||
int status;
|
||||
|
||||
TEST_ASSERT_TRUE_MESSAGE(pid >= 0, "fork() must succeed");
|
||||
|
||||
if (pid == 0) {
|
||||
if (freopen(script_path, "r", stdin) == NULL) {
|
||||
_exit(120);
|
||||
}
|
||||
memset(&sim_repl, 0, sizeof(sim_repl));
|
||||
(void)sched_sim_driver_run(&sim_repl, &args_repl);
|
||||
_exit(111); /* unreachable -- quit must already have exited */
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(pid, waitpid(pid, &status, 0),
|
||||
"waitpid must reap the REPL child");
|
||||
TEST_ASSERT_TRUE_MESSAGE(WIFEXITED(status),
|
||||
"the REPL child must exit normally via "
|
||||
"quit's exit(0), not crash/signal");
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(0, WEXITSTATUS(status),
|
||||
"quit's exit(0) is the only correct "
|
||||
"exit path");
|
||||
}
|
||||
|
||||
/* ---- Decode every ReplaySession from both output files and compare
|
||||
* the decision sequence, session by session, decision by decision. ---- */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue