drogonframework / drogon

Drogon: A C++14/17/20 based HTTP web application framework running on Linux/macOS/Unix/Windows
MIT License
11.57k stars 1.12k forks source link

Segmentation fault/Bus Error on quit #1382

Closed simoberny closed 2 years ago

simoberny commented 2 years ago

Describe the bug I'm using Drogon in my project and everything works as expected in running status. When I try to quit() and gently close the application, I randomly get Segmentation fault, even Bus error in rare case. I'am using Drogon in a separate thread

To Reproduce In the main thread, I call a thread on startServer() function When on some event I close application and I call stopServer(), I get seg fault. This is not due to the premature exit of application.

  void startServer()
  {
      registerHandlers();

      app().getLoop()->runEvery(std::chrono::seconds(25), [](){
           // Let WD manager know Web server is still alive
            Watchdog::kick();
      });

      app().loadConfigFile("./config/server.json").run();
  }

  void stopServer()
  {
      app().getLoop()->queueInLoop([]() { app().quit(); });
  }

I tried other solutions also following your tests, some seem to improve the situation, but randomly it always returns to the seg fault state.

void startServer()
{
      std::thread thr([&]() {
          app().getLoop()->runEvery(std::chrono::seconds(25), [](){
              Watchdog::kick();
          });

          app().loadConfigFile("./config/server.json").run();
      });

      thr.join();
}

Expected behavior I need Drogon to gently close on command.

Desktop:

Additional context I debugged using Valgrind and obtained the following:

Valgrind log ### ``` ==8034== Thread 8 DrogonIoLoop: ==8034== Invalid read of size 8 ==8034== at 0x6170600: std::_Rb_tree_increment(std::_Rb_tree_node_base const*) (in /usr/lib/libstdc++.so.6.0.28) ==8034== by 0xACFC8F: std::_Rb_tree_const_iterator >::operator++() (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xACBEA3: trantor::TcpServer::stop()::{lambda()#1}::operator()() const (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xACE2E7: void std::__invoke_impl(std::__invoke_other, trantor::TcpServer::stop()::{lambda()#1}&) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xACD8EF: std::enable_if, std::__is_invocable >::value, std::is_void>::type std::__invoke_r(std::__is_invocable&&, (trantor::TcpServer::stop()::{lambda()#1}&)...) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xACCEFF: std::_Function_handler::_M_invoke(std::_Any_data const&) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0x760767: std::function::operator()() const (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xABC933: trantor::EventLoop::doRunInLoopFuncs() (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xABC26B: trantor::EventLoop::loop() (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xABF21B: trantor::EventLoopThread::loopFuncs() (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xABEE3B: trantor::EventLoopThread::EventLoopThread(std::__cxx11::basic_string, std::allocator > const&)::{lambda()#1}::operator()() const (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xABFD0B: void std::__invoke_impl, std::allocator > const&)::{lambda()#1}>(std::__invoke_other, trantor::EventLoopThread::EventLoopThread(std::__cxx11::basic_string, std::allocator > const&)::{lambda()#1}&&) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== Address 0x677c7c8 is 24 bytes inside a block of size 48 free'd ==8034== at 0x484EBD0: operator delete(void*, unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so) ==8034== by 0xAD41B7: __gnu_cxx::new_allocator > >::deallocate(std::_Rb_tree_node >*, unsigned long) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xAD371B: std::allocator_traits > > >::deallocate(std::allocator > >&, std::_Rb_tree_node >*, unsigned long) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xAD26A7: std::_Rb_tree, std::shared_ptr, std::_Identity >, std::less >, std::allocator > >::_M_put_node(std::_Rb_tree_node >*) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xAD1223: std::_Rb_tree, std::shared_ptr, std::_Identity >, std::less >, std::allocator > >::_M_drop_node(std::_Rb_tree_node >*) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xAD34CF: std::_Rb_tree, std::shared_ptr, std::_Identity >, std::less >, std::allocator > >::_M_erase_aux(std::_Rb_tree_const_iterator >) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xAD2563: std::_Rb_tree, std::shared_ptr, std::_Identity >, std::less >, std::allocator > >::_M_erase_aux(std::_Rb_tree_const_iterator >, std::_Rb_tree_const_iterator >) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xAD0F73: std::_Rb_tree, std::shared_ptr, std::_Identity >, std::less >, std::allocator > >::erase(std::shared_ptr const&) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xACFE03: std::set, std::less >, std::allocator > >::erase(std::shared_ptr const&) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xACC203: trantor::TcpServer::handleCloseInLoop(std::shared_ptr const&) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xACC437: trantor::TcpServer::connectionClosed(std::shared_ptr const&) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xAD5977: void std::__invoke_impl const&), trantor::TcpServer*&, std::shared_ptr const&>(std::__invoke_memfun_deref, void (trantor::TcpServer::*&)(std::shared_ptr const&), trantor::TcpServer*&, std::shared_ptr const&) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== Block was alloc'd at ==8034== at 0x484D8B8: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-arm64-linux.so) ==8034== by 0xAD59DB: __gnu_cxx::new_allocator > >::allocate(unsigned long, void const*) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xAD50B3: std::allocator_traits > > >::allocate(std::allocator > >&, unsigned long) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xAD479F: std::_Rb_tree, std::shared_ptr, std::_Identity >, std::less >, std::allocator > >::_M_get_node() (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xAD3D0F: std::_Rb_tree_node >* std::_Rb_tree, std::shared_ptr, std::_Identity >, std::less >, std::allocator > >::_M_create_node >(std::shared_ptr&&) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xAD3147: std::_Rb_tree_node >* std::_Rb_tree, std::shared_ptr, std::_Identity >, std::less >, std::allocator > >::_Alloc_node::operator() >(std::shared_ptr&&) const (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xAD1FDF: std::_Rb_tree_iterator > std::_Rb_tree, std::shared_ptr, std::_Identity >, std::less >, std::allocator > >::_M_insert_, std::_Rb_tree, std::shared_ptr, std::_Identity >, std::less >, std::allocator > >::_Alloc_node>(std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::shared_ptr&&, std::_Rb_tree, std::shared_ptr, std::_Identity >, std::less >, std::allocator > >::_Alloc_node&) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xAD0B2F: std::pair >, bool> std::_Rb_tree, std::shared_ptr, std::_Identity >, std::less >, std::allocator > >::_M_insert_unique >(std::shared_ptr&&) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xACFA9F: std::set, std::less >, std::allocator > >::insert(std::shared_ptr&&) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xACBA1F: trantor::TcpServer::newConnection(int, trantor::InetAddress const&) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xAD5597: void std::__invoke_impl(std::__invoke_memfun_deref, void (trantor::TcpServer::*&)(int, trantor::InetAddress const&), trantor::TcpServer*&, int&&, trantor::InetAddress const&) (in /home/root/workspace/TunnelLighting/ATIone) ==8034== by 0xAD4DB7: std::__invoke_result::type std::__invoke(void (trantor::TcpServer::*&)(int, trantor::InetAddress const&), trantor::TcpServer*&, int&&, trantor::InetAddress const&) (in /home/root/workspace/TunnelLighting/ATIone) ```
an-tao commented 2 years ago

There's a recent patch (https://github.com/an-tao/trantor/pull/225?w=1) which seems to be related to your problem, please try using the latest version of drogon.

simoberny commented 2 years ago

Yes, it works. I think I missed that patch for a few hours. Thank you!