After a fork() in a multithreaded program, the child can safely call only async-signal-safe functions (see signal-safety(7)) until such time as it calls execv.
The standard library (std
namespace) is not async-signal-safe. Also, throw
, isn’t.
There was an alternative implementation using readdir
(https://github.com/bitcoin/bitcoin/pull/32529), but that isn’t async-signal-safe either, and that implementation was still using throw
.
So temporarily revert this feature.
A follow-up in the future can add it back, using only async-signal-safe functions, or by using a different approach.
Fixes #32524 Fixes #33015 Fixes #32855
For reference, a failure can manifest in the GCC debug mode:
- While
fork
ing, a debug mode mutex is held (by any other thread). - The
fork
ed child tries to use the stdard libary beforeexecv
and deadlocks.
This may look like the following:
0(gdb) thread apply all bt
1
2Thread 1 (Thread 0xf58f4b40 (LWP 774911) "b-httpworker.2"):
3[#0](/bitcoin-bitcoin/0/) 0xf7f4f589 in __kernel_vsyscall ()
4[#1](/bitcoin-bitcoin/1/) 0xf79e467e in ?? () from /lib32/libc.so.6
5[#2](/bitcoin-bitcoin/2/) 0xf79eb582 in pthread_mutex_lock () from /lib32/libc.so.6
6[#3](/bitcoin-bitcoin/3/) 0xf7d93bf2 in ?? () from /lib32/libstdc++.so.6
7[#4](/bitcoin-bitcoin/4/) 0xf7d93f36 in __gnu_debug::_Safe_iterator_base::_M_attach(__gnu_debug::_Safe_sequence_base*, bool) () from /lib32/libstdc++.so.6
8[#5](/bitcoin-bitcoin/5/) 0x5668810a in __gnu_debug::_Safe_iterator_base::_Safe_iterator_base (this=0xf58f13ac, __seq=0xf58f13f8, __constant=false) at /bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/debug/safe_base.h:91
9[#6](/bitcoin-bitcoin/6/) 0x56ddfb50 in __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<int*, std::__cxx1998::vector<int, std::allocator<int> > >, std::__debug::vector<int, std::allocator<int> >, std::forward_iterator_tag>::_Safe_iterator (this=0xf58f13a8, __i=3, __seq=0xf58f13f8) at /bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/debug/safe_iterator.h:162
10[#7](/bitcoin-bitcoin/7/) 0x56ddfacb in __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<int*, std::__cxx1998::vector<int, std::allocator<int> > >, std::__debug::vector<int, std::allocator<int> >, std::bidirectional_iterator_tag>::_Safe_iterator (this=0xf58f13a8, __i=3, __seq=0xf58f13f8) at /bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/debug/safe_iterator.h:539
11[#8](/bitcoin-bitcoin/8/) 0x56ddfa5b in __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<int*, std::__cxx1998::vector<int, std::allocator<int> > >, std::__debug::vector<int, std::allocator<int> >, std::random_access_iterator_tag>::_Safe_iterator (this=0xf58f13a8, __i=3, __seq=0xf58f13f8) at /bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/debug/safe_iterator.h:687
12[#9](/bitcoin-bitcoin/9/) 0x56ddd3f6 in std::__debug::vector<int, std::allocator<int> >::begin (this=0xf58f13f8) at /bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/debug/vector:300
13[#10](/bitcoin-bitcoin/10/) 0x57d83701 in subprocess::detail::Child::execute_child (this=0xf58f156c) at ./util/subprocess.h:1372
14[#11](/bitcoin-bitcoin/11/) 0x57d80a7c in subprocess::Popen::execute_process (this=0xf58f1cd8) at ./util/subprocess.h:1231
15[#12](/bitcoin-bitcoin/12/) 0x57d6d2b4 in subprocess::Popen::Popen<subprocess::input, subprocess::output, subprocess::error, subprocess::close_fds> (this=0xf58f1cd8, cmd_args="fake.py enumerate", args=..., args=..., args=..., args=...) at ./util/subprocess.h:964
16[#13](/bitcoin-bitcoin/13/) 0x57d6b597 in RunCommandParseJSON (str_command="fake.py enumerate", str_std_in="") at ./common/run_command.cpp:27
17[#14](/bitcoin-bitcoin/14/) 0x57a90547 in ExternalSigner::Enumerate (command="fake.py", signers=std::__debug::vector of length 0, capacity 0, chain="regtest") at ./external_signer.cpp:28
18[#15](/bitcoin-bitcoin/15/) 0x56defdab in enumeratesigners()::$_0::operator()(RPCHelpMan const&, JSONRPCRequest const&) const (this=0xf58f2ba0, self=..., request=...) at ./rpc/external_signer.cpp:51
19...
20(truncated, only one thread exists)