elements icon indicating copy to clipboard operation
elements copied to clipboard

Segfault on Alpine 3.18.5

Open grubles opened this issue 1 year ago • 9 comments

OS: Alpine 3.18.5 Arch: x86_64 Elements version: v23.2.1

When testing a PeerSwap swap (patched with https://github.com/ElementsProject/peerswap/pull/257) , elementsd segfaults.

The segfault seems to occur when PeerSwap tries to create the initial swap open transaction.

gdb backtrace here:

0x0000555555a89360 in BlindTransaction (input_value_blinding_factors=...,                                                                                                              
    input_asset_blinding_factors=..., input_assets=..., input_amounts=...,                                                                                                             
    out_val_blind_factors=..., out_asset_blind_factors=..., output_pubkeys=...,                                                                                                        
    issuance_blinding_privkey=..., token_blinding_privkey=..., tx=...,                                                                                                                 
    auxiliary_generators=0x0) at blind.cpp:287                                            
287     {                                                                                                                                                                              
(gdb) backtrace                                                                                                                                                                        #0  0x0000555555a89360 in BlindTransaction (input_value_blinding_factors=..., input_asset_blinding_factors=..., input_assets=..., input_amounts=..., out_val_blind_factors=..., 
    out_asset_blind_factors=..., output_pubkeys=..., issuance_blinding_privkey=..., token_blinding_privkey=..., tx=..., auxiliary_generators=0x0) at blind.cpp:287
#1  0x0000555555a11b98 in wallet::CreateTransactionInternal (wallet=..., vecSend=..., tx=..., nFeeRet=@0x7ffff56e9e18: 0, nChangePosInOut=@0x7ffff56e9e14: 1, error=..., 
    coin_control=..., fee_calc_out=..., sign=<optimized out>, blind_details=<optimized out>, issuance_details=<optimized out>) at wallet/spend.cpp:1444
#2  0x0000555555a1428b in wallet::CreateTransaction (wallet=..., vecSend=..., tx=..., nFeeRet=@0x7ffff56e9e18: 0, nChangePosInOut=@0x7ffff56e9e14: 1, error=..., coin_control=..., 
    fee_calc_out=..., sign=false, blind_details=0x7fff9330eb50, issuance_details=0x0) at wallet/spend.cpp:1759
#3  0x0000555555a15453 in wallet::FundTransaction (wallet=..., tx=..., nFeeRet=@0x7ffff56e9e18: 0, nChangePosInOut=@0x7ffff56e9e14: 1, error=..., 
    lockUnspents=lockUnspents@entry=false, setSubtractFeeFromOutputs=..., coinControl=...) at wallet/spend.cpp:1823
#4  0x0000555555c29220 in wallet::FundTransaction (wallet=..., tx=..., fee_out=@0x7ffff56e9e18: 0, change_position=@0x7ffff56e9e14: 1, options=..., coinControl=..., 
    solving_data=..., override_min_fee=<optimized out>) at wallet/rpc/spend.cpp:711
#5  0x0000555555c2e37f in operator() (request=..., self=..., __closure=<optimized out>) at /usr/include/c++/12.2.1/bits/shared_ptr_base.h:1665
#6  0x0000555555c2e8b4 in std::__invoke_impl<UniValue, wallet::fundrawtransaction()::<lambda(const RPCHelpMan&, const JSONRPCRequest&)>&, const RPCHelpMan&, const JSONRPCRequest&> (
    __f=...) at /usr/include/c++/12.2.1/bits/invoke.h:60
#7  std::__invoke_r<UniValue, wallet::fundrawtransaction()::<lambda(const RPCHelpMan&, const JSONRPCRequest&)>&, const RPCHelpMan&, const JSONRPCRequest&> (__fn=...)
    at /usr/include/c++/12.2.1/bits/invoke.h:116
#8  std::_Function_handler<UniValue(const RPCHelpMan&, const JSONRPCRequest&), wallet::fundrawtransaction()::<lambda(const RPCHelpMan&, const JSONRPCRequest&)> >::_M_invoke(const std:
:_Any_data &, const RPCHelpMan &, const JSONRPCRequest &) (__functor=..., __args#0=..., __args#1=...) at /usr/include/c++/12.2.1/bits/std_function.h:291
#9  0x0000555555b2c3af in std::function<UniValue (RPCHelpMan const&, JSONRPCRequest const&)>::operator()(RPCHelpMan const&, JSONRPCRequest const&) const (__args#1=..., __args#0=..., 
    this=0x7ffff56ea590) at /usr/include/c++/12.2.1/bits/std_function.h:591
#10 RPCHelpMan::HandleRequest (this=this@entry=0x7ffff56ea570, request=...) at rpc/util.cpp:599
#11 0x00005555557c368a in CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, U
niValue&, bool)#1}::operator()(JSONRPCRequest const&, UniValue&, bool) const (request=..., result=..., __closure=<optimized out>) at ./rpc/server.h:109
#12 0x00005555559aa5a3 in std::function<bool (JSONRPCRequest const&, UniValue&, bool)>::operator()(JSONRPCRequest const&, UniValue&, bool) const (__args#2=<optimized out>, 
    __args#1=..., __args#0=..., this=<optimized out>) at /usr/include/c++/12.2.1/bits/std_function.h:591
#13 operator() (__closure=0x7ffff7990d80, request=..., result=..., last_handler=<optimized out>) at wallet/interfaces.cpp:543
#14 0x0000555555735029 in std::function<bool (JSONRPCRequest const&, UniValue&, bool)>::operator()(JSONRPCRequest const&, UniValue&, bool) const (__args#2=<optimized out>, 
    __args#1=..., __args#0=..., this=<optimized out>) at /usr/include/c++/12.2.1/bits/std_function.h:591
#15 operator() (__closure=<optimized out>, last_handler=true, result=..., request=...) at node/interfaces.cpp:421
#16 std::__invoke_impl<bool, node::(anonymous namespace)::RpcHandlerImpl::RpcHandlerImpl(const CRPCCommand&)::<lambda(const JSONRPCRequest&, UniValue&, bool)>&, const JSONRPCRequest&,
 UniValue&, bool> (__f=...) at /usr/include/c++/12.2.1/bits/invoke.h:61
#17 std::__invoke_r<bool, node::(anonymous namespace)::RpcHandlerImpl::RpcHandlerImpl(const CRPCCommand&)::<lambda(const JSONRPCRequest&, UniValue&, bool)>&, const JSONRPCRequest&, Un
iValue&, bool> (__fn=...) at /usr/include/c++/12.2.1/bits/invoke.h:114
#18 std::_Function_handler<bool(const JSONRPCRequest&, UniValue&, bool), node::(anonymous namespace)::RpcHandlerImpl::RpcHandlerImpl(const CRPCCommand&)::<lambda(const JSONRPCRequest&
, UniValue&, bool)> >::_M_invoke(const std::_Any_data &, const JSONRPCRequest &, UniValue &, bool &&) (__functor=..., __args#0=..., __args#1=..., __args#2=<optimized out>)
    at /usr/include/c++/12.2.1/bits/std_function.h:290
#19 0x000055555587bddc in std::function<bool (JSONRPCRequest const&, UniValue&, bool)>::operator()(JSONRPCRequest const&, UniValue&, bool) const (__args#2=<optimized out>, 
    __args#1=..., __args#0=..., this=0x7ffff7990e18) at /usr/include/c++/12.2.1/bits/std_function.h:591
#20 ExecuteCommand (command=..., request=..., result=..., last_handler=<optimized out>) at rpc/server.cpp:478
#21 0x000055555587c31c in ExecuteCommands (result=..., request=..., commands=...) at rpc/server.cpp:444
#22 CRPCTable::execute (this=0x555556058e60 <tableRPC>, request=...) at rpc/server.cpp:464
#23 0x000055555595a7f0 in HTTPReq_JSONRPC (context=..., req=<optimized out>) at httprpc.cpp:202
#24 0x0000555555968cfd in std::function<bool (HTTPRequest*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>::operator()(HTTPRequest*, std::__c
xx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const (__args#1=..., __args#0=<optimized out>, this=0x7fff92ab4880)
#25 HTTPWorkItem::operator() (this=0x7fff92ab4850) at httpserver.cpp:54
#26 WorkQueue<HTTPClosure>::Run (this=this@entry=0x7ffff57558c0) at httpserver.cpp:112
#27 0x0000555555963f11 in HTTPWorkQueueRun (queue=0x7ffff57558c0, worker_num=<optimized out>) at httpserver.cpp:344
#28 0x00007ffff7aed1e3 in ?? () from /usr/lib/libstdc++.so.6
#29 0x00007ffff7fb9bc2 in ?? () from /lib/ld-musl-x86_64.so.1
#30 0x0000000000000000 in ?? ()

grubles avatar Dec 03 '23 16:12 grubles

Can confirm elementsd 22.1.1 segfaults at the same point as well.

grubles avatar Dec 03 '23 21:12 grubles

Here is a backtrace using 22.1.1 built with --enable-debug:

Thread 16 "b-httpworker.1" received signal SIGSEGV, Segmentation fault.                                                                                                                [Switching to LWP 27449]                                                                                                                                                               
0x0000555555ae12c0 in BlindTransaction (input_value_blinding_factors=..., 
    input_asset_blinding_factors=..., input_assets=..., input_amounts=...,                                                                                                             
    out_val_blind_factors=..., out_asset_blind_factors=..., output_pubkeys=...,                                                                                                        
    issuance_blinding_privkey=..., token_blinding_privkey=..., tx=...,                                                                                                                 
    auxiliary_generators=0x0) at blind.cpp:287                                                                                                                                         
287     {                                                                                  
(gdb) backtrace                                                                                                                                                                        
#0  0x0000555555ae12c0 in BlindTransaction (input_value_blinding_factors=..., input_asset_blinding_factors=..., input_assets=..., input_amounts=..., out_val_blind_factors=...,            out_asset_blind_factors=..., output_pubkeys=..., issuance_blinding_privkey=..., token_blinding_privkey=..., tx=..., auxiliary_generators=0x0) at blind.cpp:287
#1  0x0000555555a7382c in CWallet::CreateTransactionInternal (this=this@entry=0x7ffff5743570, vecSend=..., tx=..., nFeeRet=@0x7ffff56d8eb8: 140735612360454, 
    nChangePosInOut=@0x7ffff56d8eb4: 0, error=..., coin_control=..., fee_calc_out=..., sign=<optimized out>, blind_details=<optimized out>, issuance_details=<optimized out>)
    at wallet/spend.cpp:1361
#2  0x0000555555a7513b in CWallet::CreateTransaction (this=this@entry=0x7ffff5743570, vecSend=..., tx=..., nFeeRet=@0x7ffff56d8eb8: 140735612360454, 
    nChangePosInOut=@0x7ffff56d8eb4: 0, error=..., coin_control=..., fee_calc_out=..., sign=false, blind_details=0x7ffff524a7f0, issuance_details=0x0) at wallet/spend.cpp:1670
#3  0x0000555555a76303 in CWallet::FundTransaction (this=this@entry=0x7ffff5743570, tx=..., nFeeRet=@0x7ffff56d8eb8: 140735612360454, nChangePosInOut=@0x7ffff56d8eb4: 0, error=..., 
    lockUnspents=lockUnspents@entry=false, setSubtractFeeFromOutputs=..., coinControl=...) at wallet/spend.cpp:1735
#4  0x0000555555a2a779 in FundTransaction (wallet=..., tx=..., fee_out=@0x7ffff56d8eb8: 140735612360454, change_position=@0x7ffff56d8eb4: 0, options=..., coinControl=..., 
    solving_data=..., override_min_fee=<optimized out>) at wallet/rpcwallet.cpp:3515
#5  0x0000555555a2f7d2 in operator() (request=..., self=..., __closure=<optimized out>) at wallet/rpcwallet.cpp:3631
#6  0x0000555555a2fc84 in std::__invoke_impl<UniValue, fundrawtransaction()::<lambda(const RPCHelpMan&, const JSONRPCRequest&)>&, const RPCHelpMan&, const JSONRPCRequest&> (__f=...)
    at /usr/include/c++/12.2.1/bits/invoke.h:60
#7  std::__invoke_r<UniValue, fundrawtransaction()::<lambda(const RPCHelpMan&, const JSONRPCRequest&)>&, const RPCHelpMan&, const JSONRPCRequest&> (__fn=...)
    at /usr/include/c++/12.2.1/bits/invoke.h:116
#8  std::_Function_handler<UniValue(const RPCHelpMan&, const JSONRPCRequest&), fundrawtransaction()::<lambda(const RPCHelpMan&, const JSONRPCRequest&)> >::_M_invoke(const std::_Any_da
ta &, const RPCHelpMan &, const JSONRPCRequest &) (__functor=..., __args#0=..., __args#1=...) at /usr/include/c++/12.2.1/bits/std_function.h:291
#9  0x0000555555b7e05f in std::function<UniValue (RPCHelpMan const&, JSONRPCRequest const&)>::operator()(RPCHelpMan const&, JSONRPCRequest const&) const (__args#1=..., __args#0=..., 
    this=0x7ffff56d95a0) at /usr/include/c++/12.2.1/bits/std_function.h:591
#10 RPCHelpMan::HandleRequest (this=this@entry=0x7ffff56d9580, request=...) at rpc/util.cpp:588
#11 0x00005555557a2c7a in CRPCCommand::CRPCCommand(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, RPCHelpMan (*)())::{lambda(JSONRPCRequest const&, U
niValue&, bool)#1}::operator()(JSONRPCRequest const&, UniValue&, bool) const (request=..., result=..., __closure=<optimized out>) at ./rpc/server.h:110
#12 0x00005555559814b3 in std::function<bool (JSONRPCRequest const&, UniValue&, bool)>::operator()(JSONRPCRequest const&, UniValue&, bool) const (__args#2=<optimized out>, 
    __args#1=..., __args#0=..., this=<optimized out>) at /usr/include/c++/12.2.1/bits/std_function.h:591
#13 operator() (__closure=0x7ffff7972990, request=..., result=..., last_handler=<optimized out>) at wallet/interfaces.cpp:530
#14 0x000055555571c7b9 in std::function<bool (JSONRPCRequest const&, UniValue&, bool)>::operator()(JSONRPCRequest const&, UniValue&, bool) const (__args#2=<optimized out>, 
    __args#1=..., __args#0=..., this=<optimized out>) at /usr/include/c++/12.2.1/bits/std_function.h:591
#15 operator() (__closure=<optimized out>, last_handler=true, result=..., request=...) at node/interfaces.cpp:397
#16 std::__invoke_impl<bool, node::(anonymous namespace)::RpcHandlerImpl::RpcHandlerImpl(const CRPCCommand&)::<lambda(const JSONRPCRequest&, UniValue&, bool)>&, const JSONRPCRequest&,
 UniValue&, bool> (__f=...) at /usr/include/c++/12.2.1/bits/invoke.h:61
#17 std::__invoke_r<bool, node::(anonymous namespace)::RpcHandlerImpl::RpcHandlerImpl(const CRPCCommand&)::<lambda(const JSONRPCRequest&, UniValue&, bool)>&, const JSONRPCRequest&, Un
iValue&, bool> (__fn=...) at /usr/include/c++/12.2.1/bits/invoke.h:114
#18 std::_Function_handler<bool(const JSONRPCRequest&, UniValue&, bool), node::(anonymous namespace)::RpcHandlerImpl::RpcHandlerImpl(const CRPCCommand&)::<lambda(const JSONRPCRequest&, UniValue&, bool)> >::_M_invoke(const std::_Any_data &, const JSONRPCRequest &, UniValue &, bool &&) (__functor=..., __args#0=..., __args#1=..., __args#2=<optimized out>)
    at /usr/include/c++/12.2.1/bits/std_function.h:290
#19 0x0000555555856f2c in std::function<bool (JSONRPCRequest const&, UniValue&, bool)>::operator()(JSONRPCRequest const&, UniValue&, bool) const (__args#2=<optimized out>, 
    __args#1=..., __args#0=..., this=0x7ffff7972a28) at /usr/include/c++/12.2.1/bits/std_function.h:591
#20 ExecuteCommand (command=..., request=..., result=..., last_handler=<optimized out>) at rpc/server.cpp:478
#21 0x000055555585746c in ExecuteCommands (result=..., request=..., commands=...) at rpc/server.cpp:444
#22 CRPCTable::execute (this=0x555555fe5aa0 <tableRPC>, request=...) at rpc/server.cpp:464
#23 0x000055555592f2de in HTTPReq_JSONRPC (context=..., req=<optimized out>) at httprpc.cpp:202
#24 0x000055555593dced in std::function<bool (HTTPRequest*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>::operator()(HTTPRequest*, std::__c--Type <RET> for more, q to quit, c to continue without paging--
xx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const (__args#1=..., __args#0=<optimized out>, this=0x7fff92bab630)
    at /usr/include/c++/12.2.1/bits/std_function.h:591
#25 HTTPWorkItem::operator() (this=0x7fff92bab600) at httpserver.cpp:49
#26 WorkQueue<HTTPClosure>::Run (this=this@entry=0x7ffff573c060) at httpserver.cpp:107
#27 0x0000555555938eb7 in HTTPWorkQueueRun (queue=0x7ffff573c060, worker_num=<optimized out>) at httpserver.cpp:337
#28 0x00007ffff7aed1e3 in ?? () from /usr/lib/libstdc++.so.6
#29 0x00007ffff7fb9bc2 in ?? () from /lib/ld-musl-x86_64.so.1
#30 0x0000000000000000 in ?? ()

grubles avatar Dec 03 '23 22:12 grubles

Does this also happen with 0.21 ?

When did testing with Alpine/musl begin (has it ever worked?)

Just trying to figure out if it's a new or existing issue.

Will dig into it and try reproduce.

delta1 avatar Dec 04 '23 11:12 delta1

I can't seem to build 0.21 on Alpine 3.18 so not sure there. I just started testing unfortunately.

grubles avatar Dec 04 '23 12:12 grubles

Managed to compile, and ran the functional test suite. There are about 100 different functional tests failing, so presumably Elements has never worked completely on Alpine Linux.

I will work on figuring out what is causing these issues.

delta1 avatar Dec 04 '23 12:12 delta1

my current suspicion is the Alpine Linux thread stack size, which is much lower than gnu/linux: https://serverfault.com/a/1123054

https://ariadne.space/2021/06/25/understanding-thread-stack-sizes-and-how-alpine-is-different/

delta1 avatar Dec 06 '23 16:12 delta1

Looks like we could maybe try to detect if using Alpine/musl and adjust the LDFLAGS when building?

grubles avatar Dec 06 '23 17:12 grubles

yeah that sounds like it might work, i’m busy trying the docker env var above.

delta1 avatar Dec 06 '23 17:12 delta1

I compiled with LDFLAGS="-Wl,-z,stack-size=1024768" and elementsd did not crash when attempting a swap.

grubles avatar Dec 06 '23 18:12 grubles