ipkn / crow

Crow is very fast and easy to use C++ micro web framework (inspired by Python Flask)
BSD 3-Clause "New" or "Revised" License
7.47k stars 888 forks source link

Possible memory leak when serve is stopped #316

Open amirnik opened 6 years ago

amirnik commented 6 years ago

Hello,

I modified the example_with_all.cpp as the following:

CROW_ROUTE(app, "/")
    .name("hello")
([&app]{
        app.stop();
    return "Hello World!";
});

I run the application under valgrind: valgrind --leak-check=full CROW I run the application and did: curl localhost:18080/ Now the app has stopped and valgrind shows definitely lost error:

==16538== (2018-08-29 19:33:55) [INFO ] Crow/0.1 server is running at 0.0.0.0:18080 using 8 threads (2018-08-29 19:33:55) [INFO ] Call app.loglevel(crow::LogLevel::Warning) to hide Info level logs. (2018-08-29 19:34:13) [DEBUG ] 0x5ebc660 timer cancelled: 0 0 (2018-08-29 19:34:13) [DEBUG ] timer add inside: 0x72967c0 0 (2018-08-29 19:34:13) [DEBUG ] 0x5ebc660 timer added: 0x72967c0 0 (2018-08-29 19:34:13) [DEBUG ] 0x5ebc660 timer cancelled: 0x72967c0 0 (2018-08-29 19:34:13) [INFO ] Request: 127.0.0.1:42926 0x5ebc660 HTTP/1.1 GET / (2018-08-29 19:34:14) [DEBUG ] Matched rule '/' 1 / 2 (2018-08-29 19:34:14) [INFO ] Response: 0x5ebc660 / 200 0 (2018-08-29 19:34:14) [DEBUG ] 0x5ebc660 timer cancelled: 0 0 (2018-08-29 19:34:14) [INFO ] Exiting. (2018-08-29 19:34:14) [DEBUG ] timer add inside: 0x72967c0 1 (2018-08-29 19:34:14) [DEBUG ] 0x5ebc660 timer added: 0x72967c0 1 ==16538== ==16538== HEAP SUMMARY: ==16538== in use at exit: 13,066 bytes in 29 blocks ==16538== total heap usage: 969 allocs, 940 frees, 154,643 bytes allocated ==16538== ==16538== 4,992 (4,728 direct, 264 indirect) bytes in 1 blocks are definitely lost in loss record 22 of 23 ==16538== at 0x4C29753: operator new(unsigned long) (vg_replace_malloc.c:334) ==16538== by 0x43CE34: crow::Server<crow::Crow<>, crow::SocketAdaptor>::do_accept() (crow_all.h:7729) ==16538== by 0x43CDA4: crow::Server<crow::Crow<>, crow::SocketAdaptor>::do_accept()::{lambda(boost::system::error_code)#1}::operator()(boost::system::error_code) const (crow_all.h:7744) ==16538== by 0x458F91: boost::asio::detail::binder1<crow::Server<crow::Crow<>, crow::SocketAdaptor>::do_accept()::{lambda(boost::system::error_code)#1}, boost::system::error_code>::operator()() (bind_handler.hpp:47) ==16538== by 0x456C99: void boost::asio::asio_handler_invoke<boost::asio::detail::binder1<crow::Server<crow::Crow<>, crow::SocketAdaptor>::do_accept()::{lambda(boost::system::error_code)#1}, boost::system::error_code> >(boost::asio::detail::binder1<crow::Server<crow::Crow<>, crow::SocketAdaptor>::do_accept()::{lambda(boost::system::error_code)#1}, boost::system::error_code>, ...) (handler_invoke_hook.hpp:64) ==16538== by 0x4534D3: void boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::binder1<crow::Server<crow::Crow<>, crow::SocketAdaptor>::do_accept()::{lambda(boost::system::error_code)#1}, boost::system::error_code>, {lambda(boost::system::error_code)#1}>(boost::asio::detail::binder1<crow::Server<crow::Crow<>, crow::SocketAdaptor>::do_accept()::{lambda(boost::system::error_code)#1}, boost::system::error_code>&, {lambda(boost::system::error_code)#1}&) (handler_invoke_helpers.hpp:37) ==16538== by 0x451052: boost::asio::detail::reactive_socket_accept_op<boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service >, boost::asio::ip::tcp, crow::Server<crow::Crow<>, crow::SocketAdaptor>::do_accept()::{lambda(boost::system::error_code)#1}>::do_complete(boost::asio::detail::task_io_service, boost::asio::detail::task_io_service_operation, boost::system::error_code const&, unsigned long) (reactive_socket_accept_op.hpp:123) ==16538== by 0x40BA6B: boost::asio::detail::task_io_service_operation::complete(boost::asio::detail::task_io_service&, boost::system::error_code const&, unsigned long) (task_io_service_operation.hpp:37) ==16538== by 0x40DA38: boost::asio::detail::epoll_reactor::descriptor_state::do_complete(boost::asio::detail::task_io_service, boost::asio::detail::task_io_service_operation, boost::system::error_code const&, unsigned long) (epoll_reactor.ipp:651) ==16538== by 0x40BA6B: boost::asio::detail::task_io_service_operation::complete(boost::asio::detail::task_io_service&, boost::system::error_code const&, unsigned long) (task_io_service_operation.hpp:37) ==16538== by 0x40E5BA: boost::asio::detail::task_io_service::do_run_one(boost::asio::detail::scoped_lock&, boost::asio::detail::task_io_service_thread_info&, boost::system::error_code const&) (task_io_service.ipp:384) ==16538== by 0x40E02E: boost::asio::detail::task_io_service::run(boost::system::error_code&) (task_io_service.ipp:153) ==16538== ==16538== 8,074 (4,728 direct, 3,346 indirect) bytes in 1 blocks are definitely lost in loss record 23 of 23 ==16538== at 0x4C29753: operator new(unsigned long) (vg_replace_malloc.c:334) ==16538== by 0x43CE34: crow::Server<crow::Crow<>, crow::SocketAdaptor>::do_accept() (crow_all.h:7729) ==16538== by 0x433C60: crow::Server<crow::Crow<>, crow::SocketAdaptor>::run() (crow_all.h:7698) ==16538== by 0x42995B: crow::Crow<>::run() (crow_all.h:9756) ==16538== by 0x461EB1: main (example_with_all.cpp:94) ==16538== ==16538== LEAK SUMMARY: ==16538== definitely lost: 9,456 bytes in 2 blocks ==16538== indirectly lost: 3,610 bytes in 27 blocks ==16538== possibly lost: 0 bytes in 0 blocks ==16538== still reachable: 0 bytes in 0 blocks ==16538== suppressed: 0 bytes in 0 blocks ==16538== ==16538== For counts of detected and suppressed errors, rerun with: -v ==16538== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

Is this really a memory leak?

Thanks in Advance for your help. Amir

mrozigor commented 6 years ago

Will try to check this weekend ;)

mrozigor commented 5 years ago

Almost did it in time ;) It looks like one of pointers is only deleted when there is boost error when handling response (http_server.h:191-210). I'll try to fix this.

DmytroBiriukov commented 5 years ago

It seems I've got the same problem, ... pay attention to (http_server.h:193) Here is valgrind results: ==11120== 5,112 bytes in 1 blocks are definitely lost in loss record 2 of 2 ==11120== at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==11120== by 0x17F5FC: crow::Server<crow::Crow<>, crow::SocketAdaptor>::do_accept() (http_server.h:193) ==11120== by 0x17F56C: crow::Server<crow::Crow<>, crow::SocketAdaptor>::do_accept()::{lambda(boost::system::error_code)#1}::operator()(boost::system::error_code) const (http_server.h:211) ==11120== by 0x1B7818: boost::asio::detail::binder1<crow::Server<crow::Crow<>, crow::SocketAdaptor>::do_accept()::{lambda(boost::system::error_code)#1}, boost::system::error_code>::operator()() (bind_handler.hpp:65) ==11120== by 0x1B43A1: void boost::asio::asio_handler_invoke<boost::asio::detail::binder1<crow::Server<crow::Crow<>, crow::SocketAdaptor>::do_accept()::{lambda(boost::system::error_code)#1}, boost::system::error_code> >(boost::asio::detail::binder1<crow::Server<crow::Crow<>, crow::SocketAdaptor>::do_accept()::{lambda(boost::system::error_code)#1}, boost::system::error_code>&, ...) (handler_invoke_hook.hpp:69) ==11120== by 0x1AF0A7: void boost_asio_handler_invoke_helpers::invoke<boost::asio::detail::binder1<crow::Server<crow::Crow<>, crow::SocketAdaptor>::do_accept()::{lambda(boost::system::error_code)#1}, boost::system::error_code>, {lambda(boost::system::error_code)#1}>(boost::asio::detail::binder1<crow::Server<crow::Crow<>, crow::SocketAdaptor>::do_accept()::{lambda(boost::system::error_code)#1}, boost::system::error_code>&, {lambda(boost::system::error_code)#1}&) (handler_invoke_helpers.hpp:37)