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]

Reply via email to