feat(scheduler-sim-decision-trace): pass the scheduler log path to the simulation driver

Task 4.4: the --logfile path (or the default, now SCHED_DEFAULT_LOG_PATH)
reaches the sim driver as an owned copy so the trace file checks can
reject the scheduler log.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Rongsong Shen 2026-10-08 14:13:50 +00:00
parent aa4c43c897
commit e01ffe4c9c
Signed by untrusted user: rshen
GPG key ID: 80533536B0EB651C
5 changed files with 118 additions and 2 deletions

View file

@ -101,8 +101,22 @@ typedef struct {
* style direct core init, matching sched_sim_driver_start()'s own
* memset(sim, 0, sizeof(*sim)) default. */
bool allocator_thread_live;
/* scheduler-sim-decision-trace task 4.4 (Req 8.3): the scheduler log
* file this process writes to (--logfile, else SCHED_DEFAULT_LOG_PATH).
* An owned copy made by sched_sim_driver_start() and freed by
* sched_sim_driver_fini(); the REPL's trace-file checks reject a trace
* file that is the same file (dev/inode) as this one. */
char* log_path;
} xce_sched_sim_driver_t;
/*
* SCHED_DEFAULT_LOG_PATH - the scheduler log file main.c uses when --logfile
* is not given. sched_sim_driver_start() falls back to the same path when
* `sched_sim_args_t.log_path` is NULL, so the driver always names the file
* the scheduler actually logs to.
*/
#define SCHED_DEFAULT_LOG_PATH "/tmp/xce_scheduler.log"
/*
* SCHED_SIM_START_TS_LATEST - default value for `sched_sim_args_t.sim_start_ts`
* when the caller does not pass --sim-start-ts (main.c). AC 13's own
@ -148,6 +162,8 @@ typedef struct {
alt_events_path; /* --sim-alt-events FILE (optional, task 11.5) */
const char* output_path; /* --sim-output FILE (optional, task 11.5) */
bool interactive; /* --interactive / -i (task 12) */
const char* log_path; /* --logfile FILE (optional; NULL means
* SCHED_DEFAULT_LOG_PATH) */
} sched_sim_args_t;
/*

View file

@ -225,7 +225,7 @@ static void sig_handler(int signo)
int main(int argc, char* argv[])
{
struct arguments arguments;
char* logfile = "/tmp/xce_scheduler.log";
char* logfile = SCHED_DEFAULT_LOG_PATH;
char* loglevel = "info";
int logsize = 64 * 1024 * 1024;
int logcount = 10;
@ -387,6 +387,7 @@ int main(int argc, char* argv[])
sim_args.alt_events_path = arguments.sim_alt_events;
sim_args.output_path = arguments.sim_output;
sim_args.interactive = (arguments.interactive != 0);
sim_args.log_path = logfile;
rc = sched_sim_driver_run(&sim, &sim_args);
if (rc == -ENOSYS) {

View file

@ -671,6 +671,28 @@ int sched_sim_driver_start(xce_sched_sim_driver_t* sim,
}
}
/* scheduler-sim-decision-trace task 4.4 (Req 8.3): keep our own copy of
* the scheduler log path (argv memory belongs to the caller); with no
* --logfile the scheduler logs to SCHED_DEFAULT_LOG_PATH. */
sim->log_path = strdup((args->log_path != NULL) ? args->log_path
: SCHED_DEFAULT_LOG_PATH);
if (sim->log_path == NULL) {
ERROR("%s cannot copy the scheduler log path: out of memory",
__func__);
if (sim->record_file != NULL) {
fclose(sim->record_file);
sim->record_file = NULL;
}
if (sim->alt_events_file != NULL) {
fclose(sim->alt_events_file);
sim->alt_events_file = NULL;
}
fclose(sim->replay_file);
sim->replay_file = NULL;
xce_sched_core_fini(&(sim->core));
return -ENOMEM;
}
return 0;
}
@ -753,6 +775,9 @@ void sched_sim_driver_fini(xce_sched_sim_driver_t* sim)
sim->replay_file = NULL;
}
free(sim->log_path);
sim->log_path = NULL;
sim_take_alloc_wrappers_(sim, wrappers);
xce_sched_core_fini(&(sim->core));
sim_free_alloc_wrappers_(wrappers);

View file

@ -588,6 +588,77 @@ static void test_null_arguments_return_einval(void)
printf("test_null_arguments_return_einval: PASS\n");
}
/* ---------------------------------------------------------------------- */
/* Test 6 (scheduler-sim-decision-trace task 4.4, Req 8.3): the driver */
/* holds the scheduler log path it was started with -- its own copy, not */
/* the caller's buffer -- or SCHED_DEFAULT_LOG_PATH (the same default */
/* main.c logs to without --logfile) when none is given. The trace-file */
/* checks compare a trace file against this path. */
/* ---------------------------------------------------------------------- */
static void test_driver_holds_configured_log_path(void)
{
char path[PATH_MAX];
char log_path[PATH_MAX + 16];
uint64_t snapshot_ts = 0;
sched_sim_args_t args;
xce_sched_sim_driver_t sim;
int rc;
write_valid_fixture(path, sizeof(path), &snapshot_ts, "_logpath");
snprintf(log_path, sizeof(log_path), "%s.sched.log", path);
memset(&args, 0, sizeof(args));
args.replay_path = path;
args.sim_start_ts = SCHED_SIM_START_TS_LATEST;
args.log_path = log_path;
rc = sched_sim_driver_start(&sim, &args);
TEST_ASSERT_EQUAL_INT(0, rc);
TEST_ASSERT_NOT_NULL(sim.log_path);
TEST_ASSERT_EQUAL_STRING(log_path, sim.log_path);
TEST_ASSERT_TRUE(sim.log_path != log_path); /* owned copy */
/* The caller's buffer going away must not change the driver's path. */
memset(log_path, 'x', sizeof(log_path) - 1);
TEST_ASSERT_EQUAL_STRING_LEN(path, sim.log_path, strlen(path));
xce_core_set_active_for_logging(NULL);
sched_sim_driver_fini(&sim);
TEST_ASSERT_NULL(sim.log_path);
printf("test_driver_holds_configured_log_path: PASS\n");
}
static void test_driver_holds_default_log_path_when_none_given(void)
{
char path[PATH_MAX];
uint64_t snapshot_ts = 0;
sched_sim_args_t args;
xce_sched_sim_driver_t sim;
int rc;
write_valid_fixture(path, sizeof(path), &snapshot_ts, "_logdefault");
memset(&args, 0, sizeof(args));
args.replay_path = path;
args.sim_start_ts = SCHED_SIM_START_TS_LATEST;
rc = sched_sim_driver_start(&sim, &args);
TEST_ASSERT_EQUAL_INT(0, rc);
TEST_ASSERT_NOT_NULL(sim.log_path);
TEST_ASSERT_EQUAL_STRING(SCHED_DEFAULT_LOG_PATH, sim.log_path);
TEST_ASSERT_EQUAL_STRING("/tmp/xce_scheduler.log", sim.log_path);
xce_core_set_active_for_logging(NULL);
sched_sim_driver_fini(&sim);
TEST_ASSERT_NULL(sim.log_path);
printf("test_driver_holds_default_log_path_when_none_given: PASS\n");
}
/* Test 6 (sched_sim_driver_run() -- design.md's literal entry point --
* calling start() then failing loudly with -ENOSYS pending the event loop)
* was removed here: the event loop now exists (scheduler-core spec, task
@ -607,6 +678,8 @@ int main(void)
RUN_TEST(test_first_message_not_replayheader_fails_cleanly);
RUN_TEST(test_missing_replay_file_fails_cleanly);
RUN_TEST(test_null_arguments_return_einval);
RUN_TEST(test_driver_holds_configured_log_path);
RUN_TEST(test_driver_holds_default_log_path_when_none_given);
return UNITY_END();
}