fix(scheduler): plugin_end_session() guards on the wrong field (bug-1682/1492)
/xce-audit-invariants scheduler (dimension 1, driver state-equivalence, re-run after scheduler-sim-live-allocation) found plugin_end_session() still checked `plugin->begin_session_fn != NULL` before invoking `plugin->end_session_fn(plugin)` -- a copy-paste of plugin_begin_session()'s own (correct) guard. Two failure modes: a plugin registering only end_session_fn silently never has it invoked; a plugin registering only begin_session_fn crashes via a NULL function-pointer call. Currently inert in production (no live plugin hits either shape) but a real latent defect in exactly the session-boundary code the driver-equivalence invariant governs. This exact defect had been independently filed twice: bug-1492 (2026-08-04, scheduler-core task 5.2's review) and bug-1682 (2026-08-24, found adjacent to bug-1681's fix) -- neither investigation cross-referenced the other. Both entries also carried a "fixed" tag inconsistent with their own "not yet fixed" narrative text, caught by this audit's independent code+text cross-check. Fixed the one-line guard; added test_end_session_invokes_end_session_fn_ when_only_it_is_set() (test_plugin_hook_dispatch.c) proving the silent non-invocation, confirmed RED (84/85) against the buggy guard and GREEN (85/85) after the fix. Updated both buglog entries to FIXED with cross-references, and corrected bug-1611's stale narrative to reflect its narrowing (not elimination) by scheduler-sim-live-allocation. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
This commit is contained in:
parent
2f99406788
commit
a643966f50
4 changed files with 63 additions and 11 deletions
|
|
@ -438,7 +438,7 @@ int plugin_end_session(xce_sched_core_t* core)
|
|||
break;
|
||||
}
|
||||
|
||||
if (plugin->begin_session_fn != NULL) {
|
||||
if (plugin->end_session_fn != NULL) {
|
||||
plugin->end_session_fn(plugin);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -282,6 +282,53 @@ static void test_plugin_register_sets_honest_core_reference(void)
|
|||
TEST_ASSERT_EQUAL_PTR(&sched, plugin.sched);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* bug-1682: plugin_end_session() guards its call with */
|
||||
/* `plugin->begin_session_fn != NULL` instead of `plugin->end_session_fn != */
|
||||
/* NULL` (plugin.c, a copy-paste of plugin_begin_session()'s own guard). */
|
||||
/* Two failure modes this produces: (a) a plugin registering ONLY */
|
||||
/* end_session_fn never has it invoked (silently skipped, this test); (b) a */
|
||||
/* plugin registering ONLY begin_session_fn crashes via a NULL */
|
||||
/* function-pointer call the first time a round ends (xce-audit-invariants, */
|
||||
/* scheduler dimension 1, 2026-09-19 -- currently inert in production since */
|
||||
/* no live plugin registers begin_session_fn without end_session_fn, but a */
|
||||
/* latent defect in exactly the session-boundary code the driver- */
|
||||
/* equivalence invariant governs). This test exercises failure mode (a), */
|
||||
/* which is safely reproducible without crashing the test binary. */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static int g_end_session_calls;
|
||||
|
||||
static int mock_end_session_fn(void* arg)
|
||||
{
|
||||
(void)arg;
|
||||
g_end_session_calls++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_end_session_invokes_end_session_fn_when_only_it_is_set(void)
|
||||
{
|
||||
xce_sched_core_t core;
|
||||
xce_sched_plugin_t plugin;
|
||||
int rc;
|
||||
|
||||
core_fixture_init(&core);
|
||||
make_mock_plugin(&plugin, "end_session_only");
|
||||
/* Deliberately leave begin_session_fn NULL -- only end_session_fn is
|
||||
* set, isolating plugin_end_session()'s own guard from
|
||||
* plugin_begin_session()'s (already-correct) one. */
|
||||
plugin.begin_session_fn = NULL;
|
||||
plugin.end_session_fn = mock_end_session_fn;
|
||||
|
||||
rc = plugin_register_core(&core, &plugin);
|
||||
TEST_ASSERT_TRUE(rc >= 0);
|
||||
|
||||
g_end_session_calls = 0;
|
||||
rc = plugin_end_session(&core);
|
||||
TEST_ASSERT_EQUAL_INT(0, rc);
|
||||
TEST_ASSERT_EQUAL_INT(1, g_end_session_calls);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
|
|
@ -289,5 +336,6 @@ int main(void)
|
|||
RUN_TEST(test_dispatch_fanout_simulation_mode_shaped_container);
|
||||
RUN_TEST(test_plugin_register_core_sets_honest_core_reference);
|
||||
RUN_TEST(test_plugin_register_sets_honest_core_reference);
|
||||
RUN_TEST(test_end_session_invokes_end_session_fn_when_only_it_is_set);
|
||||
return UNITY_END();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue