fix(controller): run the become-leader tail on a task class that may block (bug-1433)
A winning RequestVoteReply is dispatched through peer_ctrl_classify, which
returned VTASK_LIVENESS for all peer-control traffic -- the never-blocks,
never-admission-gated class. The reply runs raft_cb_become_leader, whose
tail persist_apply_pump_run_sync() does bounded blocking WAL pread()s (it
cannot be made async without reopening the bug-1043-family job loss on a
freshly promoted primary). The fdatasync half of bug-1433 was removed in
40f510fb; this pread was the tracked residual.
peer_ctrl_classify now returns VTASK_LIVE_BLOCK while the node is
CTRL_ELECTING -- its peer-control traffic is then vote/PreVote replies,
election work like inbound RequestVote, which already uses LIVE_BLOCK.
As PRIMARY/STANDBY the traffic is WAL/config ACKs and stays VTASK_LIVENESS,
so a quorum of acks is never admission-gated (R4.5); a candidate has no
commit to advance.
New test_peer_ctrl_classify_vote_replies_while_electing (RED before).
Controller suite 1240/0.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
33c4f28c6a
commit
255b0faad1
2 changed files with 68 additions and 11 deletions
|
|
@ -592,6 +592,42 @@ static void test_p3_cross_endpoint_not_serialized(void)
|
|||
|
||||
/* ── Suite entry point ──────────────────────────────────────────────────── */
|
||||
|
||||
/* bug-1433: a winning vote reply runs raft_cb_become_leader, whose tail
|
||||
* persist_apply_pump_run_sync() does blocking WAL pread()s -- so while this
|
||||
* node is a candidate (CTRL_ELECTING) its peer-control messages (vote
|
||||
* replies) must be VTASK_LIVE_BLOCK, the class inbound RequestVote already
|
||||
* uses, not the never-blocks VTASK_LIVENESS. As PRIMARY/STANDBY they are
|
||||
* WAL/config ACKs and must stay VTASK_LIVENESS (never admission-gated) so
|
||||
* commit can always advance. */
|
||||
extern vtask_class_t ha_peer_ctrl_classify_for_test(ha_state_t *, io_packet_t *);
|
||||
|
||||
static void test_peer_ctrl_classify_vote_replies_while_electing(void)
|
||||
{
|
||||
cluster_t c;
|
||||
io_packet_t pkt;
|
||||
|
||||
memset(&c, 0, sizeof(c));
|
||||
memset(&pkt, 0, sizeof(pkt));
|
||||
ha_init(&c.ha, &g_cfg, 0);
|
||||
|
||||
atomic_store(&c.ha.role, CTRL_ELECTING);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(VTASK_LIVE_BLOCK,
|
||||
ha_peer_ctrl_classify_for_test(&c.ha, &pkt),
|
||||
"bug-1433: vote replies while electing may run the become-leader "
|
||||
"tail's blocking reads -- VTASK_LIVE_BLOCK");
|
||||
|
||||
atomic_store(&c.ha.role, CTRL_PRIMARY);
|
||||
TEST_ASSERT_EQUAL_INT_MESSAGE(VTASK_LIVENESS,
|
||||
ha_peer_ctrl_classify_for_test(&c.ha, &pkt),
|
||||
"ACKs to a primary must never be admission-gated");
|
||||
|
||||
atomic_store(&c.ha.role, CTRL_STANDBY);
|
||||
TEST_ASSERT_EQUAL_INT(VTASK_LIVENESS,
|
||||
ha_peer_ctrl_classify_for_test(&c.ha, &pkt));
|
||||
|
||||
ha_fini(&c.ha);
|
||||
}
|
||||
|
||||
void test_ha_dispatch_integration(void)
|
||||
{
|
||||
UnitySetTestFile(__FILE__);
|
||||
|
|
@ -600,6 +636,7 @@ void test_ha_dispatch_integration(void)
|
|||
RUN_TEST(test_p1_configpush_transfer_does_not_block_cross_endpoint);
|
||||
/* P2 — VTASK_LIVENESS ack runs under *_BLOCK pool saturation */
|
||||
RUN_TEST(test_p2_ack_runs_under_pool_saturation);
|
||||
RUN_TEST(test_peer_ctrl_classify_vote_replies_while_electing);
|
||||
/* P3 — cross-endpoint peer control is not serialized */
|
||||
RUN_TEST(test_p3_cross_endpoint_not_serialized);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue