How to Configure ThreadSanitizer (TSAN) Compatibility with Abseil: Compiler Flags and Build Guide
Building Abseil with ThreadSanitizer requires passing -fsanitize=thread to both the compiler and linker, configuring CPLUS_INCLUDE_PATH and BAZEL_LINKOPTS to point to a TSAN-instrumented libc++, and setting TSAN_SYMBOLIZER_PATH for readable stack traces.
Abseil-cpp provides built-in support for ThreadSanitizer through automated detection macros and specialized mutex wrappers. To achieve full TSAN compatibility with Abseil, you must configure specific compiler flags, library paths, and Bazel build options that align with the sanitizer's instrumentation requirements.
Essential Compiler and Linker Flags
The foundation of TSAN compatibility with Abseil relies on the -fsanitize=thread flag applied at both compile and link time. According to ci/linux_clang-latest_libcxx_tsan_bazel.sh, you must pass this flag via Bazel's --copt and --linkopt options.
At line 89, the compiler instrumentation is enabled:
--copt=-fsanitize=thread
At line 96, the linker flag ensures the TSAN runtime is embedded in the final binary:
--linkopt=-fsanitize=thread
Additionally, lines 90-91 specify -fno-sanitize-blacklist to disable user-supplied blacklists and maintain complete instrumentation coverage:
--copt=-fno-sanitize-blacklist
Include Paths and Library Configuration
ThreadSanitizer requires a specially instrumented C++ standard library. The Abseil CI demonstrates this using a custom-built libc++ located at /opt/llvm-tsan/.
TSAN-Compatible Standard Library Setup
Set these environment variables before invoking Bazel to point to the TSAN-compatible toolchain:
CPLUS_INCLUDE_PATH=/opt/llvm-tsan/include/c++/v1(line 76): Gives the compiler access to libc++ headers built for the TSAN ABI.BAZEL_LINKOPTS="-L/opt/llvm-tsan/lib ..."(line 75): Ensures the linker finds TSAN-compatible libc++ and libstdc++ libraries. The CI script uses-L/opt/llvm-tsan/lib -lc++ -lc++abi -lgcc_s -lm -Wl,-rpath=/opt/llvm-tsan/lib.TSAN_SYMBOLIZER_PATH=/opt/llvm/bin/llvm-symbolizer(line 99): Provides symbolization for TSAN reports when tests are executed.
Source-Level TSAN Integration in Abseil
Abseil detects TSAN automatically through the ABSL_INTERNAL_HAVE_TSAN_INTERFACE macro, which the compiler defines when -fsanitize=thread is active. This macro enables TSAN-specific wrappers in absl/base/internal/tsan_mutex_interface.h.
Mutex Wrapper Implementation
These wrappers (using the ABSL_TSAN_MUTEX_* macros) forward lock and unlock events to the TSAN runtime, preventing false positives for Abseil's internal synchronization primitives. The implementation is used throughout absl/synchronization/mutex.h and absl/synchronization/mutex.cc. Test coverage includes absl/synchronization/mutex_test.cc, which specifically validates TSAN reports for locked-mutex destruction, and absl/flags/internal/sequence_lock_test.cc, which demonstrates atomic contention scenarios only enabled under TSAN.
Bazel Build Configuration
Filtering TSAN-Incompatible Tests
Abseil marks tests that are incompatible with ThreadSanitizer using the notsan tag. Lines 84-86 and 102-103 of the CI script demonstrate the required filters:
--build_tag_filters="-notsan"
--test_tag_filters="-benchmark,-notsan"
The -benchmark exclusion prevents long-running benchmark tests from generating excessive TSAN output during CI runs.
Complete Build Examples
Minimal Bazel command for TSAN testing:
bazel test ... \
--copt=-fsanitize=thread \
--copt=-fno-sanitize-blacklist \
--linkopt=-fsanitize=thread \
--build_tag_filters="-notsan" \
--test_tag_filters="-benchmark,-notsan" \
--test_env=TSAN_SYMBOLIZER_PATH=/opt/llvm/bin/llvm-symbolizer
Docker-based environment matching the Abseil CI configuration:
docker run -v "$PWD":/abseil-cpp:ro \
-e CPLUS_INCLUDE_PATH=/opt/llvm-tsan/include/c++/v1 \
-e BAZEL_LINKOPTS="-L/opt/llvm-tsan/lib -lc++ -lc++abi -lgcc_s -lm -Wl,-rpath=/opt/llvm-tsan/lib" \
-e TSAN_SYMBOLIZER_PATH=/opt/llvm/bin/llvm-symbolizer \
--cap-add=SYS_PTRACE \
clang:latest \
/bin/bash -c '
bazel test ... \
--copt=-fsanitize=thread \
--copt=-fno-sanitize-blacklist \
--linkopt=-fsanitize=thread \
--build_tag_filters="-notsan" \
--test_tag_filters="-benchmark,-notsan"
'
Summary
- Pass
-fsanitize=threadvia both--coptand--linkoptin your Bazel configuration. - Configure
CPLUS_INCLUDE_PATHandBAZEL_LINKOPTSto use a TSAN-instrumented libc++, typically located at/opt/llvm-tsan/. - Set
TSAN_SYMBOLIZER_PATHto enable readable stack traces in sanitizer reports. - Exclude
notsantagged tests using--build_tag_filters="-notsan"and--test_tag_filters="-benchmark,-notsan". - Include
-fno-sanitize-blacklistto ensure complete instrumentation without source-based exclusions. - Abseil automatically activates
ABSL_INTERNAL_HAVE_TSAN_INTERFACEand mutex wrappers inabsl/base/internal/tsan_mutex_interface.hwhen TSAN is detected.
Frequently Asked Questions
Do I need a special version of the C++ standard library for TSAN compatibility with Abseil?
Yes. ThreadSanitizer requires that the C++ standard library be compiled with TSAN instrumentation. The Abseil CI script uses a custom-built libc++ located at /opt/llvm-tsan/, setting CPLUS_INCLUDE_PATH to /opt/llvm-tsan/include/c++/v1 and adding -L/opt/llvm-tsan/lib via BAZEL_LINKOPTS (lines 75-76) to ensure ABI compatibility between the sanitizer runtime and standard library containers.
What Bazel tags should I use when running TSAN tests on Abseil?
Use --build_tag_filters="-notsan" and --test_tag_filters="-benchmark,-notsan". The Abseil repository marks tests that are incompatible with ThreadSanitizer with the notsan tag, while benchmarks are excluded to prevent excessive execution time. This configuration is documented in ci/linux_clang-latest_libcxx_tsan_bazel.sh at lines 84-86.
How does Abseil prevent false positives in TSAN reports?
Abseil provides TSAN-aware mutex wrappers in absl/base/internal/tsan_mutex_interface.h. When the preprocessor detects -fsanitize=thread (defining ABSL_INTERNAL_HAVE_TSAN_INTERFACE), these wrappers forward lock and unlock operations to the TSAN runtime. This integration prevents the sanitizer from reporting false data races on Abseil's internal synchronization primitives implemented in absl/synchronization/mutex.cc.
Can I use TSAN with any Bazel compilation mode?
Yes. According to the CI configuration in linux_clang-latest_libcxx_tsan_bazel.sh at lines 90-91, any Bazel compilation mode (fastbuild, opt, or dbg) works with TSAN. The only additional requirement beyond the standard -fsanitize=thread flags is including -fno-sanitize-blacklist to disable source-based blacklists and ensure complete instrumentation coverage.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →