drogon icon indicating copy to clipboard operation
drogon copied to clipboard

drogon_ctl press: possible double free in multithreaded mode if destination unreachable

Open viachaslavic opened this issue 4 years ago • 6 comments

To Reproduce

drogon_ctl press -n 10000 -c 100 -t 4 -q "http://${unreachable_domain_or_IP}"
Output with backtrace
Too many errors
Too many errors
Too many errors
Too many errors
=================================================================
==77435==ERROR: AddressSanitizer: attempting double-free on 0x619000001980 in thread T3 (EventLoopThread):
    #0 0x7f996cde6f19 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:127
    #1 0x7f996c317552 in __run_exit_handlers (/usr/lib/libc.so.6+0x3f552)
    #2 0x7f996c31764d in exit (/usr/lib/libc.so.6+0x3f64d)
    #3 0x55a4e878ea5c in outputErrorAndExit(std::basic_string_view<char, std::char_traits<char> > const&) /usr/src/my_project/drogon/drogon_ctl/press.cc:43
    #4 0x55a4e87909b1 in operator() /usr/src/my_project/drogon/drogon_ctl/press.cc:255
    #5 0x55a4e8792815 in __invoke_impl<void, drogon_ctl::press::sendRequest(const HttpClientPtr&)::<lambda(drogon::ReqResult, const HttpResponsePtr&)>&, drogon::ReqResult, const std::shared_ptr<drogon::HttpResponse>&> /usr/include/c++/11.1.0/bits/invoke.h:61
    #6 0x55a4e8792497 in __invoke_r<void, drogon_ctl::press::sendRequest(const HttpClientPtr&)::<lambda(drogon::ReqResult, const HttpResponsePtr&)>&, drogon::ReqResult, const std::shared_ptr<drogon::HttpResponse>&> /usr/include/c++/11.1.0/bits/invoke.h:111
    #7 0x55a4e8791fe0 in _M_invoke /usr/include/c++/11.1.0/bits/std_function.h:291
    #8 0x55a4e885b428 in std::function<void (drogon::ReqResult, std::shared_ptr<drogon::HttpResponse> const&)>::operator()(drogon::ReqResult, std::shared_ptr<drogon::HttpResponse> const&) const (/home/user/.local/bin/drogon_ctl+0x22d428)
    #9 0x55a4e8849aad in operator() /usr/src/my_project/drogon/lib/src/HttpClientImpl.cc:348
    #10 0x55a4e8854bbd in __invoke_impl<void, drogon::HttpClientImpl::sendRequestInLoop(const HttpRequestPtr&, drogon::HttpReqCallback&&)::<lambda(drogon::ReqResult, const HttpResponsePtr&)>&, drogon::ReqResult, const std::shared_ptr<drogon::HttpResponse>&> /usr/include/c++/11.1.0/bits/invoke.h:61
    #11 0x55a4e8853e07 in __invoke_r<void, drogon::HttpClientImpl::sendRequestInLoop(const HttpRequestPtr&, drogon::HttpReqCallback&&)::<lambda(drogon::ReqResult, const HttpResponsePtr&)>&, drogon::ReqResult, const std::shared_ptr<drogon::HttpResponse>&> /usr/include/c++/11.1.0/bits/invoke.h:111
    #12 0x55a4e885222a in _M_invoke /usr/include/c++/11.1.0/bits/std_function.h:291
    #13 0x55a4e885b428 in std::function<void (drogon::ReqResult, std::shared_ptr<drogon::HttpResponse> const&)>::operator()(drogon::ReqResult, std::shared_ptr<drogon::HttpResponse> const&) const (/home/user/.local/bin/drogon_ctl+0x22d428)
    #14 0x55a4e884e4ed in drogon::HttpClientImpl::onError(drogon::ReqResult) /usr/src/my_project/drogon/lib/src/HttpClientImpl.cc:618
    #15 0x55a4e884440a in operator() /usr/src/my_project/drogon/lib/src/HttpClientImpl.cc:99
    #16 0x55a4e8852eeb in __invoke_impl<void, drogon::HttpClientImpl::createTcpClient()::<lambda()>&> /usr/include/c++/11.1.0/bits/invoke.h:61
    #17 0x55a4e885105f in __invoke_r<void, drogon::HttpClientImpl::createTcpClient()::<lambda()>&> /usr/include/c++/11.1.0/bits/invoke.h:111
    #18 0x55a4e884fdb8 in _M_invoke /usr/include/c++/11.1.0/bits/std_function.h:291
    #19 0x55a4e88bcd05 in std::function<void ()>::operator()() const /usr/include/c++/11.1.0/bits/std_function.h:560
    #20 0x55a4e8a4d549 in operator() /usr/src/my_project/drogon/trantor/trantor/net/TcpClient.cc:71
    #21 0x55a4e8a5203f in __invoke_impl<void, trantor::TcpClient::TcpClient(trantor::EventLoop*, const trantor::InetAddress&, const string&)::<lambda()>&> /usr/include/c++/11.1.0/bits/invoke.h:61
    #22 0x55a4e8a51736 in __invoke_r<void, trantor::TcpClient::TcpClient(trantor::EventLoop*, const trantor::InetAddress&, const string&)::<lambda()>&> /usr/include/c++/11.1.0/bits/invoke.h:154
    #23 0x55a4e8a510c1 in _M_invoke /usr/include/c++/11.1.0/bits/std_function.h:291
    #24 0x55a4e88bcd05 in std::function<void ()>::operator()() const /usr/include/c++/11.1.0/bits/std_function.h:560
    #25 0x55a4e8a76613 in trantor::Connector::handleError() /usr/src/my_project/drogon/trantor/trantor/net/inner/Connector.cc:232
    #26 0x55a4e8a79f0f in void std::__invoke_impl<void, void (trantor::Connector::*&)(), std::shared_ptr<trantor::Connector>&>(std::__invoke_memfun_deref, void (trantor::Connector::*&)(), std::shared_ptr<trantor::Connector>&) /usr/include/c++/11.1.0/bits/invoke.h:74
    #27 0x55a4e8a79dba in std::__invoke_result<void (trantor::Connector::*&)(), std::shared_ptr<trantor::Connector>&>::type std::__invoke<void (trantor::Connector::*&)(), std::shared_ptr<trantor::Connector>&>(void (trantor::Connector::*&)(), std::shared_ptr<trantor::Connector>&) /usr/include/c++/11.1.0/bits/invoke.h:96
    #28 0x55a4e8a79cf1 in void std::_Bind<void (trantor::Connector::*(std::shared_ptr<trantor::Connector>))()>::__call<void, , 0ul>(std::tuple<>&&, std::_Index_tuple<0ul>) /usr/include/c++/11.1.0/functional:420
    #29 0x55a4e8a79bb0 in void std::_Bind<void (trantor::Connector::*(std::shared_ptr<trantor::Connector>))()>::operator()<, void>() (/home/user/.local/bin/drogon_ctl+0x44bbb0)
    #30 0x55a4e8a797f9 in void std::__invoke_impl<void, std::_Bind<void (trantor::Connector::*(std::shared_ptr<trantor::Connector>))()>&>(std::__invoke_other, std::_Bind<void (trantor::Connector::*(std::shared_ptr<trantor::Connector>))()>&) /usr/include/c++/11.1.0/bits/invoke.h:61
    #31 0x55a4e8a795a4 in std::enable_if<std::__and_<std::is_void<void>, std::__is_invocable<std::_Bind<void (trantor::Connector::*(std::shared_ptr<trantor::Connector>))()>&> >::value, void>::type std::__invoke_r<void, std::_Bind<void (trantor::Connector::*(std::shared_ptr<trantor::Connector>))()>&>(std::_Bind<void (trantor::Connector::*(std::shared_ptr<trantor::Connector>))()>&) /usr/include/c++/11.1.0/bits/invoke.h:154
    #32 0x55a4e8a7900c in std::_Function_handler<void (), std::_Bind<void (trantor::Connector::*(std::shared_ptr<trantor::Connector>))()> >::_M_invoke(std::_Any_data const&) (/home/user/.local/bin/drogon_ctl+0x44b00c)
    #33 0x55a4e88bcd05 in std::function<void ()>::operator()() const /usr/include/c++/11.1.0/bits/std_function.h:560
    #34 0x55a4e8a715af in trantor::Channel::handleEventSafely() /usr/src/my_project/drogon/trantor/trantor/net/Channel.cc:80
    #35 0x55a4e8a71490 in trantor::Channel::handleEvent() /usr/src/my_project/drogon/trantor/trantor/net/Channel.cc:66
    #36 0x55a4e8a3e41a in trantor::EventLoop::loop() /usr/src/my_project/drogon/trantor/trantor/net/EventLoop.cc:190
    #37 0x55a4e8a451d6 in trantor::EventLoopThread::loopFuncs() /usr/src/my_project/drogon/trantor/trantor/net/EventLoopThread.cc:60
    #38 0x55a4e8a449b5 in operator() /usr/src/my_project/drogon/trantor/trantor/net/EventLoopThread.cc:25
    #39 0x55a4e8a4652f in __invoke_impl<void, trantor::EventLoopThread::EventLoopThread(const string&)::<lambda()> > /usr/include/c++/11.1.0/bits/invoke.h:61
    #40 0x55a4e8a464e4 in __invoke<trantor::EventLoopThread::EventLoopThread(const string&)::<lambda()> > /usr/include/c++/11.1.0/bits/invoke.h:96
    #41 0x55a4e8a46491 in _M_invoke<0> /usr/include/c++/11.1.0/bits/std_thread.h:253
    #42 0x55a4e8a46465 in operator() /usr/include/c++/11.1.0/bits/std_thread.h:260
    #43 0x55a4e8a46449 in _M_run /usr/include/c++/11.1.0/bits/std_thread.h:211
    #44 0x7f996c6e33c3 in execute_native_thread_routine /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:82
    #45 0x7f996c979258 in start_thread (/usr/lib/libpthread.so.0+0x9258)
    #46 0x7f996c3d65e2 in __GI___clone (/usr/lib/libc.so.6+0xfe5e2)

0x619000001980 is located 0 bytes inside of 1040-byte region [0x619000001980,0x619000001d90)
freed by thread T2 (EventLoopThread) here:
    #0 0x7f996cde6f19 in __interceptor_free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:127
    #1 0x7f996c317552 in __run_exit_handlers (/usr/lib/libc.so.6+0x3f552)

previously allocated by thread T0 here:
    #0 0x7f996cde7459 in __interceptor_calloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:154
    #1 0x7f996c317831 in __new_exitfn (/usr/lib/libc.so.6+0x3f831)

Thread T3 (EventLoopThread) created by T0 here:
    #0 0x7f996cd88fa7 in __interceptor_pthread_create /build/gcc/src/gcc/libsanitizer/asan/asan_interceptors.cpp:216
    #1 0x7f996c6e36aa in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:663
    #2 0x55a4e8a44b4f in trantor::EventLoopThread::EventLoopThread(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/src/my_project/drogon/trantor/trantor/net/EventLoopThread.cc:25
    #3 0x55a4e8a4b23a in void __gnu_cxx::new_allocator<trantor::EventLoopThread>::construct<trantor::EventLoopThread, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(trantor::EventLoopThread*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/include/c++/11.1.0/ext/new_allocator.h:156
    #4 0x55a4e8a4afb0 in void std::allocator_traits<std::allocator<trantor::EventLoopThread> >::construct<trantor::EventLoopThread, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::allocator<trantor::EventLoopThread>&, trantor::EventLoopThread*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/include/c++/11.1.0/bits/alloc_traits.h:512
    #5 0x55a4e8a4aa5d in std::_Sp_counted_ptr_inplace<trantor::EventLoopThread, std::allocator<trantor::EventLoopThread>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::allocator<trantor::EventLoopThread>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/include/c++/11.1.0/bits/shared_ptr_base.h:519
    #6 0x55a4e8a4a238 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<trantor::EventLoopThread, std::allocator<trantor::EventLoopThread>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(trantor::EventLoopThread*&, std::_Sp_alloc_shared_tag<std::allocator<trantor::EventLoopThread> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/include/c++/11.1.0/bits/shared_ptr_base.h:650
    #7 0x55a4e8a49ce5 in std::__shared_ptr<trantor::EventLoopThread, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<trantor::EventLoopThread>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::_Sp_alloc_shared_tag<std::allocator<trantor::EventLoopThread> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/include/c++/11.1.0/bits/shared_ptr_base.h:1337
    #8 0x55a4e8a49a48 in std::shared_ptr<trantor::EventLoopThread>::shared_ptr<std::allocator<trantor::EventLoopThread>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::_Sp_alloc_shared_tag<std::allocator<trantor::EventLoopThread> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/include/c++/11.1.0/bits/shared_ptr.h:409
    #9 0x55a4e8a490b5 in std::shared_ptr<trantor::EventLoopThread> std::allocate_shared<trantor::EventLoopThread, std::allocator<trantor::EventLoopThread>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::allocator<trantor::EventLoopThread> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/include/c++/11.1.0/bits/shared_ptr.h:861
    #10 0x55a4e8a48b41 in std::shared_ptr<trantor::EventLoopThread> std::make_shared<trantor::EventLoopThread, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/include/c++/11.1.0/bits/shared_ptr.h:877
    #11 0x55a4e8a48435 in trantor::EventLoopThreadPool::EventLoopThreadPool(unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/src/my_project/drogon/trantor/trantor/net/EventLoopThreadPool.cc:23
    #12 0x55a4e8794f75 in std::_MakeUniq<trantor::EventLoopThreadPool>::__single_object std::make_unique<trantor::EventLoopThreadPool, unsigned long&>(unsigned long&) (/home/user/.local/bin/drogon_ctl+0x166f75)
    #13 0x55a4e8790268 in drogon_ctl::press::createRequestAndClients() /usr/src/my_project/drogon/drogon_ctl/press.cc:213
    #14 0x55a4e878feda in drogon_ctl::press::doTesting() /usr/src/my_project/drogon/drogon_ctl/press.cc:198
    #15 0x55a4e878f94c in drogon_ctl::press::handleCommand(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&) /usr/src/my_project/drogon/drogon_ctl/press.cc:193
    #16 0x55a4e86e5287 in exeCommand(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&) /usr/src/my_project/drogon/drogon_ctl/cmd.cc:43
    #17 0x55a4e878d62e in main /usr/src/my_project/drogon/drogon_ctl/main.cc:46
    #18 0x7f996c2ffb24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)

Thread T2 (EventLoopThread) created by T0 here:
    #0 0x7f996cd88fa7 in __interceptor_pthread_create /build/gcc/src/gcc/libsanitizer/asan/asan_interceptors.cpp:216
    #1 0x7f996c6e36aa in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:663
    #2 0x55a4e8a44b4f in trantor::EventLoopThread::EventLoopThread(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/src/my_project/drogon/trantor/trantor/net/EventLoopThread.cc:25
    #3 0x55a4e8a4b23a in void __gnu_cxx::new_allocator<trantor::EventLoopThread>::construct<trantor::EventLoopThread, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(trantor::EventLoopThread*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/include/c++/11.1.0/ext/new_allocator.h:156
    #4 0x55a4e8a4afb0 in void std::allocator_traits<std::allocator<trantor::EventLoopThread> >::construct<trantor::EventLoopThread, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::allocator<trantor::EventLoopThread>&, trantor::EventLoopThread*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/include/c++/11.1.0/bits/alloc_traits.h:512
    #5 0x55a4e8a4aa5d in std::_Sp_counted_ptr_inplace<trantor::EventLoopThread, std::allocator<trantor::EventLoopThread>, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::allocator<trantor::EventLoopThread>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/include/c++/11.1.0/bits/shared_ptr_base.h:519
    #6 0x55a4e8a4a238 in std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<trantor::EventLoopThread, std::allocator<trantor::EventLoopThread>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(trantor::EventLoopThread*&, std::_Sp_alloc_shared_tag<std::allocator<trantor::EventLoopThread> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/include/c++/11.1.0/bits/shared_ptr_base.h:650
    #7 0x55a4e8a49ce5 in std::__shared_ptr<trantor::EventLoopThread, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<trantor::EventLoopThread>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::_Sp_alloc_shared_tag<std::allocator<trantor::EventLoopThread> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/include/c++/11.1.0/bits/shared_ptr_base.h:1337
    #8 0x55a4e8a49a48 in std::shared_ptr<trantor::EventLoopThread>::shared_ptr<std::allocator<trantor::EventLoopThread>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::_Sp_alloc_shared_tag<std::allocator<trantor::EventLoopThread> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/include/c++/11.1.0/bits/shared_ptr.h:409
    #9 0x55a4e8a490b5 in std::shared_ptr<trantor::EventLoopThread> std::allocate_shared<trantor::EventLoopThread, std::allocator<trantor::EventLoopThread>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::allocator<trantor::EventLoopThread> const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/include/c++/11.1.0/bits/shared_ptr.h:861
    #10 0x55a4e8a48b41 in std::shared_ptr<trantor::EventLoopThread> std::make_shared<trantor::EventLoopThread, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/include/c++/11.1.0/bits/shared_ptr.h:877
    #11 0x55a4e8a48435 in trantor::EventLoopThreadPool::EventLoopThreadPool(unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /usr/src/my_project/drogon/trantor/trantor/net/EventLoopThreadPool.cc:23
    #12 0x55a4e8794f75 in std::_MakeUniq<trantor::EventLoopThreadPool>::__single_object std::make_unique<trantor::EventLoopThreadPool, unsigned long&>(unsigned long&) (/home/user/.local/bin/drogon_ctl+0x166f75)
    #13 0x55a4e8790268 in drogon_ctl::press::createRequestAndClients() /usr/src/my_project/drogon/drogon_ctl/press.cc:213
    #14 0x55a4e878feda in drogon_ctl::press::doTesting() /usr/src/my_project/drogon/drogon_ctl/press.cc:198
    #15 0x55a4e878f94c in drogon_ctl::press::handleCommand(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&) /usr/src/my_project/drogon/drogon_ctl/press.cc:193
    #16 0x55a4e86e5287 in exeCommand(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&) /usr/src/my_project/drogon/drogon_ctl/cmd.cc:43
    #17 0x55a4e878d62e in main /usr/src/my_project/drogon/drogon_ctl/main.cc:46
    #18 0x7f996c2ffb24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)

SUMMARY: AddressSanitizer: double-free /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cpp:127 in __interceptor_free
==77435==ABORTING

Expected behavior Correct program termination with error description.

Desktop (please complete the following information):

  • OS: ArchLinux
  • amd64 quad core laptop
~$ drogon_ctl -v
     _                             
  __| |_ __ ___   __ _  ___  _ __  
 / _` | '__/ _ \ / _` |/ _ \| '_ \ 
| (_| | | | (_) | (_| | (_) | | | |
 \__,_|_|  \___/ \__, |\___/|_| |_|
                 |___/             

A utility for drogon
Version: 1.7.2
Git commit: 3fd9d88dc0e44186f09c08c1e490ddb05ed54eae
Compilation: 
  Compiler: /usr/bin/c++
  Compiler ID: GNU
  Compilation flags: -g -fno-omit-frame-pointer -fsanitize=leak -fsanitize=address -std=c++17 -I/usr/include -I/home/user/.local/include
Libraries: 
  postgresql: no  (batch mode: no)
  mariadb: no
  sqlite3: no
  openssl: yes
  brotli: yes
  boost: no
  hiredis: no
  c-ares: yes

Additional context P.S. Too many errors - not very speaking error. I got it even with a single request, when server instance was started explicitly on an IPv6 address, but the destination for drogon_ctl is set to localhost. When using curl this request passed.

viachaslavic avatar Sep 29 '21 20:09 viachaslavic

Thanks for reporting the issue. We be looking into it.

Note for myself:

It's weird that although ASan and valgrind does see the error can thus report it. The crash doesn't trigger whenever I ran it in GDB.

marty1885 avatar Sep 30 '21 00:09 marty1885

My understanding is that the issue is a consequence of incorrect error handling in the definition of

void NormalResolver::resolve(const std::string &hostname, const Callback &callback)

in the trantor library. Specifically, lines 65-74 in file trantor/net/inner/NormalResolver.cc

if (error == -1 || res == nullptr) { LOG_SYSERR << "InetAddress::resolve"; if (res != nullptr) { freeaddrinfo(res); } callback(InetAddress{}); return; }

look problematic to me, as error code error signals a problem for non-zero values, not only for -1. Specifically, on my computer (Ubuntu 20.04.3 LTS) an invalid URL produces error==-2 and a nonzero pointer res (which doesn't actually point to properly allocated stuff), leading to a problematic invocation of freeaddrinfo(res) in line 90 (relevant documentation).

Replacement of those lines with

if (error != 0) { LOG_SYSERR << "InetAddress::resolve"; callback(InetAddress{}); return; }

fixed the problem for me.

bgornik avatar Dec 01 '21 16:12 bgornik

My understanding is that the issue is a consequence of incorrect error handling in the definition of

void NormalResolver::resolve(const std::string &hostname, const Callback &callback)

in the trantor library. Specifically, lines 65-74 in file trantor/net/inner/NormalResolver.cc

if (error == -1 || res == nullptr) { LOG_SYSERR << "InetAddress::resolve"; if (res != nullptr) { freeaddrinfo(res); } callback(InetAddress{}); return; }

look problematic to me, as error code error signals a problem for non-zero values, not only for -1. Specifically, on my computer (Ubuntu 20.04.3 LTS) an invalid URL produces error==-2 and a nonzero pointer res (which doesn't actually point to properly allocated stuff), leading to a problematic invocation of freeaddrinfo(res) in line 90 (relevant documentation).

Replacement of those lines with

if (error != 0) { LOG_SYSERR << "InetAddress::resolve"; callback(InetAddress{}); return; }

fixed the problem for me.

Thanks so much for your feedback, I made a PR for this

an-tao avatar Dec 02 '21 01:12 an-tao

Good fix. But it does not solve the described problem

dg_ctl_asan.log dg_ctl_valgrind.log

P.S. Maybe these are false positives, but then I would like to get a more detailed description of the error. Maybe through the counter with error enum.

viachaslavic avatar Dec 07 '21 20:12 viachaslavic

Good fix. But it does not solve the described problem

dg_ctl_asan.log dg_ctl_valgrind.log

Looked into this, seems the problem is the fact that exit gets called from different threads which is not OK since exit is not thread-safe as stated in official documentation.

I introduced a mutex in file drogon/drogon_ctl/press.cc

std::mutex exit_mutex;

and inserted

std::lock_guard<std::mutex> lock(exit_mutex);

before the existing two lines in void outputErrorAndExit(const string_view &err) and the problem was fixed.

As I am not very familiar with the entire philosophy and construction of this project, I don't want to suggest this is the most elegant way of going about it.

P.S. [...] then I would like to get a more detailed description of the error. Maybe through the counter with error enum.

I don't understand this. If you mean enumeration and explanation of the variable error it is found in the official documentation for getaddrinfo. If you mean something else, please clarify.

And another thing. Execution of

drogon_ctl press http://127.0.0.1:808090

produces yet another error, namely, a std::bad_function_call error. This is a consequence of the following bug: in file drogon/lib/src/HttpClientImpl.cc in line 351 the function wrapper callback is gutted by having its contents moved, not copied/cloned into the capture of a certain lambda function, so, later on, the call to callback in line 425 raises the std::bad_function_call exception.

Changing the line 351

callback = std::move(callback)](ReqResult result,

to

callback](ReqResult result,

fixes this problem. Again, if copying is too time consuming, other solutions are possible, but someone with more understanding of this project should suggest them.

bgornik avatar Dec 08 '21 13:12 bgornik

@bgornik , thanks for the detailed answer !

I introduced a mutex in file drogon/drogon_ctl/press.cc

As it seems , in this case synchronization will not hurt

I don't understand this. If you mean enumeration and explanation of the variable error it is found in the official documentation for getaddrinfo. If you mean something else, please clarify.

I meant possible internat errors at various levels for the "drogon_ctl press" module with statistics output. This can be thought of as a FR.

viachaslavic avatar Dec 08 '21 14:12 viachaslavic