Zig Version
0.14.0
Steps to Reproduce and Observed Behavior
I've discovered a data race in Zig's debug system when running tests with ThreadSanitizer enabled in a project that uses OpenCL (which creates additional threads).
When a test fails, Zig attempts to dump the stack trace, but ThreadSanitizer reports data races in the debug system itself. The race occurs between the main thread trying to print debug information and a secondary thread handling signals, both accessing the same debug structures concurrently.
test
└─ run test 11/12 passed, 1 failed
aborting due to recursive panic
error: 'tensor.extra.memory.test.fill and get random value' failed: expected -97, found -86
Segmentation fault at address 0x7ffff5de00fb
==================
WARNING: ThreadSanitizer: data race (pid=16584)
Read of size 8 at 0x555555868c88 by main thread:
#0 __tsan_memcpy ~/.zvm/master/lib/tsan/tsan_interceptors_memintrinsics.cpp:27:3 (test+0x25738b)
#1 debug.getDebugInfoAllocator ~/.zvm/master/lib/std/debug.zig:1315:9 (test+0xaeb61)
#2 debug.getSelfDebugInfo ~/.zvm/master/lib/std/debug.zig:229:66 (test+0xae9f2)
#3 debug.dumpStackTrace ~/.zvm/master/lib/std/debug.zig:497:44 (test+0xa7048)
#4 test_runner.mainServer ~/.zvm/master/lib/compiler/test_runner.zig:131:53 (test+0x16b297)
#5 test_runner.main ~/.zvm/master/lib/compiler/test_runner.zig:60:26 (test+0x16564a)
#6 start.callMain ~/.zvm/master/lib/std/start.zig:647:22 (test+0x164dd4)
#7 start.callMainWithArgs ~/.zvm/master/lib/std/start.zig:616:20 (test+0x164dd4)
#8 main ~/.zvm/master/lib/std/start.zig:631:28 (test+0x164dd4)
Previous write of size 8 at 0x555555868c88 by thread T1:
#0 __tsan_memcpy ~/.zvm/master/lib/tsan/tsan_interceptors_memintrinsics.cpp:27:3 (test+0x25738b)
#1 debug.getDebugInfoAllocator ~/.zvm/master/lib/std/debug.zig:1319:5 (test+0xaec04)
#2 debug.getSelfDebugInfo ~/.zvm/master/lib/std/debug.zig:229:66 (test+0xae9f2)
#3 debug.dumpStackTraceFromBase ~/.zvm/master/lib/std/debug.zig:399:44 (test+0x17d974)
#4 debug.dumpSegfaultInfoPosix ~/.zvm/master/lib/std/debug.zig:1462:35 (test+0x177f6a)
#5 debug.handleSegfaultPosix ~/.zvm/master/lib/std/debug.zig:1414:38 (test+0x16f1b1)
#6 __tsan::CallUserSignalHandler(__tsan::ThreadState*, bool, bool, int, __sanitizer::__sanitizer_siginfo*, void*) ~/.zvm/master/lib/tsan/tsan_inte
rceptors_posix.cpp:2117:5 (test+0x25ea16)
#7 NEO::Event::Callback::execute() /usr/src/debug/intel-compute-runtime/compute-runtime-25.05.32567.17/opencl/source/event/event.h:58:29 (libigdrcl.so+0x11
b913) (BuildId: 0f39548f748fd1848da17a8a92ea6783933d5920)
#8 NEO::Event::executeCallbacks(int) /usr/src/debug/intel-compute-runtime/compute-runtime-25.05.32567.17/opencl/source/event/event.cpp:954:26 (libigdrcl.so
+0x11b913)
Location is global 'debug.debug_info_allocator' of size 24 at 0x555555868c88 (test+0x314c88)
Thread T1 (tid=16589, running) created by main thread at:
#0 pthread_create ~/.zvm/master/lib/tsan/tsan_interceptors_posix.cpp:1023:3 (test+0x25a22d)
#1 NEO::Thread::create(void* (*)(void*), void*) /usr/src/debug/intel-compute-runtime/compute-runtime-25.05.32567.17/shared/source/os_interface/linux/os_thr
ead_linux.cpp:19:19 (libigdrcl.so+0x8981d3) (BuildId: 0f39548f748fd1848da17a8a92ea6783933d5920)
#2 tensor.event_manager.appendNewEvent ~<..>/wekua/src/tensor/event_manager.zig:450:33 (test+0x1aeb59)
#3 tensor.main.Tensor(i8).createPitchBuffer ~<..>/wekua/src/tensor/main.zig:113:51 (test+0x1aeb59)
#4 tensor.main.Tensor(i8).empty ~<..>/wekua/src/tensor/main.zig:240:41 (test+0x1b267e)
#5 tensor.empty.create_and_release__anon_40297 ~<..>/wekua/tests/tensor/empty.zig:9:45 (test+0x1b5170)
#6 tensor.empty.test_tensor_creation ~<..>/wekua/tests/tensor/empty.zig:31:31 (test+0x1dbedb)
#7 tensor.empty.test.create and release ~<..>/wekua/tests/tensor/empty.zig:45:29 (test+0x1dc57b)
#8 test_runner.mainServer ~/.zvm/master/lib/compiler/test_runner.zig:126:29 (test+0x16b111)
#9 test_runner.main ~/.zvm/master/lib/compiler/test_runner.zig:60:26 (test+0x16564a)
#10 start.callMain ~/.zvm/master/lib/std/start.zig:647:22 (test+0x164dd4)
#11 start.callMainWithArgs ~/.zvm/master/lib/std/start.zig:616:20 (test+0x164dd4)
#12 main ~/.zvm/master/lib/std/start.zig:631:28 (test+0x164dd4)
SUMMARY: ThreadSanitizer: data race ~/.zvm/master/lib/tsan/tsan_interceptors_memintrinsics.cpp:27:3 in __tsan_memcpy
==================
...
==================
WARNING: ThreadSanitizer: data race (pid=16584)
Write of size 8 at 0x7fffdc0585d8 by thread T1:
#0 __tsan_memset ~/.zvm/master/lib/tsan/tsan_interceptors_memintrinsics.cpp:35:3 (test+0x257499)
#1 mem.Allocator.allocBytesWithAlignment__anon_9684 ~/.zvm/master/lib/std/mem/Allocator.zig:270:21 (test+0xd15d8)
#2 mem.Allocator.allocWithSizeAndAlignment__anon_19803 ~/.zvm/master/lib/std/mem/Allocator.zig:260:40 (test+0x1328a9)
#3 mem.Allocator.allocAdvancedWithRetAddr ~/.zvm/master/lib/std/mem/Allocator.zig:254:75 (test+0x10e04c)
#4 mem.Allocator.alloc__anon_17999 ~/.zvm/master/lib/std/mem/Allocator.zig:178:41 (test+0x10e04c)
#5 debug.Dwarf.scanAllFunctions ~/.zvm/master/lib/std/debug/Dwarf.zig:891:46 (test+0xf0542)
#6 debug.Dwarf.open ~/.zvm/master/lib/std/debug/Dwarf.zig:786:27 (test+0xd4996)
#7 debug.Dwarf.ElfModule.load ~/.zvm/master/lib/std/debug/Dwarf.zig:2410:23 (test+0xb2d45)
#8 debug.SelfInfo.readElfDebugInfo ~/.zvm/master/lib/std/debug/SelfInfo.zig:1060:36 (test+0xb0873)
#9 debug.SelfInfo.lookupModuleDl ~/.zvm/master/lib/std/debug/SelfInfo.zig:480:36 (test+0xbee7c)
#10 debug.SelfInfo.getModuleForAddress ~/.zvm/master/lib/std/debug/SelfInfo.zig:133:35 (test+0xbf622)
#11 debug.printSourceAtAddress__anon_7267 ~/.zvm/master/lib/std/debug.zig:1064:50 (test+0xca904)
#12 debug.dumpStackTraceFromBase ~/.zvm/master/lib/std/debug.zig:418:29 (test+0x17dd4b)
#13 debug.dumpSegfaultInfoPosix ~/.zvm/master/lib/std/debug.zig:1462:35 (test+0x177f6a)
#14 debug.handleSegfaultPosix ~/.zvm/master/lib/std/debug.zig:1414:38 (test+0x16f1b1)
#15 __tsan::CallUserSignalHandler(__tsan::ThreadState*, bool, bool, int, __sanitizer::__sanitizer_siginfo*, void*) ~/.zvm/master/lib/tsan/tsan_int
erceptors_posix.cpp:2117:5 (test+0x25ea16)
#16 NEO::Event::Callback::execute() /usr/src/debug/intel-compute-runtime/compute-runtime-25.05.32567.17/opencl/source/event/event.h:58:29 (libigdrcl.so+0x1
1b913) (BuildId: 0f39548f748fd1848da17a8a92ea6783933d5920)
#17 NEO::Event::executeCallbacks(int) /usr/src/debug/intel-compute-runtime/compute-runtime-25.05.32567.17/opencl/source/event/event.cpp:954:26 (libigdrcl.s
o+0x11b913)
Previous write of size 8 at 0x7fffdc0585d8 by main thread:
#0 __tsan_memcpy ~/.zvm/master/lib/tsan/tsan_interceptors_memintrinsics.cpp:27:3 (test+0x25738b)
#1 array_list.ArrayListAligned(debug.Dwarf.Abbrev.Attr,null).append ~/.zvm/master/lib/std/array_list.zig:262:13 (test+0x10cad5)
#2 debug.Dwarf.parseAbbrevTable ~/.zvm/master/lib/std/debug/Dwarf.zig:1365:29 (test+0x10bec8)
#3 debug.Dwarf.getAbbrevTable ~/.zvm/master/lib/std/debug/Dwarf.zig:1332:32 (test+0x10d3f6)
#4 debug.Dwarf.scanAllFunctions ~/.zvm/master/lib/std/debug/Dwarf.zig:876:51 (test+0xf02b3)
#5 debug.Dwarf.open ~/.zvm/master/lib/std/debug/Dwarf.zig:786:27 (test+0xd4996)
#6 debug.Dwarf.ElfModule.load ~/.zvm/master/lib/std/debug/Dwarf.zig:2410:23 (test+0xb2d45)
#7 debug.SelfInfo.readElfDebugInfo ~/.zvm/master/lib/std/debug/SelfInfo.zig:1060:36 (test+0xb0873)
#8 debug.SelfInfo.lookupModuleDl ~/.zvm/master/lib/std/debug/SelfInfo.zig:480:36 (test+0xbee7c)
#9 debug.SelfInfo.getModuleForAddress ~/.zvm/master/lib/std/debug/SelfInfo.zig:133:35 (test+0xbf622)
#10 debug.printSourceAtAddress__anon_7267 ~/.zvm/master/lib/std/debug.zig:1064:50 (test+0xca904)
#11 debug.writeStackTrace__anon_7255 ~/.zvm/master/lib/std/debug.zig:708:33 (test+0xcb237)
#12 debug.dumpStackTrace ~/.zvm/master/lib/std/debug.zig:501:24 (test+0xa70bb)
#13 test_runner.mainServer ~/.zvm/master/lib/compiler/test_runner.zig:131:53 (test+0x16b297)
#14 test_runner.main ~/.zvm/master/lib/compiler/test_runner.zig:60:26 (test+0x16564a)
#15 start.callMain ~/.zvm/master/lib/std/start.zig:647:22 (test+0x164dd4)
#16 start.callMainWithArgs ~/.zvm/master/lib/std/start.zig:616:20 (test+0x164dd4)
#17 main ~/.zvm/master/lib/std/start.zig:631:28 (test+0x164dd4)
Thread T1 (tid=16589, running) created by main thread at:
#0 pthread_create ~/.zvm/master/lib/tsan/tsan_interceptors_posix.cpp:1023:3 (test+0x25a22d)
#1 NEO::Thread::create(void* (*)(void*), void*) /usr/src/debug/intel-compute-runtime/compute-runtime-25.05.32567.17/shared/source/os_interface/linux/os_thr
ead_linux.cpp:19:19 (libigdrcl.so+0x8981d3) (BuildId: 0f39548f748fd1848da17a8a92ea6783933d5920)
#2 tensor.event_manager.appendNewEvent ~<..>/wekua/src/tensor/event_manager.zig:450:33 (test+0x1aeb59)
#3 tensor.main.Tensor(i8).createPitchBuffer ~<..>/wekua/src/tensor/main.zig:113:51 (test+0x1aeb59)
#4 tensor.main.Tensor(i8).empty ~<..>/wekua/src/tensor/main.zig:240:41 (test+0x1b267e)
#5 tensor.empty.create_and_release__anon_40297 ~<..>/wekua/tests/tensor/empty.zig:9:45 (test+0x1b5170)
#6 tensor.empty.test_tensor_creation ~<..>/wekua/tests/tensor/empty.zig:31:31 (test+0x1dbedb)
#7 tensor.empty.test.create and release ~<..>/wekua/tests/tensor/empty.zig:45:29 (test+0x1dc57b)
#8 test_runner.mainServer ~/.zvm/master/lib/compiler/test_runner.zig:126:29 (test+0x16b111)
#9 test_runner.main ~/.zvm/master/lib/compiler/test_runner.zig:60:26 (test+0x16564a)
#10 start.callMain ~/.zvm/master/lib/std/start.zig:647:22 (test+0x164dd4)
#11 start.callMainWithArgs ~/.zvm/master/lib/std/start.zig:616:20 (test+0x164dd4)
#12 main ~/.zvm/master/lib/std/start.zig:631:28 (test+0x164dd4)
SUMMARY: ThreadSanitizer: data race ~/.zvm/master/lib/tsan/tsan_interceptors_memintrinsics.cpp:35:3 in __tsan_memset
==================
???:?:?: 0x555555701c19 in ??? ()
???:?:?: 0x5555557a0f1e in ??? ()
error: while executing test 'tensor.extra.memory.test.fill and get random complex value', the following command terminated with signal 6 (expected exited with
code 0):
Build Summary: 2/4 steps succeeded; 1 failed; 11/12 tests passed; 1 failed
test transitive failure
└─ run test 11/12 passed, 1 failed
└─ zig test Debug native cached 19ms MaxRSS:51M
└─ options cached
error: the following build command failed with exit code 1:
Steps to reproduce
While my specific case involves Intel's OpenCL runtime, the core issue should be reproducible in any scenario where:
- Multiple threads are active during test execution (could be created by any multi-threading library, not necessarily OpenCL)
- A test failure occurs, triggering Zig's debug system to dump a stack trace
- One or more background threads attempt to access debug information simultaneously
The fundamental issue is that Zig's debug system appears not to be thread-safe, which becomes apparent when using ThreadSanitizer with any multi-threaded application.
https://github.com/ziglang/zig/blob/2a4e06bcb30f71e83b14026bcbade6aac3aece84/lib/std/debug.zig#L1311C1-L1321C2
If you need more specific details about my environment to reproduce this issue, please let me know.
Expected Behavior
The debug system should be thread-safe and not produce data races when multiple threads are present.
Zig Version
0.14.0
Steps to Reproduce and Observed Behavior
I've discovered a data race in Zig's debug system when running tests with ThreadSanitizer enabled in a project that uses OpenCL (which creates additional threads).
When a test fails, Zig attempts to dump the stack trace, but ThreadSanitizer reports data races in the debug system itself. The race occurs between the main thread trying to print debug information and a secondary thread handling signals, both accessing the same debug structures concurrently.
Steps to reproduce
While my specific case involves Intel's OpenCL runtime, the core issue should be reproducible in any scenario where:
The fundamental issue is that Zig's debug system appears not to be thread-safe, which becomes apparent when using ThreadSanitizer with any multi-threaded application.
https://github.com/ziglang/zig/blob/2a4e06bcb30f71e83b14026bcbade6aac3aece84/lib/std/debug.zig#L1311C1-L1321C2
If you need more specific details about my environment to reproduce this issue, please let me know.
Expected Behavior
The debug system should be thread-safe and not produce data races when multiple threads are present.