Read the wakeup pipe fds atomically
Merged
HE
3mo ago+228+228+012345678901234567890123456789-78-78-01234567890123456789
Address the race condition caught by CI
test-fork-exec [ FAIL ] (exit 134)
==================
WARNING: ThreadSanitizer: data race (pid=76887)
Read of size 4 at 0x0001004fc6c4 by thread T1:
#0 wakeup_pipe_signal poll.c:63 (elfuse:arm64+0x100060248)
#1 preempt_thread_main proc.c:2897 (elfuse:arm64+0x10007368c)
Previous write of size 4 at 0x0001004fc6c4 by main thread:
#0 wakeup_pipe_init poll.c:57 (elfuse:arm64+0x1000601e8)
#1 syscall_init syscall.c:117 (elfuse:arm64+0x10002dcbc)
#2 guest_bootstrap_prepare bootstrap.c:574 (elfuse:arm64+0x10000fce4)
#3 guest_bootstrap_prepare bootstrap.c:369 (elfuse:arm64+0x10000ecd4)
#4 main main.c:243 (elfuse:arm64+0x1000008c4)
Location is global 'wakeup_pipe_wr' at 0x0001004fc6c4 (elfuse+0x1000c46c4)
Thread T1 (tid=39753171, running) created by main thread at:
#0 pthread_create <null> (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x33834)
#1 proc_preempt_init proc.c:2997 (elfuse:arm64+0x1000735c4)
#2 main main.c:464 (elfuse:arm64+0x100001254)
SUMMARY: ThreadSanitizer: data race poll.c:63 in wakeup_pipe_signal
==================
Summary by cubic
Fixes a wakeup-pipe data race by making the pipe fds atomic and reading the wake fd once per wait. Old behavior: plain ints allowed torn reads between init and signal delivery and code re-read the fd in pselect6. New behavior: _Atomic int with relaxed loads/stores and a single read per ppoll/pselect6; no readiness semantics change.
- In
ppoll/pselect6, load the wake fd once, reuse it across FD_SET/ISSET/CLR and the poll fallback, then drain and decrement the result when only the wakeup fired. - Move the wakeup-pipe API to
syscall/wakeup-pipe.c/.h; remove it fromsyscall/poll.h; update all includes tosyscall/wakeup-pipe.h. - Add native host concurrency test
test-wakeup-pipe-host; build and run in host and sanitizer lanes.