From 5809440f1ace96d140e575307f7d84f44455f452 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Fri, 4 Jan 2013 07:06:54 -0600 Subject: [PATCH] Updates multithreaded non-forked listen methods to not prematurely close the endpoint. references #168 --- src/roles/server.hpp | 64 +++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 24 deletions(-) diff --git a/src/roles/server.hpp b/src/roles/server.hpp index 31e194c19c..439b103d0a 100644 --- a/src/roles/server.hpp +++ b/src/roles/server.hpp @@ -218,21 +218,29 @@ public: // legacy interface void listen(uint16_t port, size_t num_threads = 1) { - start_listen(port,num_threads>1 ? num_threads : 0); - if(num_threads > 1) stop_listen(true); + start_listen(port,num_threads>1 ? num_threads : 0); + if(num_threads > 1) { + stop_listen(true); + } } void listen(const boost::asio::ip::tcp::endpoint& e, size_t num_threads = 1) { - start_listen(e,num_threads>1 ? num_threads : 0); - if(num_threads > 1) stop_listen(true); + start_listen(e,num_threads>1 ? num_threads : 0); + if(num_threads > 1) { + stop_listen(true); + } } void listen(const std::string &host, const std::string &service, size_t num_threads = 1) { - start_listen(host,service,num_threads>1 ? num_threads : 0); - if(num_threads > 1) stop_listen(true); + start_listen(host,service,num_threads>1 ? num_threads : 0); + if(num_threads > 1) { + stop_listen(true); + } } template void listen(const InternetProtocol &internet_protocol, uint16_t port, size_t num_threads = 1) { - start_listen(internet_protocol,port,num_threads>1 ? num_threads : 0); - if(num_threads > 1) stop_listen(true); + start_listen(internet_protocol,port,num_threads>1 ? num_threads : 0); + if(num_threads > 1) { + stop_listen(true); + } } protected: @@ -309,24 +317,32 @@ void server::start_listen(const boost::asio::ip::tcp::endpoint& e,size template void server::stop_listen(bool join) { { - boost::unique_lock lock(m_endpoint.m_lock); - - if (m_state != LISTENING) { - throw exception("stop_listen called from invalid state"); - } - - m_acceptor.close(); - } + boost::unique_lock lock(m_endpoint.m_lock); - if(join) { - for (std::size_t i = 0; i < m_listening_threads.size(); ++i) { - m_listening_threads[i]->join(); - } + if (m_state != LISTENING) { + throw exception("stop_listen called from invalid state"); + } } - - m_listening_threads.clear(); - - m_state = IDLE; + + // If there are multiple threads we should join before stopping. Normally + // this will result in WebSocket++ blocking here waiting for the workers to + if (join) { + for (std::size_t i = 0; i < m_listening_threads.size(); ++i) { + m_listening_threads[i]->join(); + } + + m_listening_threads.clear(); + } + + boost::unique_lock lock(m_endpoint.m_lock); + + if (m_state != LISTENING) { + throw exception("stop_listen called from invalid state"); + } + + // Clean up + m_acceptor.close(); + m_state = IDLE; } template