c++boost-asiowebsocket++

websocketpp asio listen error


I have a multi-threaded websocketpp server. With no clients connected when I quit the program and relaunch, it works with no issues.

However when a client is connected and I quit/relaunch, the program throws this error

[2017-08-06 15:36:05] [info] asio listen error: system:98 ()
terminate called after throwing an instance of 'websocketpp::exception'
   what():  Underlying Transport Error
Aborted

I believe I have a proper disconnect sequence going and I have the following message (my own debug info) when I initiate the quit sequence

[2017-08-06 15:35:55] [control] Control frame received with opcode 8
on_close
[2017-08-06 15:35:55] [disconnect] Disconnect close local:[1000] remote:[1000]
Quitting :3
Waiting for thread

What does the asio error mean? I am hoping someone has seen this before so that I can begin troubleshooting. Thanks!

EDIT: I am adapting the stock broadcast_server example where

typedef std::map<connection_hdl, connection_data, std::owner_less<connection_hdl> > con_list;
con_list m_connections;

Code to close connections.

lock_guard<mutex> guard(m_connection_lock);
std::cout << "Closing Server" << std::endl;
con_list::iterator it;
for (it = m_connections.begin(); it != m_connections.end(); ++it)
{
    m_server.close(it->first, websocketpp::close::status::normal, "", ec);
    if (ec)
    {
        std::cout << "> Error initiating client close: " << ec.message() << std::endl;
    }
    m_connections.erase(it->first);
}

Also in destructor for broadcast_server class I have a m_server.stop()


Solution

  • Whenever there's a websocketpp::exception, I first check anywhere I'm explicitly using the endpoint, in your case m_server.

    For instance, it could be somewhere where you are calling m_server.send(...). Since you're multithreading, it's very possible that one of the threads may be trying to utilize a connection_hdl while it has already been closed by a different thread.

    In that case, it's usually a websocketpp::exception invalid state. I'm not sure for the Underlying Transport Error.

    You can use breakpoints to spot the culprit (or put a bunch of cout sequences in different methods, and see which sequence is broken before the exception is thrown), or use a try/catch:

    try {
        m_server.send(hdl, ...);
        // or
        m_server.close(hdl, ...);
        // or really anything you're trying to do using `m_server`.
    } catch (const websocketpp::exception &e) {//by safety, I just go with `const std::exception` so that it grabs any potential exceptions out there.
        std::cout << "Exception in method foo() because: " << e.what() /* log the cause of the exception */ << std::endl;
    }
    

    Otherwise, I have noticed that it will sometimes throw an exception when you're trying to close a connection_hdl, even if no other thread is seemingly accessing it. But if you put it in a try/catch, although it still throws the exception, since it doesn't terminate the program, it eventually closes the handler.

    Also, maybe try m_server.pause_reading(it->first) before calling close() to freeze activity from that handler.


    After second look, I think the exception you're getting is thrown where you listen with m_server.listen(...). Try surrounding it with a try/catch and putting a custom logging message.