fix(lib): stop cbuf_put/get orphaning their mutex on cancellation, hanging vtaskmgr_fini

pthread_cond_wait() reacquires its mutex before honoring a cancellation,
but mylock.c installed no cleanup handler to release it again -- a
thread cancelled mid-wait terminated holding the lock forever. vtaskmgr's
pthread_cancel()-based teardown could land there from three angles
(dispatcher cancelled while polling the shared queue, or a vcpu racing
back into it after its own shutdown signal), permanently deadlocking any
other thread that touched the same queue and hanging vtaskmgr_fini()'s
pthread_join() indefinitely.

Reproduced live as xce_test hanging on Ctrl-D exit once a connection
context was entered; gdb confirmed a vcpu thread blocked forever on a
mutex owned by an already-exited thread ID.

Fix: cbuf_put()/cbuf_get()/cbuf_timedget() now unlock via a
pthread_cleanup_push/pop handler around the wait, so a cancelled waiter
always releases the mutex. vcpu_idle()/vcpu_entry() also recognize the
teardown poison pill and exit immediately instead of needlessly
re-announcing into the already-dead shared queue.

New test_vtaskmgr_teardown.c reproduces the race deterministically
(self-pinned to one CPU, since true multi-core parallelism rarely hits
the window) and bounds vtaskmgr_fini() with a timed join so a
regression fails fast instead of hanging the suite. Logged as bug-1810.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RLSNJhNoULvVcUhXEFafQC
This commit is contained in:
Rongsong Shen 2026-09-15 04:13:53 +00:00
parent b7250c2ec6
commit 0f3919f195
No known key found for this signature in database
GPG key ID: 5BCDAAE0123E9FE2
9 changed files with 335 additions and 9 deletions

View file

@ -55,6 +55,7 @@ extern void test_wal_wire(void);
extern void test_ctrlstatus(void);
extern void test_vtask_admission(void);
extern void test_vtask_enq_race(void);
extern void test_vtaskmgr_teardown(void);
extern void test_xcealloc(void);
void setUp(void) { return; }
@ -180,6 +181,7 @@ int main(int argc, char* argv[])
TEST(test_ctrlstatus);
TEST(test_vtask_admission);
TEST(test_vtask_enq_race);
TEST(test_vtaskmgr_teardown);
TEST(test_xcealloc);
return UNITY_END();