catchorg / catchorg/Catch2

ThreadSanitizer: signal-unsafe call inside of a signal

Open
#1,833 5 comments 8 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.