This is an automated email from the ASF dual-hosted git repository.
kgiusti pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-dispatch.git
The following commit(s) were added to refs/heads/master by this push:
new 0c3b89b DISPATCH-1450: enable thread sanitizer (TSAN) run time
checking
0c3b89b is described below
commit 0c3b89b25c2da5d26b0433256afdb83dfc0f16f5
Author: Kenneth Giusti <[email protected]>
AuthorDate: Wed Oct 16 09:33:14 2019 -0400
DISPATCH-1450: enable thread sanitizer (TSAN) run time checking
Currently all issues found by running the CTest suite with TSAN are
suppressed. JIRAs will be opened to track each issue at a later date.
This closes #595
---
CMakeLists.txt | 8 ---
README | 62 +++++++++++++++++++++--
cmake/RuntimeChecks.cmake | 124 +++++++++++++++++++++++++++++++++-------------
pom.xml | 1 +
run.py.in | 5 +-
src/CMakeLists.txt | 10 +++-
tests/tsan.supp | 50 +++++++++++++++++++
7 files changed, 210 insertions(+), 50 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index edfb3ff..27fc706 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -191,14 +191,6 @@ if (CMAKE_C_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wno-gnu-statement-expression)
endif()
-if (APPLE)
- set(CATCH_UNDEFINED "-Wl,-flat_namespace")
-elseif(NOT (USE_SANITIZERS OR USE_TSAN))
- set(CATCH_UNDEFINED "-Wl,-z,defs")
-else(APPLE)
- set(CATCH_UNDEFINED "")
-endif(APPLE)
-
##
## Header file installation
##
diff --git a/README b/README
index 412dd68..91cc94f 100644
--- a/README
+++ b/README
@@ -100,10 +100,62 @@ This does the following:
- Run system tests on the installation in 'install'.
-Using Valgrind
-==============
+Run Time Validation
+===================
-If valgrind is installed and cmake option 'USE_VALGRIND' is 'ON' the tests will
-be run with valgrind's memcheck debugger. You can set other types of test
runner
-or modify the valgrind flags by setting the TEST_RUNNER cmake variable.
+The CTest test suite can be configured to enable extra run time
+validation checks against the dispatch router.
+Since run time validation slows down qdrouter considerably it is
+disabled by default. It can be enabled by setting the RUNTIME_CHECK
+build flag via the cmake command.
+
+Note well: Depending on your environment the ctest suite may time out
+if validation is enabled due to the additional run time overhead it
+adds. You can extend the default test time via the ctest "--timeout"
+option. Example:
+
+ctest --timeout 1500 -VV
+
+The Qpid Dispatch Router test suite supports the following run time
+validation tools:
+
+Valgrind Memcheck
+-----------------
+Runs qdrouterd under Valgrind's memcheck leak checker during the CTest
+suite. This will cause tests to fail if a memory error is
+encountered. Use the grinder tool (in the bin directory) to create a
+summary of the errors found during the test run.
+
+The valgrind toolset must be installed in order to use memcheck.
+
+To enable memcheck set the RUNTIME_CHECK build flag to "memcheck":
+
+cmake .. -DRUNTIME_CHECK=memcheck
+
+If valgrind detects errors the qdrouterd process will exit with an
+exit code of 42. This will be displayed in the CTest output. For
+example:
+
+RuntimeError: Errors during teardown:
+Process XXXX error: exit code 42, expected 0
+
+GCC/Clang Thread Sanitizer (TSAN)
+---------------------------------
+This option turns on extra run time threading verification.
+
+Applicable only to GCC versions >= 4.8 and Clang versions >= 4.1.
+
+To enable the thread sanitizer set the RUNTIME_CHECK build flag to "tsan":
+
+cmake .. -DRUNTIME_CHECK=tsan
+
+The TSAN library (libtsan) must be installed in order to use this
+option.
+
+If threading violations are detected during the CTest suite the
+qdrouterd process will exit with an exit code of 66. This will be
+displayed in the CTest output. For example:
+
+RuntimeError: Errors during teardown:
+Process XXXX error: exit code 66, expected 0
diff --git a/cmake/RuntimeChecks.cmake b/cmake/RuntimeChecks.cmake
index 872f943..929bb1d 100644
--- a/cmake/RuntimeChecks.cmake
+++ b/cmake/RuntimeChecks.cmake
@@ -17,41 +17,97 @@
# under the License.
#
-# Configuration for code analysis tools: runtime checking and coverage.
+# Configuration for code analysis tools.
+#
+# The RUNTIME_CHECK variable enables run-time checking when running
+# the CTest test suite. The following tools are supported
+#
+# -DRUNTIME_CHECK=memcheck # runs qdrouter under valgrind's leak checker
+# -DRUNTIME_CHECK=tsan # turns on thread sanitizer
+#
+# This file updates the QDROUTERD_RUNNER and CMAKE_C_FLAGS
+# appropriately for use when running the ctest suite.
-##
-## Valgrind
-##
+
+# Valid options for RUNTIME_CHECK
+#
+set(runtime_checks OFF tsan memcheck helgrind)
+
+# Valgrind configuration
+#
find_program(VALGRIND_EXECUTABLE valgrind DOC "Location of the valgrind
program")
-mark_as_advanced(VALGRIND_EXECUTABLE)
-find_package_handle_standard_args(VALGRIND DEFAULT_MSG VALGRIND_EXECUTABLE)
-option(USE_VALGRIND "Use valgrind when running tests" OFF)
-option(VALGRIND_XML "Write valgrind output as XML" OFF)
-
-if (USE_VALGRIND)
- if (CMAKE_BUILD_TYPE MATCHES "Coverage")
- message(WARNING "Building for coverage analysis; disabling valgrind
run-time error detection")
- else ()
- set(QDROUTERD_RUNNER "${VALGRIND_EXECUTABLE} --quiet --leak-check=full
--show-leak-kinds=definite --errors-for-leak-kinds=definite --error-exitcode=42
--suppressions=${CMAKE_SOURCE_DIR}/tests/valgrind.supp")
- if (VALGRIND_XML)
- set(QDROUTERD_RUNNER "${QDROUTERD_RUNNER} --xml=yes
--xml-file=valgrind-%p.xml")
- endif()
- endif ()
+set(VALGRIND_SUPPRESSIONS "${CMAKE_SOURCE_DIR}/tests/valgrind.supp" CACHE
STRING "Suppressions file for valgrind")
+set(VALGRIND_COMMON_ARGS "--error-exitcode=42 --xml=yes
--xml-file=valgrind-%p.xml --quiet --suppressions=${VALGRIND_SUPPRESSIONS}")
+mark_as_advanced(VALGRIND_EXECUTABLE VALGRIND_SUPPRESSIONS
VALGRIND_COMMON_ARGS)
+macro(assert_has_valgrind)
+ if(NOT VALGRIND_EXECUTABLE)
+ message(FATAL_ERROR "valgrind is not available")
+ endif()
+endmacro()
+
+# Check for compiler's support of sanitizers.
+# Currently have tested back to gcc 7.4.0 and clang 6.0.0, older
+# versions may require more work
+#
+if((CMAKE_C_COMPILER_ID MATCHES "GNU"
+ AND (CMAKE_C_COMPILER_VERSION VERSION_GREATER 7.4
+ OR CMAKE_C_COMPILER_VERSION VERSION_EQUAL 7.4))
+ OR (CMAKE_C_COMPILER_ID MATCHES "Clang"
+ AND (CMAKE_C_COMPILER_VERSION VERSION_GREATER 6.0
+ OR CMAKE_C_COMPILER_VERSION VERSION_EQUAL 6.0)))
+ set(HAS_SANITIZERS TRUE)
endif()
+macro(assert_has_sanitizers)
+ if(NOT HAS_SANITIZERS)
+ message(FATAL_ERROR "compiler sanitizers are not available")
+ endif()
+endmacro()
-##
-## Sanitizers
-##
-option(USE_SANITIZERS "Compile with sanitizers (ASan, UBSan, TSan);
incompatible with Valgrind" OFF)
-if (USE_SANITIZERS)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize=leak
-fsanitize=undefined")
- add_compile_options(-g)
- add_compile_options(-fno-omit-frame-pointer)
-endif (USE_SANITIZERS)
-
-option(USE_TSAN "Compile with ThreadSanitizer (TSan); incompatible with
Valgrind" OFF)
-if (USE_TSAN)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=thread")
- add_compile_options(-g)
- add_compile_options(-fno-omit-frame-pointer)
-endif (USE_TSAN)
+# Set RUNTIME_CHECK value and deal with the older cmake flags for
+# valgrind and TSAN
+#
+macro(deprecated_enable_check old new doc)
+ if (${old})
+ message("WARNING: option ${old} is deprecated, use -DRUNTIME_CHECK=${new}
instead")
+ set(RUNTIME_CHECK_DEFAULT ${new})
+ endif()
+ unset(${old} CACHE)
+endmacro()
+option(VALGRIND_XML "Write valgrind output as XML (DEPRECATED)" OFF)
+deprecated_enable_check(USE_VALGRIND memcheck "Use valgrind to detect run-time
problems")
+deprecated_enable_check(USE_TSAN tsan "Compile with thread sanitizer (tsan)")
+
+set(RUNTIME_CHECK ${RUNTIME_CHECK_DEFAULT} CACHE STRING "Enable runtime
checks. Valid values: ${runtime_checks}")
+if(CMAKE_BUILD_TYPE MATCHES "Coverage" AND RUNTIME_CHECK)
+ message(FATAL_ERROR "Cannot set RUNTIME_CHECK with
CMAKE_BUILD_TYPE=Coverage")
+endif()
+
+if(RUNTIME_CHECK STREQUAL "memcheck")
+ assert_has_valgrind()
+ message(STATUS "Runtime memory checker: valgrind memcheck")
+ set(QDROUTERD_RUNNER "${VALGRIND_EXECUTABLE} --tool=memcheck
--leak-check=full --show-leak-kinds=definite --errors-for-leak-kinds=definite
${VALGRIND_COMMON_ARGS}")
+
+elseif(RUNTIME_CHECK STREQUAL "helgrind")
+ assert_has_valgrind()
+ message(STATUS "Runtime race checker: valgrind helgrind")
+ set(QDROUTERD_RUNNER "${VALGRIND_EXECUTABLE} --tool=helgrind
${VALGRIND_COMMON_ARGS}")
+
+#elseif(RUNTIME_CHECK STREQUAL "asan")
+# assert_has_sanitizers()
+# message(STATUS "Runtime memory checker: gcc/clang memory sanitizers")
+# set(SANITIZE_FLAGS "-g -fno-omit-frame-pointer
-fsanitize=address,undefined")
+# set(TEST_WRAP_PREFIX "${CMAKE_SOURCE_DIR}/tests/preload_asan.sh
$<TARGET_FILE:qpid-proton-core>")
+
+elseif(RUNTIME_CHECK STREQUAL "tsan")
+ assert_has_sanitizers()
+ find_library(TSAN_LIBRARY NAME tsan libtsan)
+ if(TSAN_LIBRARY-NOTFOUND)
+ message(FATAL_ERROR "libtsan not installed - thread sanitizer not
available")
+ endif(TSAN_LIBRARY-NOTFOUND)
+ message(STATUS "Runtime race checker: gcc/clang thread sanitizer")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -fno-omit-frame-pointer
-fsanitize=thread")
+ set(RUNTIME_TSAN_ENV_OPTIONS "second_deadlock_stack=1
suppressions=${CMAKE_SOURCE_DIR}/tests/tsan.supp")
+
+elseif(NOT RUNTIME_CHECK STREQUAL "")
+ message(FATAL_ERROR "'RUNTIME_CHECK=${RUNTIME_CHECK}' is invalid, valid
values: ${runtime_checks}")
+endif()
diff --git a/pom.xml b/pom.xml
index 375a479..95fece9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -97,6 +97,7 @@
<exclude>**/*.lock</exclude>
<exclude>**/MANIFEST.in</exclude>
<exclude>**/valgrind.supp</exclude>
+ <exclude>**/tsan.supp</exclude>
<exclude>**/*.json.in</exclude>
<exclude>**/*.json</exclude>
<exclude>**/*.svg</exclude>
diff --git a/run.py.in b/run.py.in
index bda8e13..1ab6379 100755
--- a/run.py.in
+++ b/run.py.in
@@ -82,8 +82,9 @@ env_vars = {
'QPID_DISPATCH_HOME': "${CMAKE_SOURCE_DIR}",
'QPID_DISPATCH_LIB': "${CMAKE_BINARY_DIR}/src/${QPID_DISPATCH_LIB}",
'QPID_DISPATCH_RUNNER': qdrouterd_runner,
- 'MALLOC_CHECK_': "3", # 3 = print error and abort
- 'MALLOC_PERTURB_': "153" # 153 = 0x99 freed memory pattern
+ 'MALLOC_CHECK_': "3", # 3 = print error and abort
+ 'MALLOC_PERTURB_': "153", # 153 = 0x99 freed memory pattern
+ 'TSAN_OPTIONS': "${RUNTIME_TSAN_ENV_OPTIONS}"
}
os.environ.update(env_vars)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5e7313b..b70dde2 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -139,11 +139,19 @@ if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
PROPERTY COMPILE_FLAGS -Wno-strict-aliasing)
endif (CMAKE_C_COMPILER_ID STREQUAL "GNU")
+# DISPATCH-1384 - for MacOS use flat_namespace instead of 2 level
+# namespace (acts more like linux)
+if (APPLE)
+ set(QPID_DISPATCH_LIB_LINK_FLAGS "-Wl,-flat_namespace
${QPID_DISPATCH_LIB_LINK_FLAGS}")
+else(APPLE)
+ set(QPID_DISPATCH_LIB_LINK_FLAGS "-Wl,-z,defs
${QPID_DISPATCH_LIB_LINK_FLAGS}")
+endif(APPLE)
+
add_library(qpid-dispatch SHARED ${qpid_dispatch_SOURCES})
target_include_directories(qpid-dispatch PRIVATE ${qpid_dispatch_INCLUDES})
target_link_libraries(qpid-dispatch ${qpid_dispatch_LIBRARIES})
set_target_properties(qpid-dispatch PROPERTIES
- LINK_FLAGS "${CATCH_UNDEFINED}")
+ LINK_FLAGS "${QPID_DISPATCH_LIB_LINK_FLAGS}")
install(TARGETS qpid-dispatch
LIBRARY DESTINATION ${QPID_DISPATCH_HOME})
diff --git a/tests/tsan.supp b/tests/tsan.supp
new file mode 100644
index 0000000..68d89d8
--- /dev/null
+++ b/tests/tsan.supp
@@ -0,0 +1,50 @@
+# ThreadSanitizer (tsan) suppression file
+#
+race:libqpid-proton-proactor
+deadlock:libpython
+
+race:qd_vlog_impl
+deadlock:qd_vlog_impl
+race:qd_log_entity
+
+race:qdr_core_free
+
+race:qd_alloc
+race:qd_entity_refresh_allocator
+
+mutex:qd_router_timer_handler
+race:qdr_process_tick_CT
+deadlock:qd_timer
+
+race:qdr_connection_process
+
+race:qdr_link_flow
+race:qdr_link_flow_CT
+race:qdr_link_process_deliveries
+race:qdr_link_stalled_outbound
+race:qdr_link_first_attach
+
+race:qdr_delivery_link_peers_CT
+race:qdr_delivery_push_CT
+race:qdr_delivery_disposition
+race:qdr_delivery_anycast_update_CT
+
+race:qdr_connection_set_context
+race:qdr_connection_get_context
+
+race:notify_downstream
+race:notify_upstream
+
+race:qdr_delivery_mcast_inbound_update_CT
+race:qdr_delivery_mcast_outbound_update_CT
+race:qdr_delivery_mcast_outbound_settled_CT
+race:qdr_delivery_mcast_outbound_disposition_CT
+
+race:qd_message_receive
+race:qd_message_receive_complete
+
+mutex:qdr_forward_on_message
+
+mutex:qd_policy_amqp_open
+mutex:qd_policy_amqp_open_connector
+
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]