zaphoyd / websocketpp

C++ websocket client/server library
http://www.zaphoyd.com/websocketpp
Other
6.95k stars 1.96k forks source link

Websocket locked DLL_PROCESS_DETACH #905

Open AnWuPP opened 4 years ago

AnWuPP commented 4 years ago

Hey. I make a WebSocket connection in a dynamic library. The problem occurs when you try to unload this very library. The main application freezes.

websocket.h

#pragma once
typedef websocketpp::client<websocketpp::config::asio_client> client;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;

typedef websocketpp::config::asio_client::message_type::ptr message_ptr;

class ws_point :public boost::noncopyable
{
public:
    typedef boost::system::error_code error_code;
    typedef ws_point type;
    typedef std::chrono::duration<int, std::micro> dur_type;
    websocketpp::connection_hdl ghdl;
    bool connected;
    bool inited;

    ws_point();
    ~ws_point();
    void init();
    void connect(std::string& uri);
    void disconnect();
    void send(websocketpp::connection_hdl hdl, const char* str);
    void close(websocketpp::connection_hdl hdl, websocketpp::close::status::value code);
    void on_open(websocketpp::connection_hdl hdl);
    void on_message(websocketpp::connection_hdl hdl, message_ptr msg);
    void on_close(websocketpp::connection_hdl hdl);
    void on_fail(websocketpp::connection_hdl hdl);
private:
    client m_endpoint;
    websocketpp::lib::shared_ptr<websocketpp::lib::thread> m_thread;
};

extern std::shared_ptr<ws_point> WebSocket;

websocket.cpp

void ws_point::init()
{
    if (!inited)
    {
        m_endpoint.clear_access_channels(websocketpp::log::alevel::all);
        m_endpoint.clear_error_channels(websocketpp::log::elevel::all);
        m_endpoint.init_asio();
        m_endpoint.start_perpetual();
        m_thread = websocketpp::lib::make_shared<websocketpp::lib::thread>(&client::run, &m_endpoint);
        inited = true;
        //connect(wsuri);
    }
}
void ws_point::disconnect()
{
    m_endpoint.stop_perpetual();
    websocketpp::lib::error_code ec;
    if (connected)
        m_endpoint.close(ghdl, websocketpp::close::status::going_away, "", ec);
    /*if (ec) {
        return;
    }*/
    m_endpoint.stop();
    m_thread->join();
    connected = false;
}

void ws_point::connect(std::string& uri) {
    if (inited)
    {
        websocketpp::lib::error_code ec;
        client::connection_ptr con = m_endpoint.get_connection(uri, ec);
        if (ec) {
            SF->Log(ec.message());
            return;
        }
        ghdl = con->get_handle();
        con->set_message_handler(bind(&type::on_message, this, ::_1, ::_2));
        con->set_open_handler(bind(&type::on_open, this, ::_1));
        con->set_close_handler(bind(&type::on_close, this, ::_1));
        con->set_fail_handler(bind(&type::on_fail, this, ::_1));
        m_endpoint.connect(con);
    }
}

init in main.cpp

WebSocket = std::make_shared<ws_point>();
WebSocket->init();
WebSocket->connect(wsuri);

what am i doing wrong?

xinthose commented 4 years ago

Are you saying your program freezes when disconnect is called?

AnWuPP commented 4 years ago

Are you saying your program freezes when disconnect is called?

call in destructor dll

AnWuPP commented 4 years ago

Are you saying your program freezes when disconnect is called?

yea. problem with shared_ptr. thread m_thread alive after unloading my dll. maybe

xinthose commented 4 years ago

I do not use the libraries' thread, but a boost::thread instead:

boost::thread run_thread;

INFO << "start the ASIO io_service run loop";
run_thread = boost::thread([this] {
    try
    {
        m_server.run();
    }
    catch (const std::exception &e)
    {
        ERROR << "run_thread >> error = " << e.what();
        callback_error = true;
    }
    INFO << "run_thread stopping";
});

Then, in my deconstructor, I stop listening, close all connections, and join run_thread:

websocketpp::lib::error_code ec;

m_server.stop_listening();

// close all connections
con_list::iterator it;
for (it = m_connections.begin(); it != m_connections.end(); ++it)
{
    m_server.close(*it, websocketpp::close::status::service_restart, "class destructor", ec);
    if (ec)
    {
        ERROR << "close error; error = " << ec.message();
    }
}

// stop running thread
if (run_thread.joinable())
{
    INFO << "end run_thread";
    run_thread.join();
}