No description
- C 89.8%
- Makefile 10.2%
|
|
||
|---|---|---|
| .gitignore | ||
| Makefile | ||
| README.md | ||
| tsan_demo.c | ||
| tsan_fixed.c | ||
ThreadSanitizer demo
tsan_demo.c has a race condition which we can use ThreadSanitizer (TSan) to detect.
Run make then ./tsan_demo.
Example TSan Output
$ ./tsan_demo
Output:
==================
WARNING: ThreadSanitizer: data race (pid=73303)
Write of size 4 at 0x000102978000 by thread T2:
#0 increment_thread tsan_demo.c:20 (tsan_demo:arm64+0x100000690)
Previous write of size 4 at 0x000102978000 by thread T1:
#0 increment_thread tsan_demo.c:20 (tsan_demo:arm64+0x100000690)
Location is global 'shared_counter' at 0x000102978000 (tsan_demo+0x100008000)
Thread T2 (tid=49145052, running) created by main thread at:
#0 pthread_create <null> (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x2f708)
#1 main tsan_demo.c:54 (tsan_demo:arm64+0x1000007f8)
Thread T1 (tid=49145051, finished) created by main thread at:
#0 pthread_create <null> (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x2f708)
#1 main tsan_demo.c:54 (tsan_demo:arm64+0x1000007f8)
SUMMARY: ThreadSanitizer: data race tsan_demo.c:20 in increment_thread
==================
==================
WARNING: ThreadSanitizer: data race (pid=73303)
Read of size 4 at 0x000102978008 by thread T4:
#0 reader_thread tsan_demo.c (tsan_demo:arm64+0x100000728)
Previous write of size 4 at 0x000102978008 by thread T3:
#0 writer_thread tsan_demo.c:31 (tsan_demo:arm64+0x1000006e4)
Location is global 'ready' at 0x000102978008 (tsan_demo+0x100008008)
Thread T4 (tid=49145106, running) created by main thread at:
#0 pthread_create <null> (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x2f708)
#1 main tsan_demo.c:68 (tsan_demo:arm64+0x100000894)
Thread T3 (tid=49145105, finished) created by main thread at:
#0 pthread_create <null> (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x2f708)
#1 main tsan_demo.c:67 (tsan_demo:arm64+0x10000087c)
SUMMARY: ThreadSanitizer: data race tsan_demo.c in reader_thread
==================
=== ThreadSanitizer Demo ===
This program contains intentional data races.
Demo 1: Counter increment race
Expected: 400000, Got: 400000
Demo 2: Read-Write race
Reader shared_data: 42
=== Demo Complete ===
TSan should have reported data races above.
ThreadSanitizer: reported 2 warnings
What This Tells Us:
- Both data races detected, in the two demos in that file.
- Conflicting accesses identified:
- Thread T1 and T2 both write to
shared_counterat the same time due to an increment - Thread T3 writes to
readywhile Thread T4 reads it without synchronization
- Thread T1 and T2 both write to
- Exact locations: Line 20 in
tsan_demo.c(theshared_counter++statement) and line 31 (readyflag) - Result may be correct by luck — the counter shows 400000 here but the race still exists
Running the Fixed Version
$ ./tsan_fixed
Output:
=== ThreadSanitizer Demo - FIXED ===
This program uses proper synchronization.
Compile with: gcc -fsanitize=thread -g -o tsan_fixed tsan_fixed.c -lpthread
Demo 1: Safe counter increment
Expected: 400000, Got: 400000
Demo 2: Safe Read-Write
Reader saw: 42
=== Demo Complete ===
Done. TSan should report NO data races.
What This Tells Us:
- Zero warnings - no data races detected
- Correct results - counter matches expected value consistently
- Proper synchronization using mutexes prevents races
Data races
What makes these bugs data races?
Two or more threads accessing the same memory location where:
- At least one access is a write
- Accesses are not ordered by synchronization (mutex, atomic, etc.)
- Accesses could happen simultaneously
How to interpret TSan output:
WARNING: ThreadSanitizer: data race
Read of size 4 at 0x... by thread T2: <- Second access (Read)
#0 function_name file.c:LINE <- Where in code
Previous write of size 4 at 0x... by thread T1: <- First access (Write)
#0 function_name file.c:LINE <- Where in code
Location is global 'variable_name' <- Which variable
The key information:
- What kind of data race? (read/write vs write/write)
- Where in the code? (file and line number for each thread)
- Which address? (global variable or other shared memory)