https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126307
Bug ID: 126307
Summary: [TSan] Fiber destruction crashes with stale
Trace::local_head
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: sanitizer
Assignee: unassigned at gcc dot gnu.org
Reporter: alexey.klimkin at intel dot com
CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org,
jakub at gcc dot gnu.org, kcc at gcc dot gnu.org
Target Milestone: ---
Host: x86_64-pc-linux-gnu
Target: x86_64-pc-linux-gnu
Build: x86_64-pc-linux-gnu
> *This was generated by AI during triage.*
Repeated `__tsan_create_fiber`/`__tsan_destroy_fiber` calls crash GCC's
ThreadSanitizer runtime because `Trace::local_head` is not initialized.
Tested with GCC master commit
`58ce322cb0ca9369d5a9aced23731e25b150ce00` on
`x86_64-pc-linux-gnu`.
Minimal reproducer:
```c
extern void *__tsan_create_fiber(unsigned flags);
extern void __tsan_destroy_fiber(void *fiber);
int main(void) {
for (unsigned i = 0; i < 10000; ++i) {
void *fiber = __tsan_create_fiber(0);
__tsan_destroy_fiber(fiber);
}
}
```
Build and run:
```sh
gcc -O2 -g -fsanitize=thread -fno-pie -no-pie fiber-destroy.c -o fiber-destroy
./fiber-destroy
```
On this host, 7,943 iterations pass; 7,944 iterations reliably crash:
```text
ThreadSanitizer:DEADLYSIGNAL
ERROR: ThreadSanitizer: SEGV on unknown address 0x001d00001c14
ThreadSanitizer: nested bug in the same thread, aborting.
```
GDB resolves the failure to:
```text
__tsan::ThreadContext::OnFinished
at libsanitizer/tsan/tsan_rtl_thread.cpp:283
__sanitizer::ThreadContextBase::SetFinished
__sanitizer::ThreadRegistry::FinishThread
__tsan::ThreadFinish
__tsan::FiberDestroy
```
The failing `ThreadContext` has `trace.parts.Size() == 0` but a stale,
non-null `trace.local_head`. `Trace::local_head` lacks an initializer, so
allocator reuse eventually exposes arbitrary contents.
LLVM fixed this upstream by initializing `local_head` to `nullptr`:
- LLVM PR: https://github.com/llvm/llvm-project/pull/171766
- LLVM commit:
https://github.com/llvm/llvm-project/commit/cdfdb06c9155080ec97d6e4f4dd90b6e7cefb0ca
GCC master currently records compiler-rt merge revision
`8723fe5606de6dfb344afacd667c20f55bb2f5e0`, which predates this fix.
Applying the upstream one-line initialization locally gives:
- GCC C/C++ TSan suites: 495 expected passes, zero unexpected failures.
- Standalone fiber churn: 100,000 iterations pass.
- Original downstream workload: 10,000 repetitions pass.
Suggested resolution: import or backport LLVM commit `cdfdb06c9155`, with a
C/C++ TSan regression that churns enough fibers to force allocator reuse.