-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
I have a application that allows creating and removing new servers at runtime.
To do this I have a wrapper class that contains a instance of
websocketpp::server<websocketpp::config::asio>
In the constructor I initialize the server instance using this code:
_server.init_asio(&service);
auto os = Logger::GetOutputStream();
_log_out = os;
_server.get_alog().set_ostream(_log_out.get());
_server.get_elog().set_ostream(_log_out.get());
_server.set_message_handler(boost::bind(&ws_on_message, this, ::_1, ::_2));
_server.set_close_handler(boost::bind(&ws_on_close, this, ::_1));
_server.set_open_handler(boost::bind(&ws_on_open, this, ::_1));
_server.set_http_handler(boost::bind(&ws_on_http, this, ::_1));
...
_server.set_reuse_addr(reuse_addr);
_server.listen(config_port);
_server.start_accept();
Inside my destructor I stop listening and iterate over all connections calling close on them.
Afterwards I call stop on the server
_server.stop_listening();
{
std::unique_lock<std::mutex> lck(_connections_mutex);
for (auto& c : _connections)
{
_server.close(c.first, websocketpp::close::status::going_away, "Server shutdown");
}
}
_server.stop();
However I have a problem.
Some time later when the server tries to write anything to the log it crashes while locking the mutex in logger/basic.hpp
void write(level channel, std::string const & msg) {
scoped_lock_type lock(m_lock); // <= here
if (!this->dynamic_test(channel)) { return; }
*m_out << "[" << timestamp << "] "
<< "[" << names::channel_name(channel) << "] "
<< msg << "\n";
m_out->flush();
}
I suppose that some operations are still running in the asio pool which try to access the already closed log file.
Is this the correct way to shutdown the server ?
How can I force the server to wait for all its asynchronous tasks to exit.
I can not shutdown the asio pool because it is shared by several tasks.
I'm not sure whether my code is wrong or not.