drogonframework / drogon

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

HttpAppFrameworkImpl destructor crash on application exit #1286

Open tripleslash opened 2 years ago

tripleslash commented 2 years ago

I'm getting a crash on application exit on Visual Studio 2022 compiler because drogon::HttpAppFrameworkImpl destructor is not properly cleaning up objects. It is using something that relies on EventLoop after it was already destroyed when the destructors of static objects got invoked.

The minimal reconstructible example that I could make is this:

int main(int argc, char* argv[])
{
    drogon::app().run();
} // <- crash happens here

Here is the call stack right before the crash happens:

image

If i step over this line I get:

image

backend-api.exe!trantor::EventLoop::isInLoopThread() Line 107 (c:\dev\backend\build\_deps\drogon-src\trantor\trantor\net\EventLoop.h:107)
backend-api.exe!trantor::EventLoop::assertInLoopThread() Line 80 (c:\dev\backend\build\_deps\drogon-src\trantor\trantor\net\EventLoop.h:80)
backend-api.exe!trantor::TimingWheel::~TimingWheel() Line 68 (c:\dev\backend\build\_deps\drogon-src\trantor\trantor\utils\TimingWheel.cc:68)
backend-api.exe!trantor::TimingWheel::`scalar deleting destructor'(unsigned int) (Unknown Source:0)
backend-api.exe!std::_Destroy_in_place<trantor::TimingWheel>(trantor::TimingWheel & _Obj) Line 300 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\xmemory:300)
backend-api.exe!std::_Ref_count_obj2<trantor::TimingWheel>::_Destroy() Line 2033 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\memory:2033)
backend-api.exe!std::_Ref_count_base::_Decref() Line 1106 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\memory:1106)
backend-api.exe!std::_Ptr_base<trantor::TimingWheel>::_Decref() Line 1332 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\memory:1332)
backend-api.exe!std::shared_ptr<trantor::TimingWheel>::~shared_ptr<trantor::TimingWheel>() Line 1615 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\memory:1615)
backend-api.exe!std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>::~pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>() (Unknown Source:0)
backend-api.exe!std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>::`scalar deleting destructor'(unsigned int) (Unknown Source:0)
backend-api.exe!std::_Default_allocator_traits<std::allocator<std::_Tree_node<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>,void *>>>::destroy<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>>(std::allocator<std::_Tree_node<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>,void *>> & __formal, std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>> * const _Ptr) Line 691 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\xmemory:691)
backend-api.exe!std::_Tree_node<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>,void *>::_Freenode<std::allocator<std::_Tree_node<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>,void *>>>(std::allocator<std::_Tree_node<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>,void *>> & _Al, std::_Tree_node<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>,void *> * _Ptr) Line 381 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\xtree:381)
backend-api.exe!std::_Tree_val<std::_Tree_simple_types<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>>>::_Erase_tree<std::allocator<std::_Tree_node<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>,void *>>>(std::allocator<std::_Tree_node<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>,void *>> & _Al, std::_Tree_node<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>,void *> * _Rootnode) Line 746 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\xtree:746)
backend-api.exe!std::_Tree_val<std::_Tree_simple_types<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>>>::_Erase_head<std::allocator<std::_Tree_node<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>,void *>>>(std::allocator<std::_Tree_node<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>,void *>> & _Al) Line 753 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\xtree:753)
backend-api.exe!std::_Tree<std::_Tmap_traits<trantor::EventLoop *,std::shared_ptr<trantor::TimingWheel>,std::less<trantor::EventLoop *>,std::allocator<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>>,0>>::~_Tree<std::_Tmap_traits<trantor::EventLoop *,std::shared_ptr<trantor::TimingWheel>,std::less<trantor::EventLoop *>,std::allocator<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>>,0>>() Line 1085 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\xtree:1085)
backend-api.exe!std::map<trantor::EventLoop *,std::shared_ptr<trantor::TimingWheel>,std::less<trantor::EventLoop *>,std::allocator<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>>>::~map<trantor::EventLoop *,std::shared_ptr<trantor::TimingWheel>,std::less<trantor::EventLoop *>,std::allocator<std::pair<trantor::EventLoop * const,std::shared_ptr<trantor::TimingWheel>>>>() (Unknown Source:0)
backend-api.exe!trantor::TcpServer::~TcpServer() Line 46 (c:\dev\backend\build\_deps\drogon-src\trantor\trantor\net\TcpServer.cc:46)
backend-api.exe!drogon::HttpServer::~HttpServer() Line 180 (c:\dev\backend\build\_deps\drogon-src\lib\src\HttpServer.cc:180)
backend-api.exe!drogon::HttpServer::`scalar deleting destructor'(unsigned int) (Unknown Source:0)
backend-api.exe!std::_Destroy_in_place<drogon::HttpServer>(drogon::HttpServer & _Obj) Line 300 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\xmemory:300)
backend-api.exe!std::_Ref_count_obj2<drogon::HttpServer>::_Destroy() Line 2033 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\memory:2033)
backend-api.exe!std::_Ref_count_base::_Decref() Line 1106 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\memory:1106)
backend-api.exe!std::_Ptr_base<drogon::HttpServer>::_Decref() Line 1332 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\memory:1332)
backend-api.exe!std::shared_ptr<drogon::HttpServer>::~shared_ptr<drogon::HttpServer>() Line 1615 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\memory:1615)
backend-api.exe!std::shared_ptr<drogon::HttpServer>::`scalar deleting destructor'(unsigned int) (Unknown Source:0)
backend-api.exe!std::destroy_at<std::shared_ptr<drogon::HttpServer>>(std::shared_ptr<drogon::HttpServer> * const _Location) Line 313 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\xmemory:313)
backend-api.exe!std::_Default_allocator_traits<std::allocator<std::shared_ptr<drogon::HttpServer>>>::destroy<std::shared_ptr<drogon::HttpServer>>(std::allocator<std::shared_ptr<drogon::HttpServer>> & __formal, std::shared_ptr<drogon::HttpServer> * const _Ptr) Line 691 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\xmemory:691)
backend-api.exe!std::_Destroy_range<std::allocator<std::shared_ptr<drogon::HttpServer>>>(std::shared_ptr<drogon::HttpServer> * _First, std::shared_ptr<drogon::HttpServer> * const _Last, std::allocator<std::shared_ptr<drogon::HttpServer>> & _Al) Line 941 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\xmemory:941)
backend-api.exe!std::vector<std::shared_ptr<drogon::HttpServer>,std::allocator<std::shared_ptr<drogon::HttpServer>>>::_Tidy() Line 1621 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\vector:1621)
backend-api.exe!std::vector<std::shared_ptr<drogon::HttpServer>,std::allocator<std::shared_ptr<drogon::HttpServer>>>::~vector<std::shared_ptr<drogon::HttpServer>,std::allocator<std::shared_ptr<drogon::HttpServer>>>() Line 595 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\vector:595)
backend-api.exe!drogon::ListenerManager::~ListenerManager() Line 58 (c:\dev\backend\build\_deps\drogon-src\lib\src\ListenerManager.h:58)
backend-api.exe!drogon::ListenerManager::`scalar deleting destructor'(unsigned int) (Unknown Source:0)
backend-api.exe!std::default_delete<drogon::ListenerManager>::operator()(drogon::ListenerManager * _Ptr) Line 3125 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\memory:3125)
backend-api.exe!std::unique_ptr<drogon::ListenerManager,std::default_delete<drogon::ListenerManager>>::~unique_ptr<drogon::ListenerManager,std::default_delete<drogon::ListenerManager>>() Line 3235 (c:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.31.31103\include\memory:3235)
backend-api.exe!drogon::HttpAppFrameworkImpl::~HttpAppFrameworkImpl() Line 205 (c:\dev\backend\build\_deps\drogon-src\lib\src\HttpAppFrameworkImpl.cc:205)
backend-api.exe!`drogon::HttpAppFrameworkImpl::instance'::`2'::`dynamic atexit destructor for 'instance''() (Unknown Source:0)
ucrtbased.dll!00007ffd2b364957() (Unknown Source:0)
ucrtbased.dll!00007ffd2b364365() (Unknown Source:0)
ucrtbased.dll!00007ffd2b36449a() (Unknown Source:0)
ucrtbased.dll!00007ffd2b364b01() (Unknown Source:0)
ucrtbased.dll!00007ffd2b363cd1() (Unknown Source:0)
ucrtbased.dll!00007ffd2b363b7d() (Unknown Source:0)
ucrtbased.dll!00007ffd2b363bea() (Unknown Source:0)
ucrtbased.dll!00007ffd2b363e64() (Unknown Source:0)
ucrtbased.dll!00007ffd2b3641f6() (Unknown Source:0)
backend-api.exe!__scrt_common_main_seh() Line 297 (d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:297)
backend-api.exe!__scrt_common_main() Line 331 (d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:331)
backend-api.exe!mainCRTStartup(void * __formal) Line 17 (d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp:17)
kernel32.dll!00007ffd4cfd6fd4() (Unknown Source:0)
ntdll.dll!00007ffd4d5bcec1() (Unknown Source:0)
an-tao commented 2 years ago

Did you use the latest commit of the master branch?

tripleslash commented 2 years ago

I've used v1.7.5 Release bundle

An Tao @.***> schrieb am Do., 16. Juni 2022, 03:56:

Did you use the latest commit of the master branch?

— Reply to this email directly, view it on GitHub https://github.com/drogonframework/drogon/issues/1286#issuecomment-1157146204, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABATEP63SIZBZEJ7RRPC46LVPKCS5ANCNFSM5Y5DBCBA . You are receiving this because you authored the thread.Message ID: @.***>

an-tao commented 2 years ago

We made some patches to fix the crash on exit, please use the last commit or wait for the 1.7.6 release.

tripleslash commented 2 years ago

I've just tried it with the latest master and the crash is gone but the shutdown issue is not:

On Windows the Ctrl+C interrupt is not handled by drogon. It just eats up the Ctrl+C signal and continues to run. And if I try to manually call drogon::app().quit() from somewhere then drogon will hang in a spinlock in Event Loop and never return from the run method. Is this a known problem?

This is where it hangs:

image

an-tao commented 2 years ago

Did you call "app().run()" in another thread than the main thread?

tripleslash commented 2 years ago

No I did not. I've only called it once directly from main. The minimal reproducible example above still applies to this bug. I am using MSVC 2022 and todays drogon master.

An Tao @.***> schrieb am Fr., 17. Juni 2022, 03:43:

Did you call "app().run()" in another thread than the main thread?

— Reply to this email directly, view it on GitHub https://github.com/drogonframework/drogon/issues/1286#issuecomment-1158383222, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABATEPYCMC6MUD6B63JIXFLVPPJ3HANCNFSM5Y5DBCBA . You are receiving this because you authored the thread.Message ID: @.***>

an-tao commented 2 years ago

Where did you call the app().quit() method? Would you please make a complete minimal example to reproduce this problem?

timomrs commented 2 years ago

Just a though, could this be related to my issue https://github.com/drogonframework/drogon/issues/1157 ?

tripleslash commented 2 years ago

The following code causes the issue:

int main(int argc, char* argv[])
{
    drogon::app()
        .registerBeginningAdvice([]
        {
            drogon::app().quit();
        })
        .run();

    // Never reached...
    return 0;
}