Crow
Crow copied to clipboard
Suspected Memory Leak: Occurs when a WebSocket remains open on the client side and the server shuts down.
Description
This issue arises whenever a client opens a WebSocket and does not close it before the server shuts down.
Version used
Crow release version v1.2.0
https://github.com/CrowCpp/Crow/releases/tag/v1.2.0
How to reproduce
Can be easily reproduced using the following code:
#include <chrono>
#include <crow.h>
#include <thread>
int main()
{
crow::SimpleApp app;
// Define a route that streams data
CROW_WEBSOCKET_ROUTE(app, "/ws")
.onopen([&](crow::websocket::connection &conn) {
CROW_LOG_INFO << "new websocket connection from " << conn.get_remote_ip();
})
.onclose([&](crow::websocket::connection &conn, const std::string &reason) {
CROW_LOG_INFO << "websocket connection closed: " << reason;
})
.onmessage([&](crow::websocket::connection &conn, const std::string &data, bool is_binary)
{
CROW_LOG_INFO << "Recv message:" << data;
if (is_binary)
conn.send_binary(data);
else
conn.send_text(data);
});
auto worker = [&]() {
app.port(18080).run(); // Run the server on port 18080
};
std::thread worker_thread(worker);
std::this_thread::sleep_for(std::chrono::seconds(5));
app.stop();
if (worker_thread.joinable()) {
worker_thread.join();
}
}
Memory Sanitizer Report
=================================================================
==1010203==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 4544 byte(s) in 1 object(s) allocated from:
#0 0x7fd8758c33b8 in operator new(unsigned long) (/lib64/libasan.so.8+0xc33b8) (BuildId: 0505b45e5a5d9a6c8ecb1d529aaaf13cd21fbe4e)
#1 0x55812b2447c7 in crow::WebSocketRule<crow::Crow<> >::handle_upgrade(crow::request const&, crow::response&, crow::SocketAdaptor&&) /home/anivice/Source/Sysdarft/src/include/crow/routing.h:465
#2 0x55812af588ac in void crow::Router::handle_upgrade<crow::SocketAdaptor&>(crow::request const&, crow::response&, crow::SocketAdaptor&) (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x48a8ac) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#3 0x55812af2920d in void crow::Crow<>::handle_upgrade<crow::SocketAdaptor>(crow::request const&, crow::response&, crow::SocketAdaptor&&) (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x45b20d) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#4 0x55812af11808 in crow::Connection<crow::SocketAdaptor, crow::Crow<>>::handle() /home/anivice/Source/Sysdarft/src/include/crow/http_connection.h:174
#5 0x55812aef87b3 in crow::HTTPParser<crow::Connection<crow::SocketAdaptor, crow::Crow<>> >::process_message() /home/anivice/Source/Sysdarft/src/include/crow/parser.h:162
#6 0x55812aeddc54 in crow::HTTPParser<crow::Connection<crow::SocketAdaptor, crow::Crow<>> >::on_message_complete(crow::http_parser*) (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x40fc54) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#7 0x55812acf19a7 in crow::http_parser_execute(crow::http_parser*, crow::http_parser_settings const*, char const*, unsigned long) /home/anivice/Source/Sysdarft/src/include/crow/http_parser_merged.h:1661
#8 0x55812aec2211 in crow::HTTPParser<crow::Connection<crow::SocketAdaptor, crow::Crow<>> >::feed(char const*, int) (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x3f4211) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#9 0x55812aea4788 in crow::Connection<crow::SocketAdaptor, crow::Crow<>>::do_read()::{lambda(std::error_code const&, unsigned long)#1}::operator()(std::error_code const&, unsigned long) const /home/anivice/Source/Sysdarft/src/include/crow/http_connection.h:492
#10 0x55812af86770 in asio::detail::binder2<crow::Connection<crow::SocketAdaptor, crow::Crow<>>::do_read()::{lambda(std::error_code const&, unsigned long)#1}, std::error_code, unsigned long>::operator()() (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x4b8770) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#11 0x55812af7c1d1 in void asio::detail::handler_work<crow::Connection<crow::SocketAdaptor, crow::Crow<>>::do_read()::{lambda(std::error_code const&, unsigned long)#1}, asio::any_io_executor, void>::complete<asio::detail::binder2<crow::Connection<crow::SocketAdaptor, crow::Crow<>>::do_read()::{lambda(std::error_code const&, unsigned long)#1}, std::error_code, unsigned long> >(asio::detail::binder2<crow::Connection<crow::SocketAdaptor, crow::Crow<>>::do_read()::{lambda(std::error_code const&, unsigned long)#1}, std::error_code, unsigned long>&, crow::Connection<crow::SocketAdaptor, crow::Crow<>>::do_read()::{lambda(std::error_code const&, unsigned long)#1}&) (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x4ae1d1) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#12 0x55812af70b0d in asio::detail::reactive_socket_recv_op<asio::mutable_buffers_1, crow::Connection<crow::SocketAdaptor, crow::Crow<>>::do_read()::{lambda(std::error_code const&, unsigned long)#1}, asio::any_io_executor>::do_complete(void*, asio::detail::scheduler_operation*, std::error_code const&, unsigned long) (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x4a2b0d) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#13 0x55812ad069ab in asio::detail::scheduler_operation::complete(void*, std::error_code const&, unsigned long) (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x2389ab) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#14 0x55812ad33067 in asio::detail::scheduler::do_run_one(asio::detail::conditionally_enabled_mutex::scoped_lock&, asio::detail::scheduler_thread_info&, std::error_code const&) (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x265067) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#15 0x55812ad2eedb in asio::detail::scheduler::run(std::error_code&) (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x260edb) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#16 0x55812ad36156 in asio::io_context::run() (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x268156) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#17 0x55812ae1e817 in crow::Server<crow::Crow<>, crow::SocketAdaptor>::run()::{lambda()#1}::operator()() const (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x350817) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#18 0x55812afa640d in void std::__invoke_impl<void, crow::Server<crow::Crow<>, crow::SocketAdaptor>::run()::{lambda()#1}>(std::__invoke_other, crow::Server<crow::Crow<>, crow::SocketAdaptor>::run()::{lambda()#1}&&) /usr/include/c++/14/bits/invoke.h:61
#19 0x55812afa4823 in std::__invoke_result<crow::Server<crow::Crow<>, crow::SocketAdaptor>::run()::{lambda()#1}>::type std::__invoke<crow::Server<crow::Crow<>, crow::SocketAdaptor>::run()::{lambda()#1}>(crow::Server<crow::Crow<>, crow::SocketAdaptor>::run()::{lambda()#1}&&) /usr/include/c++/14/bits/invoke.h:96
#20 0x55812afa2f40 in void std::thread::_Invoker<std::tuple<crow::Server<crow::Crow<>, crow::SocketAdaptor>::run()::{lambda()#1}> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/include/c++/14/bits/std_thread.h:301
#21 0x55812af9fd3e in std::thread::_Invoker<std::tuple<crow::Server<crow::Crow<>, crow::SocketAdaptor>::run()::{lambda()#1}> >::operator()() /usr/include/c++/14/bits/std_thread.h:308
#22 0x55812af9c43c in std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::thread::_Invoker<std::tuple<crow::Server<crow::Crow<>, crow::SocketAdaptor>::run()::{lambda()#1}> >, void>::operator()() const /usr/include/c++/14/future:1439
#23 0x55812af94eff in std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter> std::__invoke_impl<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::thread::_Invoker<std::tuple<crow::Server<crow::Crow<>, crow::SocketAdaptor>::run()::{lambda()#1}> >, void>&>(std::__invoke_other, std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::thread::_Invoker<std::tuple<crow::Server<crow::Crow<>, crow::SocketAdaptor>::run()::{lambda()#1}> >, void>&) /usr/include/c++/14/bits/invoke.h:61
#24 0x55812af88b4a in std::enable_if<is_invocable_r_v<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::thread::_Invoker<std::tuple<crow::Server<crow::Crow<>, crow::SocketAdaptor>::run()::{lambda()#1}> >, void>&>, std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> >::type std::__invoke_r<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::thread::_Invoker<std::tuple<crow::Server<crow::Crow<>, crow::SocketAdaptor>::run()::{lambda()#1}> >, void>&>(std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::thread::_Invoker<std::tuple<crow::Server<crow::Crow<>, crow::SocketAdaptor>::run()::{lambda()#1}> >, void>&) (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x4bab4a) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#25 0x55812af7fad8 in std::_Function_handler<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> (), std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::thread::_Invoker<std::tuple<crow::Server<crow::Crow<>, crow::SocketAdaptor>::run()::{lambda()#1}> >, void> >::_M_invoke(std::_Any_data const&) /usr/include/c++/14/bits/std_function.h:291
#26 0x55812adbdacd in std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>::operator()() const (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x2efacd) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#27 0x55812ad6196c in std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*) (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x29396c) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#28 0x55812ae2b432 in void std::__invoke_impl<void, void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::__invoke_memfun_deref, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/14/bits/invoke.h:74
#29 0x55812adeaec4 in std::__invoke_result<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>::type std::__invoke<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/include/c++/14/bits/invoke.h:96
Indirect leak of 128 byte(s) in 1 object(s) allocated from:
#0 0x7fd8758c33b8 in operator new(unsigned long) (/lib64/libasan.so.8+0xc33b8) (BuildId: 0505b45e5a5d9a6c8ecb1d529aaaf13cd21fbe4e)
#1 0x55812ab69df1 in std::__new_allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::allocate(unsigned long, void const*) /usr/include/c++/14/bits/new_allocator.h:151
#2 0x55812ab30851 in std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::allocate(unsigned long) /usr/include/c++/14/bits/allocator.h:196
#3 0x55812ab30851 in std::allocator_traits<std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::allocate(std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, unsigned long) /usr/include/c++/14/bits/alloc_traits.h:515
#4 0x55812ab30851 in std::_Vector_base<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> > > >::_M_allocate(unsigned long) /usr/include/c++/14/bits/stl_vector.h:380
#5 0x55812ab348fc in void 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> > > >::_M_realloc_append<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++/14/bits/vector.tcc:596
#6 0x55812b253718 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >& 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> > > >::emplace_back<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++/14/bits/vector.tcc:123
#7 0x55812b2517da in crow::websocket::Connection<crow::SocketAdaptor, crow::Crow<> >::start(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&) /home/anivice/Source/Sysdarft/src/include/crow/websocket.h:281
#8 0x55812b24bd3e in crow::websocket::Connection<crow::SocketAdaptor, crow::Crow<> >::Connection(crow::request const&, crow::SocketAdaptor&&, crow::Crow<>*, unsigned long, std::function<void (crow::websocket::connection&)>, std::function<void (crow::websocket::connection&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool)>, std::function<void (crow::websocket::connection&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, std::function<void (crow::websocket::connection&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)>, std::function<bool (crow::request const&, void**)>) /home/anivice/Source/Sysdarft/src/include/crow/websocket.h:132
#9 0x55812b245161 in crow::WebSocketRule<crow::Crow<> >::handle_upgrade(crow::request const&, crow::response&, crow::SocketAdaptor&&) /home/anivice/Source/Sysdarft/src/include/crow/routing.h:465
#10 0x55812af588ac in void crow::Router::handle_upgrade<crow::SocketAdaptor&>(crow::request const&, crow::response&, crow::SocketAdaptor&) (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x48a8ac) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#11 0x55812af2920d in void crow::Crow<>::handle_upgrade<crow::SocketAdaptor>(crow::request const&, crow::response&, crow::SocketAdaptor&&) (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x45b20d) (BuildId: 428bac8d658cfc693366d36e3a8411ff280025d0)
#12 0x55812af11808 in crow::Connection<crow::SocketAdaptor, crow::Crow<>>::handle() /home/anivice/Source/Sysdarft/src/include/crow/http_connection.h:174
#13 0x55812aef87b3 in crow::HTTPParser<crow::Connection<crow::SocketAdaptor, crow::Crow<>> >::process_message() /home/anivice/Source/Sysdarft/src/include/crow/parser.h:162
#14 0x55812aeddc54 in crow::HTTPParser<crow::Connection<crow::SocketAdaptor, crow::Crow<>> >::on_message_complete(crow::http_parser*) (/home/anivice/Source/Sysdarft/cmake-build-debug/sysdarft-system+0x40fc54) (BuildId: 428bac8d658cfc693366d36e3a8411ff2⏎