diff options
author | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2020-07-02 20:04:31 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-07-03 00:31:10 +0000 |
commit | bf36c726bd2befb026236b10c962e5cb55bceadc (patch) | |
tree | 038ca7a945c36b1fa7906cd39ae7ee3440554566 /src/mongo/unittest/death_test.cpp | |
parent | bc470fa684619411b721d176f806ea8093a0c5f9 (diff) | |
download | mongo-bf36c726bd2befb026236b10c962e5cb55bceadc.tar.gz |
SERVER-48887 C++ death tests should fail on TSAN exit code
Diffstat (limited to 'src/mongo/unittest/death_test.cpp')
-rw-r--r-- | src/mongo/unittest/death_test.cpp | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/src/mongo/unittest/death_test.cpp b/src/mongo/unittest/death_test.cpp index 50ec0fda6db..3cba33b8ccd 100644 --- a/src/mongo/unittest/death_test.cpp +++ b/src/mongo/unittest/death_test.cpp @@ -35,6 +35,7 @@ #include "mongo/bson/json.h" #include "mongo/unittest/death_test.h" +#include "mongo/util/exit_code.h" #ifndef _WIN32 #include <cstdio> @@ -47,6 +48,10 @@ #include <TargetConditionals.h> #endif +#if defined(__has_feature) && __has_feature(thread_sanitizer) +#include <sanitizer/common_interface_defs.h> +#endif + #include <sstream> #include "mongo/logv2/log.h" @@ -81,6 +86,15 @@ void logAndThrowWithErrnoAt(const StringData expr, "{} failed: {} @{}:{}"_format(expr, errnoWithDescription(err), file, line)); } +#if defined(__has_feature) && __has_feature(thread_sanitizer) +// Our callback handler exits with the default TSAN exit code so we can check in the death test +// framework Without this, the use could override the exit code and get a false positive that the +// test passes in TSAN builds. +void sanitizerDieCallback() { + _exit(EXIT_THREAD_SANITIZER); +} +#endif + void DeathTestBase::_doTest() { #if defined(_WIN32) LOGV2(24133, "Skipping death test on Windows"); @@ -150,7 +164,14 @@ void DeathTestBase::_doTest() { } } if (WIFSIGNALED(stat) || (WIFEXITED(stat) && WEXITSTATUS(stat) != 0)) { - // Exited with a signal or non-zero code. Validate the expected message. +// Exited with a signal or non-zero code. Validate the expected message. +#if defined(__has_feature) && __has_feature(thread_sanitizer) + if (WEXITSTATUS(stat) == EXIT_THREAD_SANITIZER) { + FAIL( + "Death test exited with Thread Sanitizer exit code, search test output for " + "'ThreadSanitizer' for more information"); + } +#endif if (_isRegex()) { ASSERT_STRING_SEARCH_REGEX(os.str(), _doGetPattern()) << " @" << _getFile() << ":" << _getLine(); @@ -180,6 +201,10 @@ void DeathTestBase::_doTest() { if (setrlimit(RLIMIT_CORE, &kNoCoreDump) == -1) logAndThrowWithErrno("setrlimit(RLIMIT_CORE, &kNoCoreDump)"); +#if defined(__has_feature) && __has_feature(thread_sanitizer) + __sanitizer_set_death_callback(sanitizerDieCallback); +#endif + try { auto test = _doMakeTest(); LOGV2(23515, "Running DeathTest in child"); |