-
Notifications
You must be signed in to change notification settings - Fork 14k
Description
I've been investigating the Firefox Profiler hangs that were happening in TSan builds, and discovered that LLVM doesn't correctly mark some blocking functions calls (llvm/llvm-project#83561 and llvm/llvm-project#83844). And it was failing to send async signals like SIGPROF properly.
There is also a Rust test case in the second issue if you want to try it yourself: https://github.com/canova/rustc-tsan-testcase
They've been resolved now, but Rust needs to get the LLVM patches as well and on top of it it needs to do a manual handling for FUTEX_WAIT syscalls.
It looks like for calling syscalls directly, there isn't a way to intercept the call (it's possible for glibc calls like pthread_mutex_lock etc.). That's why when a syscall is being called, the program itself has to inject pre/post syscall hooks itself. My PR added these new hooks for futex syscalls so they can be marked as blocking properly. Rust std library also calls FUTEX_WAIT syscalls directly, which means that we need to add __sanitizer_syscall_pre_futex and __sanitizer_syscall_post_futex to here (beware that these are macros, so you'll want to cal the functions that the macros call instead):
rust/library/std/src/sys/pal/unix/futex.rs
Lines 60 to 70 in 10a7aa1
| // Use FUTEX_WAIT_BITSET rather than FUTEX_WAIT to be able to give an | |
| // absolute time rather than a relative time. | |
| libc::syscall( | |
| libc::SYS_futex, | |
| futex as *const AtomicU32, | |
| libc::FUTEX_WAIT_BITSET | libc::FUTEX_PRIVATE_FLAG, | |
| expected, | |
| timespec.as_ref().map_or(null(), |t| t as *const libc::timespec), | |
| null::<u32>(), // This argument is unused for FUTEX_WAIT_BITSET. | |
| !0u32, // A full bitmask, to make it behave like a regular FUTEX_WAIT. | |
| ) |
I tried implementing it, but I couldn't make the linker happy yet. It can't find the hooks, they should be inside the libclang_rt but I can't seem to make it work. Any help would be appreciated!