-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Open
Labels
compiler-rt:tsanThread sanitizerThread sanitizer
Description
Component: ThreadSanitizer (compiler-rt)
Toolchain & versions
Clang: Ubuntu clang version 19.1.7 (++20250804090312+cd708029e0b2-1~exp1~20250804210325.79)
Target triple used for build: aarch64-linux-gnu
Linker: lld-19
TSan runtime: libclang_rt.tsan-aarch64.{a,so} from LLVM 19 packages
Runtime environment
- Hardware: Raspberry Pi Compute Module 4 (ARMv8, AArch64)
- Kernel: Linux 5.15, configured with CONFIG_ARM64_VA_BITS_48=y (/proc/config confirms ARM64_VA_BITS=48)
- Page size: 4096
- Distro/userspace: Yocto
- ASLR: kernel.randomize_va_space=2
- vm.mmap_rnd_bits: tested values 30, 28, 27, 26 (no change)
- ulimit -v: unlimited
- Execution is native on AArch64
Build Flags
-fsanitize=thread -fPIE -pie -g -O1
What happens
Running the instrumented app and invoking a specific code path that calls into a closed-source shared library (which internally creates and manages threads) reliably aborts with a TSan CHECK:
ThreadSanitizer: CHECK failed: sanitizer_thread_registry.cpp:348
"((t)) != (0)" (0x0, 0x0) (tid=3351)
#0 __tsan::CheckUnwind() crtstuff.c (some+0x528840) (BuildId: 50d2cc61e1c5...)
#1 __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long)
crtstuff.c (some+0x499844) (BuildId: 50d2cc61e1c5...)
#2 __sanitizer::ThreadRegistry::ConsumeThreadUserId(unsigned long)
crtstuff.c (some+0x498598) (BuildId: 50d2cc61e1c5...)
#3 pthread_detach <null> (some+0x4b74c0) (BuildId: 50d2cc61e1c5...)
#4 PtUtilsLib::Thread::WaitUntilSignaled() (application frame)
...
With TSAN_OPTIONS=verbosity=2
I also see (right before the CHECK) repeated lines like:
__tls_get_addr: DTLS_Destroy 0x...
__tls_get_addr: DTLS_Destroy 0x...
- so the detach seems to happen during thread exit / a TLS destructor path.
Minimal reproducer?
I don’t have the library’s sources. However, the symptom is consistent with either:
- a double pthread_detach (or detach after join), or
- a detach in a TLS destructor after TSan has already "consumed" the thread id, or
- a thread created in non-instrumented code such that TSan never registered it, but later intercepts pthread_detach on its pthread_t.
A synthetic mini test that double-detaches does not crash glibc (second call returns EINVAL), so a TSan CHECK here seems unexpected:
// build: clang -fsanitize=thread -fPIE -pie -O1 -g dd.c -o dd
#include <pthread.h>
#include <stdio.h>
void* fn(void*) { return NULL; }
int main() {
pthread_t th;
int rc = pthread_create(&th, 0, fn, 0);
if (rc) return rc;
int rc1 = pthread_detach(th); // expected 0
int rc2 = pthread_detach(th); // expected EINVAL; with TSan I hit the CHECK above
printf("detach rc1=%d rc2=%d\n", rc1, rc2);
return 0;
}
the example will result in:
# TSAN_OPTIONS="verbosity=2" ./dd
==4014==Installed the sigaction for signal 11
==4014==Installed the sigaction for signal 7
==4014==Installed the sigaction for signal 8
==4014==Using llvm-symbolizer found at: /usr/bin/llvm-symbolizer-19
***** Running under ThreadSanitizer v3 (pid 4014) *****
ThreadSanitizer: growing heap block allocator: 0 out of 262144*4096
ThreadSanitizer: CHECK failed: sanitizer_thread_registry.cpp:348 "((t)) != (0)" (0x0, 0x0) (tid=4014)
#0 __tsan::CheckUnwind() <null> (dd+0xdcbc0) (BuildId: 01c0d8ea751ed81d4f79412b065be84f2c38f375)
#1 __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) <null> (dd+0x4dc44) (BuildId: 01c0d8ea751ed81d4f79412b065be84f2c38f375)
#2 __sanitizer::ThreadRegistry::ConsumeThreadUserId(unsigned long) <null> (dd+0x4c998) (BuildId: 01c0d8ea751ed81d4f79412b065be84f2c38f375)
#3 pthread_detach <null> (dd+0x6b840) (BuildId: 01c0d8ea751ed81d4f79412b065be84f2c38f375)
#4 main /dd.c:9:13 (dd+0xfae14) (BuildId: 01c0d8ea751ed81d4f79412b065be84f2c38f375)
#5 <null> <null> (libc.so.6+0x284c0) (BuildId: a62e1f95f9de1a57d5b80979eedf2c7a742e3b42)
#6 __libc_start_main <null> (libc.so.6+0x28594) (BuildId: a62e1f95f9de1a57d5b80979eedf2c7a742e3b42)
#7 _start <null> (dd+0x385ac) (BuildId: 01c0d8ea751ed81d4f79412b065be84f2c38f375)
Mqxx
Metadata
Metadata
Assignees
Labels
compiler-rt:tsanThread sanitizerThread sanitizer