Crow icon indicating copy to clipboard operation
Crow copied to clipboard

Suspected Memory Leak: Occurs when a WebSocket remains open on the client side and the server shuts down.

Open Anivice opened this issue 11 months ago • 0 comments

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⏎

Anivice avatar Jan 19 '25 01:01 Anivice