Skip to content

Need an explicit way to signal when it is safe to destroy an endpoint #501

@Thalhammer

Description

@Thalhammer

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.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions