Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
Anivice opened this issue Jan 19, 2025 · 0 comments

Comments

@Anivice
Copy link

Anivice commented Jan 19, 2025

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⏎
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant