bitcoincore growth – Segfault when clearing mempool. What am I doing incorrect?



For a analysis challenge, I’m attempting to periodically clear the content material of my Bitcoin node’s mempool. For this function I’ve created a brand new thread in init.cpp utilizing the increase threadgroup (I’ve experimented with this efficiently with a unique challenge previously and I’m certain this isn’t the reason for the issue) within the Bitcoin Core software program. Within the new thread, I periodically name a operate func (outlined under), the only function of which is to clear the content material of the node’s mempool.

void func()
    LOCK2(cs_main, mempool.cs);

I test for and lock vital sections that I believe I ought to earlier than I modify the mempool (the code above mimics what occurs when a brand new transaction is added to the mempool; I mainly checked out what occurs within the NetMsgType::TX department of ProcessMessage in net_processing.cpp after which AcceptToMemoryPoolWorker in validation.cpp and mimic that).


After I run Bitcoin after efficiently compiling my code, I typically instantly (i.e., as quickly because the GUI window pops up) and typically a lot later within the execution face a segfault that causes this system to crash.

[email protected]:~$ bitcoin-qt -mpctimeout=1
Segmentation fault (core dumped)

Within the code above, the operate func is executed each 1 minute (represented by mpctimeout=1).


What may very well be inflicting the segfault? May it probably be race situations when attempting to get a lock on the mempool or execution of the primary thread? It’s my understanding that LOCK2 ought to preserve attempting to get a lock on the vital sections once they develop into out there in case they’re already locked by one other thread/course of. Since these locks solely exist inside the scope of the operate func, they ought to ideally be launched when getting back from the operate.

Edit # 1:

Some debugging exhibits that the segfault does not happen whereas func is being executed however whereas the thread is put in sleep for mpctimeout period of time. This leaves me questioning whether or not clearing the mempool has some long-term results? I’ve made certain that the lock is launched by verifying that transactions are certainly accepted to the mempool whereas the brand new thread is asleep. The segfault nonetheless happens even when the mpctimeout worth is giant (e.g., 1 hour).

FWIW, I exploit increase::this_thread::sleep_for to place the thread to sleep. I assume this works with out fault and that the segfault is as an alternative prompted in the long term as a consequence of clearing the mempool. Any ideas?

Edit # 2:

Under is the output of debugging the binary by gdb:

(gdb) run
Beginning program: /usr/native/bin/bitcoin-qt
[Thread debugging using libthread_db enabled]
Utilizing host libthread_db library "/lib/x86_64-linux-gnu/".
[New Thread 0x7fffe9900700 (LWP 25643)]
[New Thread 0x7fffdf37f700 (LWP 25644)]
[New Thread 0x7fffdeb7e700 (LWP 25645)]
[New Thread 0x7fffdd0e7700 (LWP 25646)]
[New Thread 0x7fffc7cd2700 (LWP 25648)]
[New Thread 0x7fffc74d1700 (LWP 25649)]
[New Thread 0x7fffc6cd0700 (LWP 25650)]
[New Thread 0x7fffc64cf700 (LWP 25651)]
[New Thread 0x7fffc5cce700 (LWP 25652)]
[New Thread 0x7fffc54cd700 (LWP 25653)]
[New Thread 0x7fffc4ccc700 (LWP 25654)]
[New Thread 0x7fffa7fff700 (LWP 25655)]
[New Thread 0x7fffa77fe700 (LWP 25656)]
[New Thread 0x7fffa6ffd700 (LWP 25657)]
[New Thread 0x7fffa67fc700 (LWP 25658)]
[New Thread 0x7fffa5ffb700 (LWP 25659)]
[New Thread 0x7fffa57fa700 (LWP 25660)]
[New Thread 0x7fffa4f63700 (LWP 25661)]
[New Thread 0x7fff8dffd700 (LWP 25662)]
[New Thread 0x7fff8d7fc700 (LWP 25663)]
[New Thread 0x7fff8cffb700 (LWP 25664)]
[New Thread 0x7fff7bfff700 (LWP 25665)]
[New Thread 0x7fff7b7fe700 (LWP 25666)]
[New Thread 0x7fff7affd700 (LWP 25667)]
[New Thread 0x7fff7a7fc700 (LWP 25668)]
[New Thread 0x7fff79ffb700 (LWP 25669)]
[New Thread 0x7fff797fa700 (LWP 25670)]
[New Thread 0x7fff78ff9700 (LWP 25671)]
[New Thread 0x7fff53fff700 (LWP 25672)]
[New Thread 0x7fff537fe700 (LWP 25673)]
[New Thread 0x7fff4a174700 (LWP 25677)]
[New Thread 0x7ffed1a7b700 (LWP 25678)]
[Thread 0x7ffed1a7b700 (LWP 25678) exited]
[New Thread 0x7ffed127a700 (LWP 25679)]
[New Thread 0x7ffed0a79700 (LWP 25680)]
[New Thread 0x7ffecbfff700 (LWP 25681)]
[New Thread 0x7ffecb7fe700 (LWP 25682)]
[New Thread 0x7ffecaffd700 (LWP 25683)]
[New Thread 0x7ffeca7fc700 (LWP 25684)]
[New Thread 0x7ffec9ffb700 (LWP 25685)]
[New Thread 0x7ffec97fa700 (LWP 25686)]
[New Thread 0x7ffec8ff9700 (LWP 25687)]
[Thread 0x7ffed127a700 (LWP 25679) exited]
[Thread 0x7ffecb7fe700 (LWP 25682) exited]

Thread 40 "bitcoin-msghand" acquired sign SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffec9ffb700 (LWP 25685)]
__gnu_cxx::__atomic_add_dispatch (__val=1, __mem=0x1a45fe36190ee438)
    at /usr/embrace/c++/7/ext/atomicity.h:96
96        __atomic_add(__mem, __val);

I suppose that the segfault is prompted when attempting to replace an atomic variable.

Edit # 3:

gdb backtrace

#0  0x0000555555854178 in __gnu_cxx::__atomic_add_dispatch (__val=1, __mem=0xf) at /usr/embrace/c++/7/ext/atomicity.h:96
#1  0x0000555555854178 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_add_ref_copy() (this=0x7) at /usr/embrace/c++/7/bits/shared_ptr_base.h:138
#2  0x0000555555854178 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count(std::__shared_count<(__gnu_cxx::_Lock_policy)2> const&) (__r=..., this=0x7ffef5ff71b8)
    at /usr/embrace/c++/7/bits/shared_ptr_base.h:691
#3  0x0000555555854178 in std::__shared_ptr<CTransaction const, (__gnu_cxx::_Lock_policy)2>::__shared_ptr(std::__shared_ptr<CTransaction const, (__gnu_cxx::_Lock_policy)2> const&)
    (this=0x7ffef5ff71b0) at /usr/embrace/c++/7/bits/shared_ptr_base.h:1121
#4  0x0000555555854178 in std::shared_ptr<CTransaction const>::shared_ptr(std::shared_ptr<CTransaction const> const&) (this=0x7ffef5ff71b0)
    at /usr/embrace/c++/7/bits/shared_ptr.h:119
#5  0x0000555555854178 in CTxMemPoolEntry::GetSharedTx() const (this=0x7ffee12106a0) at ./txmempool.h:101
#6  0x0000555555854178 in PartiallyDownloadedBlock::InitData(CBlockHeaderAndShortTxIDs const&, std::vector<std::pair<uint256, std::shared_ptr<CTransaction const> >, std::allocator<std::pair<uint256, std::shared_ptr<CTransaction const> > > > const&) ([email protected]=0x7ffef5ff9f30, cmpctblock=..., extra_txn=std::vector of size 100, capability 100 = {...})
    at blockencodings.cpp:114
#7  0x00005555556a2d4a in ProcessMessage(CNode*, std::__cxx11::string const&, CDataStream&, int64_t, CChainParams const&, CConnman*, std::atomic<bool> const&, bool)
    ([email protected]=0x7ffedc0010d0, strCommand="cmpctblock", vRecv=..., nTimeReceived=1593549860206352, chainparams=..., connman=0x7fffbc04ba20, interruptMsgProc=..., enable_bip61=false) at net_processing.cpp:3051
#8  0x00005555556a6f01 in PeerLogicValidation::ProcessMessages(CNode*, std::atomic<bool>&) (this=<optimized out>, pfrom=0x7ffedc0010d0, interruptMsgProc=...) at net_processing.cpp:3629
#9  0x000055555566b19e in CConnman::ThreadMessageHandler() (this=0x7fffbc04ba20) at internet.cpp:1966

Supply hyperlink

Leave a reply