fix(controller): stop a failed test from hanging the unit suite (bug-1429); mkstemp for upgrade temp file (bug-1861)
A failing TEST_ASSERT longjmps out and skips the fixture teardown, leaving the commit engine's sweep thread and persist's fsync_worker asleep on a static struct. The next test re-inits it underneath them, corrupting the condvar, and a later teardown blocks in pthread_cond_destroy/join until the 300s meson timeout. The failure line itself was lost because stdout was fully buffered. - controller_test: line-buffer stdout; tearDown() reaps what a failed test leaked via new XCE_TESTING registries (persist_test_reap_unstopped, then commit_test_reap_unfinalized_engines -- persist_stop before engine fini). Clean run reaps 0; an injected failure now fails in 2s instead of hanging. - persist: flusher_flush_once reports only its own durable advance, so fsync_worker no longer re-fires the durable callback for an advance a concurrent persist_flush made (flaky "must not re-fire" test). Regression test test_flusher_pass_does_not_claim_concurrent_flush_advance. - tests: jap observer is atomic and waits (bounded) for a continuation that may resolve on the flusher thread; pump catch-up tests wait for trailing replies instead of a single scan. - config_repl: upgrade decode temp file via mkstemp instead of a pthread_self()-derived /tmp name (same value across processes, opened without O_EXCL -- collisions and a symlink target). Verified: controller_unit_test 1222/1222; 24 parallel runs (6x4), no hangs or ASAN errors. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
44c1981cff
commit
b5d59253e5
9 changed files with 316 additions and 23 deletions
|
|
@ -1056,6 +1056,34 @@ static void test_persist_flush_fires_durable_advance_callback(void)
|
|||
printf("test_persist_flush_fires_durable_advance_callback: PASS\n");
|
||||
}
|
||||
|
||||
/* bug-1429: fsync_worker used to snapshot durable_lsn, flush, and fire the
|
||||
* durable-advance callback if the watermark moved -- crediting itself with
|
||||
* an advance a concurrent persist_flush() made in between, so the callback
|
||||
* fired twice for one advance (the flaky "must not re-fire" failure above
|
||||
* under load). A flusher pass must report only its own advance. */
|
||||
static void test_flusher_pass_does_not_claim_concurrent_flush_advance(void)
|
||||
{
|
||||
char tmp[256];
|
||||
strcpy(tmp, "/tmp/xce_flushown_XXXXXX");
|
||||
TEST_ASSERT_NOT_NULL(mkdtemp(tmp));
|
||||
|
||||
persist_t* p = make_durability_persist(tmp);
|
||||
TEST_ASSERT_NOT_NULL(p);
|
||||
|
||||
bool advanced = true;
|
||||
|
||||
/* persist_flush() advances the watermark first ... */
|
||||
TEST_ASSERT_EQUAL_INT(0, persist_wal_async(p, WAL_JOB_UPDATE, "a", 1));
|
||||
TEST_ASSERT_EQUAL_INT(0, persist_flush(p));
|
||||
/* ... so the flusher's pass right after has nothing of its own */
|
||||
persist_test_flusher_flush_once(p, &advanced);
|
||||
TEST_ASSERT_FALSE_MESSAGE(advanced,
|
||||
"a flusher pass must not report an advance persist_flush() made");
|
||||
|
||||
teardown_durability_persist(p);
|
||||
printf("test_flusher_pass_does_not_claim_concurrent_flush_advance: PASS\n");
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ *
|
||||
* Test 5.1b (Req 1.5 / 2.5): losing the sole durable contributor *
|
||||
* leaves the acknowledged op present on a surviving member. *
|
||||
|
|
@ -2599,6 +2627,7 @@ void test_commit_durability(void)
|
|||
/* task 5.1 — durable-majority commit wired end to end */
|
||||
RUN_TEST(test_durable_majority_commit_end_to_end);
|
||||
RUN_TEST(test_persist_flush_fires_durable_advance_callback);
|
||||
RUN_TEST(test_flusher_pass_does_not_claim_concurrent_flush_advance);
|
||||
RUN_TEST(test_sole_durable_contributor_loss_survives);
|
||||
RUN_TEST(test_durability_work_off_iomgr_preserves_liveness);
|
||||
RUN_TEST(test_recover_verdict_clean_intact_log);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue