myxce/src
Rongsong Shen 1ce007814d fix(raft-drive-async): fix bug-1376 cold-start self-deadlock, flip peerctrl+snapshot flags ON
Root cause: peer_ctrl_msg_handler held ep->dispatch_inflight incremented
across the entire peer_ctrl_dispatch_to_pool call, including its inline
fallback (the common cold-start shape when ha->pool isn't wired yet). That
inline body can reach raft_cb_become_follower, which -- now that
cluster_init_phase2 ran synchronously earlier in the same call chain and
wired the pool -- tears down its own loser vote-ep (the very ep whose reply
triggered this call) via the deferred path (vote_ep_teardown_async), whose
endpoint_mark_tearing_down spins waiting for dispatch_inflight==0 on that
SAME ep. That count is held only by this exact call, on this exact thread,
and can't reach 0 until the spin itself returns -- a permanent self-deadlock.

Confirmed live via a gdb thread backtrace: added a GDB_WRAP debug seam to
run-ha-soak.sh (launches a named node directly under `gdb --batch` so it
becomes ptrace-legal as gdb's own direct child under yama scope 1, bypassing
a live-attach restriction), then SIGINT to gdb once the log went stale for a
bounded interrupt + full backtrace. The frame dump showed pool=0x0 at
peer_ctrl_dispatch_to_pool, and the same ep pointer in the nested
vote_ep_teardown_async -> endpoint_mark_tearing_down frame, spinning on
sched_yield().

Fix: moved the dispatch_inflight release into peer_ctrl_dispatch_to_pool
itself, at the exact right point per exit path -- released BEFORE calling
the inline body on every fallback path (pool==NULL, OOM, enqueue failure),
since io_worker is single-threaded and the inline path never enqueues
anything (no pool-worker race left to protect against once inline execution
is committed to); released only AFTER the non-blocking enqueue completes on
the success path, preserving the original protection for the genuinely
concurrent pool-worker case.

New unit test test_vep_self_teardown_does_not_deadlock uses a bounded
pthread_timedjoin_np so a regression fails loud instead of hanging the
suite. RED confirmed via a temporary manual revert (ETIMEDOUT) before
restoring the fix.

Live-verified with both flags ON: --force-snapshot soak (the exact repro
shape) completes without hanging across repeated runs, confirms real
snapshot installs, zero divergence, zero job loss; a 6-round --chaotic soak
also passed clean; full controller suite green throughout.

g_drive_async_snapshot_offload and g_drive_async_peerctrl_dispatch_enabled
now default ON in production, closing raft-drive-async tasks 3.1 and 3.2.
g_drive_async_configpush_offload stays OFF -- a distinct, still-open hazard
in push_config_transport_only's endpoint handling (task 3.3, unrelated to
this bug).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014dZVSx3CdBjys9BB6hqpxP
2026-07-02 07:18:42 +00:00
..
autoscaler support shared libxce(for api server) 2026-01-19 11:02:49 +08:00
controller fix(raft-drive-async): fix bug-1376 cold-start self-deadlock, flip peerctrl+snapshot flags ON 2026-07-02 07:18:42 +00:00
docs docs(ha-single-leader-role): sync steering + contributor docs to three-state model + own-term gate (task 6.1) 2026-06-13 14:58:55 +00:00
frontend chore: baseline snapshot — prior-session work + ha-consistency-invariants spec family 2026-06-11 13:21:50 +00:00
include fix(raft-ha-core-safety): close 5.10a — WAL segment rotation + endpoint UAF blocking real snapshot catch-up 2026-07-02 04:11:20 +00:00
lib fix(lib): normalize delaymgr to one CLOCK_MONOTONIC ms timescale, fixing seconds-task starvation 2026-07-02 03:40:08 +00:00
nixSupport Merge Go frontend (apiserver + xcecli) into meson build 2026-04-14 11:23:18 +08:00
scheduler test(scheduler-controller-msg-gap): real handler/applier unit tests (bug-765 G-6) 2026-06-19 04:14:20 +00:00
schema feat(raft-ha-core-safety): establish snapshot (term,lsn) boundary on install (task 3.2) 2026-07-01 13:08:10 +00:00
tools feat(xce-build): add non-ASAN debug + release profiles; root-cause bug-1286 with the debug build 2026-06-30 09:15:36 +00:00
worker enhance xce-build skill 2026-05-30 08:13:59 +08:00
flake.lock chore(nix): repin flake.lock (c-capnproto) to restore buildable dev shell 2026-06-22 04:32:14 +00:00
flake.nix save works 2026-03-04 18:18:53 +08:00
meson.build Merge Go frontend (apiserver + xcecli) into meson build 2026-04-14 11:23:18 +08:00
meson.options Merge Go frontend (apiserver + xcecli) into meson build 2026-04-14 11:23:18 +08:00