From c1d195641d81c702e342772cd48aa3ad3481a352 Mon Sep 17 00:00:00 2001 From: Bill Torpey Date: Wed, 20 May 2020 15:01:29 -0400 Subject: [PATCH] provide minimal support for TSAN (#3929) * provide minimal support for thread sanitizer --- CMakeLists.txt | 19 +++++++++++++++++++ configure.ac | 27 +++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4aafbcc9..0fee2532 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,25 @@ if(ENABLE_ASAN) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope") endif() +# NOTE: Running libzmq under TSAN doesn't make much sense -- synchronization in libzmq is to some extent +# handled by the code "knowing" what threads are allowed to do, rather than by enforcing those +# restrictions, so TSAN generates a lot of (presumably) false positives from libzmq. +# The settings below are intended to enable libzmq to be built with minimal support for TSAN +# such that it can be used along with other code that is also built with TSAN. +option(ENABLE_TSAN "Build with thread sanitizer" OFF) +if(ENABLE_TSAN) + message(STATUS "Instrumenting with Thread Sanitizer") + set(CMAKE_BUILD_TYPE "RelWithDebInfo") + set(TSAN_FLAGS "-fno-omit-frame-pointer -fsanitize=thread") + set(TSAN_CCFLAGS "${TSAN_CCFLAGS} -mllvm -tsan-instrument-memory-accesses=0") + set(TSAN_CCFLAGS "${TSAN_CCFLAGS} -mllvm -tsan-instrument-atomics=0") + set(TSAN_CCFLAGS "${TSAN_CCFLAGS} -mllvm -tsan-instrument-func-entry-exit=1") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TSAN_FLAGS} ${TSAN_CCFLAGS} -fPIE") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TSAN_FLAGS} ${TSAN_CCFLAGS} -fPIE") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${TSAN_FLAGS} -pie -Qunused-arguments") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${TSAN_FLAGS} -pie -Qunused-arguments") +endif() + option(ENABLE_INTRINSICS "Build using compiler intrinsics for atomic ops" OFF) if(ENABLE_INTRINSICS) message(STATUS "Using compiler intrinsics for atomic ops") diff --git a/configure.ac b/configure.ac index 1ea7ee2b..800171f3 100644 --- a/configure.ac +++ b/configure.ac @@ -152,6 +152,33 @@ case "${host_os}" in ;; esac +# Data race/deadlock detection +# NOTE: Running libzmq under TSAN doesn't make much sense -- synchronization in libzmq is to some extent +# handled by the code "knowing" what threads are allowed to do, rather than by enforcing those +# restrictions, so TSAN generates a lot of (presumably) false positives from libzmq. +# The settings below are intended to enable libzmq to be built with minimal support for TSAN +# such that it can be used along with other code that is also built with TSAN. +AC_MSG_CHECKING([whether to enable TSan]) +AC_ARG_ENABLE(thread-sanitizer, [AS_HELP_STRING([--enable-thread-sanitizer=yes/no], + [Build with clang Thread Sanitizer instrumentation])], + [ZMQ_TSAN="$enableval"]) + +if test "x${ZMQ_TSAN}" = "xyes"; then + TSAN_FLAGS="-fno-omit-frame-pointer -fsanitize=thread" + TSAN_CCFLAGS="${TSAN_CCFLAGS} -mllvm -tsan-instrument-memory-accesses=0" + TSAN_CCFLAGS="${TSAN_CCFLAGS} -mllvm -tsan-instrument-atomics=0" + TSAN_CCFLAGS="${TSAN_CCFLAGS} -mllvm -tsan-instrument-func-entry-exit=1" + CFLAGS="${CFLAGS} ${TSAN_FLAGS} ${TSAN_CCFLAGS}" + CXXFLAGS="${CXXFLAGS} ${TSAN_FLAGS} ${TSAN_CCFLAGS}" + LDFLAGS="${LDFLAGS} ${TSAN_FLAGS} -pie" + + AM_CONDITIONAL(ENABLE_TSAN, true) + AC_MSG_RESULT([yes]) +else + AM_CONDITIONAL(ENABLE_TSAN, false) + AC_MSG_RESULT([no]) +fi + # Memory mis-use detection AC_MSG_CHECKING([whether to enable ASan]) AC_ARG_ENABLE(address-sanitizer, [AS_HELP_STRING([--enable-address-sanitizer=yes/no],