ThreadSanitizer: signal-unsafe call inside of a signal
- Dominant language
- C++
- Stars
- 21.5k
- Forks
- 3.5k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 2
Description
**Describe the bug**
Using a thread sanitizer setup with clang, our CI seems to hit an assertion; probably in a background thread. After that, our log is flooded with sanitizer violations that seem to be related to Catch, starting like this:
```
terminate called without an active exception
==================
WARNING: ThreadSanitizer: signal-unsafe call inside of a signal (pid=46206)
#0 operator new(unsigned long) /tmp/llvm-project/compiler-rt/lib/tsan/rtl/tsan_new_delete.cc:64 (sync-test+0x531217)
#1 __gnu_cxx::new_allocator::allocate(unsigned long, void const*) /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/../../../../include/c++/7/ext/new_allocator.h:111:27 (sync-test+0x53c998)
#2 std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator const&) /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/../../../../include/c++/7/bits/basic_string.tcc:1057:49 (sync-test+0x53c70b)
#3 char* std::string::_S_construct(char const*, char const*, std::allocator const&, std::forward_iterator_tag) /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/../../../../include/c++/7/bits/basic_string.tcc:578:14 (sync-test+0x5410b4)
#4 char* std::string::_S_construct_aux(char const*, char const*, std::allocator const&, std::__false_type) /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/../../../../include/c++/7/bits/basic_string.h:5033:18 (sync-test+0x540f58)
#5 char* std::string::_S_construct(char const*, char const*, std::allocator const&) /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/../../../../include/c++/7/bits/basic_string.h:5054:11 (sync-test+0x540ed8)
#6 std::basic_string, std::allocator >::basic_string(char const*, unsigned long, std::allocator const&) /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/../../../../include/c++/7/bits/basic_string.tcc:657:19 (sync-test+0x5ca878)
#7 Catch::StringRef::operator std::string() const /home/jenkins/agent/workspace/ObjectBox-Sanitizers_sync_2/cbuild/Debug-tsan/objectbox/src/main/cpp/sync/test/../../../../../../../../external/catch/catch.hpp:610:20 (sync-test+0x5a90aa)
#8 Catch::RunContext::handleFatalErrorCondition(Catch::StringRef) /home/jenkins/agent/workspace/ObjectBox-Sanitizers_sync_2/cbuild/Debug-tsan/objectbox/src/main/cpp/sync/test/../../../../../../../../external/catch/catch.hpp:12693:55 (sync-test+0x55f2a5)
#9 (anonymous namespace)::reportFatal(char const*) /home/jenkins/agent/workspace/ObjectBox-Sanitizers_sync_2/cbuild/Debug-tsan/objectbox/src/main/cpp/sync/test/../../../../../../../../external/catch/catch.hpp:10644:56 (sync-test+0x5505dd)
#10 Catch::FatalConditionHandler::handleSignal(int) /home/jenkins/agent/workspace/ObjectBox-Sanitizers_sync_2/cbuild/Debug-tsan/objectbox/src/main/cpp/sync/test/../../../../../../../../external/catch/catch.hpp:10738:9 (sync-test+0x550443)
#11 __tsan::CallUserSignalHandler(__tsan::ThreadState*, bool, bool, bool, int, __sanitizer::__sanitizer_siginfo*, void*) /tmp/llvm-project/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:1914 (sync-test+0x487bd3)
#12 __gnu_cxx::__verbose_terminate_handler() (libstdc++.so.6+0x607d4)
#13 [application code stack follows...]
```
Another example:
```
WARNING: ThreadSanitizer: signal-unsafe call inside of a signal (pid=46206)
#0 operator delete(void*) /tmp/llvm-project/compiler-rt/lib/tsan/rtl/tsan_new_delete.cc:126 (sync-test+0x531ae9)
#1 __gnu_cxx::new_allocator::deallocate(std::string*, unsigned long) /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/../../../../include/c++/7/ext/new_allocator.h:125:2 (sync-test+0x5ccde3)
#2 std::allocator_traits >::deallocate(std::allocator&, std::string*, unsigned long) /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/../../../../include/c++/7/bits/alloc_traits.h:462:13 (sync-test+0x5ccd93)
#3 std::__cxx1998::_Vector_base >::_M_deallocate(std::string*, unsigned long) /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/../../../../include/c++/7/bits/stl_vector.h:180:4 (sync-test+0x612b0b)
#4 void std::__cxx1998::vector >::_M_realloc_insert(__gnu_cxx::__normal_iterator > >, std::string const&) /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/../../../../include/c++/7/bits/vector.tcc:448:7 (sync-test+0x63d638)
#5 std::__cxx1998::vector >::push_back(std::string const&) /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/../../../../include/c++/7/bits/stl_vector.h:948:4 (sync-test+0x63d19e)
#6 std::__debug::vector >::push_back(std::string const&) /opt/rh/devtoolset-7/root/usr/lib/gcc/x86_64-redhat-linux/7/../../../../include/c++/7/debug/vector:467:9 (sync-test+0x5b9dbe)
#7 Catch::XmlWriter::startElement(std::string const&, Catch::XmlFormatting) /home/jenkins/agent/workspace/ObjectBox-Sanitizers_sync_2/cbuild/Debug-tsan/objectbox/src/main/cpp/sync/test/../../../../../../../../external/catch/catch.hpp:15326:16 (sync-test+0x5709e7)
#8 Catch::XmlWriter::scopedElement(std::string const&, Catch::XmlFormatting) /home/jenkins/agent/workspace/ObjectBox-Sanitizers_sync_2/cbuild/Debug-tsan/objectbox/src/main/cpp/sync/test/../../../../../../../../external/catch/catch.hpp:15334:9 (sync-test+0x570c3e)
#9 Catch::JunitReporter::writeGroup(Catch::CumulativeReporterBase::Node::Node::SectionNode> > const&, double) /home/jenkins/agent/workspace/ObjectBox-Sanitizers_sync_2/cbuild/Debug-tsan/objectbox/src/main/cpp/sync/test/../../../../../../../../external/catch/catch.hpp:16558:42 (sync-test+0x57a2a7)
#10 Catch::JunitReporter::testGroupEnded(Catch::TestGroupStats const&) /home/jenkins/agent/workspace/ObjectBox-Sanitizers_sync_2/cbuild/Debug-tsan/objectbox/src/main/cpp/sync/test/../../../../../../../../external/catch/catch.hpp:16550:9 (sync-test+0x57a1a6)
#11 Catch::RunContext::testGroupEnded(std::string const&, Catch::Totals const&, unsigned long, unsigned long) /home/jenkins/agent/workspace/ObjectBox-Sanitizers_sync_2/cbuild/Debug-tsan/objectbox/src/main/cpp/sync/test/../../../../../../../../external/catch/catch.hpp:12505:21 (sync-test+0x55c1b4)
#12 Catch::RunContext::handleFatalErrorCondition(Catch::StringRef) /home/jenkins/agent/workspace/ObjectBox-Sanitizers_sync_2/cbuild/Debug-tsan/objectbox/src/main/cpp/sync/test/../../../../../../../../external/catch/catch.hpp:12720:9 (sync-test+0x55f5b4)
#13 (anonymous namespace)::reportFatal(char const*) /home/jenkins/agent/workspace/ObjectBox-Sanitizers_sync_2/cbuild/Debug-tsan/objectbox/src/main/cpp/sync/test/../../../../../../../../external/catch/catch.hpp:10644:56 (sync-test+0x5505dd)
#14 Catch::FatalConditionHandler::handleSignal(int) /home/jenkins/agent/workspace/ObjectBox-Sanitizers_sync_2/cbuild/Debug-tsan/objectbox/src/main/cpp/sync/test/../../../../../../../../external/catch/catch.hpp:10738:9 (sync-test+0x550443)
#15 __tsan::CallUserSignalHandler(__tsan::ThreadState*, bool, bool, bool, int, __sanitizer::__sanitizer_siginfo*, void*) /tmp/llvm-project/compiler-rt/lib/tsan/rtl/tsan_interceptors.cc:1914 (sync-test+0x487bd3)
#16 __gnu_cxx::__verbose_terminate_handler() (libstdc++.so.6+0x607d4)
[...]
```
In total, there are 68 warnings like that in the log.
**Expected behavior**
Catch should not trigger tsan warnings
**Reproduction steps**
Currently, around 3 out of 4 builds produce an assertion and thus trigger the "warning flood". No simple repro known.
**Platform information:**
- OS: **CentOS**
- Compiler+version: **clang 9.0.0**
- Catch version: **v2.11.0**
**Additional context**
[async-signal-safe functions](http://man7.org/linux/man-pages/man7/signal-safety.7.html)
Of course we will need to fix triggering the assertion and this is not the issue. **The question is** if Catch is doing things in a signal handler that it should not do, like calling new and delete.
Contributor guide
Assessment
This issue has not been assessed yet.