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.49k stars 890 forks source link

Multiple issues while using with libraries that uses asio #150

Open sivachandran opened 8 years ago

sivachandran commented 8 years ago

I am writing an application that uses libtorrent-rasterbar and crow, both of them uses boost asio. I started by implementing the web APIs using crow and everything worked fine. But the moment I start using libtorrent-rasterbar, crow stopped responding to HTTP requests. Crow's HTTP server listens for client but it simply hangs after accepting the client connection.

After some debugging I found that the io_service that is responsible for handling the client requests terminates(run exits) prematurely. So I introduced work pool to keep the io_service running. After this change crow started handling the http request but only the very first one. Consecutive http requests simply hang. Further debugging revealed that it has to do with the Keep-Alive connections. If I turn off Keep-Alive connection through http header then all http requests are handled.

I added some debug logs and found that the deadline timer is not triggered which is responsible for flushing Keep-Alive connection cache(i.e. Keep-Alive). But even if the cached connection is not timed out the consecutive should've been processed in the same connection but it didn't happen.

All the above mentioned issues occur only if I use libtorrent-rasterbar. I think all these are related to race condition or timing issues. You can reproduce the issue simply by declaring a variable of libtorrent-rasterbar object. The following snippet reproduces the issues always on my Mac using clang++.

#include <crow.h>
#include <libtorrent/session.hpp>

#include <chrono>
#include <thread>

using namespace std;
int main()
{
    libtorrent::session session;
    crow::SimpleApp app;

    CROW_ROUTE(app, "/")([](){
        return "Hello world";
    });

    app.port(18080).run();
    this_thread::sleep_for(chrono::minutes(1000));
    return 0;
}
ipkn commented 8 years ago

I tried this on my ubuntu VM and it serves well. I will test on the mac soon.

0xAT commented 6 years ago

Any update? If you will run these code on Windows, it will crash with access violation.

msvc-14.0 boost-1.65.1

>   test-crow-libtorrent.exe!boost::asio::detail::win_iocp_socket_service_base::do_open(boost::asio::detail::win_iocp_socket_service_base::base_implementation_type & impl, int family, int type, int protocol, boost::system::error_code & ec) Line 307    C++
    test-crow-libtorrent.exe!libtorrent::aux::session_impl::setup_listener(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class boost::asio::ip::tcp const &,int,int,class boost::system::error_code &)    C++
    test-crow-libtorrent.exe!libtorrent::aux::session_impl::open_listen_port(void)  C++
    test-crow-libtorrent.exe!libtorrent::aux::session_impl::init(class boost::shared_ptr<struct libtorrent::settings_pack>) C++
    test-crow-libtorrent.exe!boost::_mfi::mf1<void,struct libtorrent::aux::session_impl,class boost::shared_ptr<struct libtorrent::settings_pack> >::operator()(struct libtorrent::aux::session_impl *,class boost::shared_ptr<struct libtorrent::settings_pack>)   C++
    test-crow-libtorrent.exe!boost::asio::asio_handler_invoke<class boost::_bi::bind_t<void,class boost::_mfi::mf1<void,struct libtorrent::aux::session_impl,class boost::shared_ptr<struct libtorrent::settings_pack> >,class boost::_bi::list2<class boost::_bi::value<struct libtorrent::aux::session_impl *>,class boost::_bi::value<class boost::shared_ptr<struct libtorrent::settings_pack> > > > >(class boost::_bi::bind_t<void,class boost::_mfi::mf1<void,struct libtorrent::aux::session_impl,class boost::shared_ptr<struct libtorrent::settings_pack> >,class boost::_bi::list2<class boost::_bi::value<struct libtorrent::aux::session_impl *>,class boost::_bi::value<class boost::shared_ptr<struct libtorrent::settings_pack> > > > &,...)    C++
    test-crow-libtorrent.exe!boost::asio::detail::completion_handler<class boost::_bi::bind_t<void,class boost::_mfi::mf1<void,struct libtorrent::aux::session_impl,class boost::shared_ptr<struct libtorrent::settings_pack> >,class boost::_bi::list2<class boost::_bi::value<struct libtorrent::aux::session_impl *>,class boost::_bi::value<class boost::shared_ptr<struct libtorrent::settings_pack> > > > >::do_complete(class boost::asio::detail::win_iocp_io_service *,class boost::asio::detail::win_iocp_operation *,class boost::system::error_code const &,unsigned int)   C++
    test-crow-libtorrent.exe!boost::asio::detail::win_iocp_io_service::do_one(bool block, boost::system::error_code & ec) Line 405  C++
    test-crow-libtorrent.exe!boost::asio::detail::win_iocp_io_service::run(boost::system::error_code & ec) Line 164 C++
    test-crow-libtorrent.exe!boost::asio::io_service::run() Line 60 C++
    test-crow-libtorrent.exe!boost::asio::detail::win_thread_function(void * arg) Line 121  C++
    test-crow-libtorrent.exe!thread_start<unsigned int (__stdcall*)(void *)>(void * const parameter) Line 115   C++
    kernel32.dll!@BaseThreadInitThunk@12() Unknown
    ntdll.dll!__RtlUserThreadStart()    Unknown
    ntdll.dll!__RtlUserThreadStart@8() Unknown