fix(harness): reset getopt_long via optind=0 to stop cross-command corruption
Every cmd_* REPL handler in test.c/join_worker_args.c reset flag parsing with `optind = 1;` only. glibc's getopt_long only fully reinitializes its internal scan state (nextchar/first_nonopt/last_nonopt) when optind==0, or on the process's very first getopt_long() call ever -- optind=1 alone leaves that state stale for every call after the first. Since xce_test's REPL dispatches many independent cmd_*() calls per process, a command whose parse ends on a short no-argument flag (`qctrl -a`, `hostctrl -o`) left state that corrupted the NEXT unrelated command's parse badly enough to misread its own name as an unrecognized flag. This was the actual cause of harness_unit_test's 4 deterministic (not flaky -- 20/20 identical repeat runs) test_test_cli.c failures, each burning its full 5s confirmation-prompt timeout. Fixed by using optind=0 at all 21 reset sites; confirmed via 3 isolated pty repros plus 10 consecutive clean harness_unit_test runs (132/132, was 4 failures/run every time). Also fixes a resource leak found while investigating: test_test_cli.c's spawned xce_test sessions were only torn down by inline clitest_kill_and_reap()/clitest_close() calls at the bottom of each test function, which Unity's longjmp-based TEST_ASSERT abort skips entirely on failure, leaking the child process and its pty/pipe fds. Added a static session mirror (safe across the longjmp, unlike a stack pointer) reaped from harness_test.c's tearDown(), which Unity guarantees runs after every test regardless of outcome. Logged as bug-1807/bug-1808 in .wolf/buglog.json, with the underlying getopt/longjmp gotchas recorded in .wolf/cerebrum.md. Full ASAN /xce-build harness also passes 5/5 with no sanitizer findings. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
This commit is contained in:
parent
cbf822fc53
commit
868c6427c8
9 changed files with 672 additions and 74 deletions
|
|
@ -19,10 +19,19 @@ extern void test_listfmt_json(void);
|
|||
extern void test_xcetest_process_entry(void);
|
||||
extern void test_test_cli(void);
|
||||
|
||||
/* test_test_cli.c's leak-safety net (see its own comment): reaps and
|
||||
* closes any clitest session left open by a test function that aborted
|
||||
* via a TEST_ASSERT_* failure partway through, before it reached its own
|
||||
* clitest_kill_and_reap()+clitest_close() cleanup. A no-op whenever no
|
||||
* session is currently open (i.e. after every test outside test_test_cli,
|
||||
* and after every test_test_cli sub-test that ran its own cleanup). */
|
||||
extern void clitest_reap_leaked_session(void);
|
||||
|
||||
void setUp(void) { return; }
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
clitest_reap_leaked_session();
|
||||
printf("\n-----------------------------------------------------\n");
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue