zaphoyd / websocketpp

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

Export symbols #1108

Open isaacsaffold opened 1 year ago

isaacsaffold commented 1 year ago

Symbol conflicts can occur when WebSocket++ headers are included in multiple shared libraries. The various lib::error_category singletons are particularly troublesome in this regard.

For example, I recently ran into a bug in my code that was traceable to a comparison of error codes in websocketpp::transport::asio::connection::handle_post_init_timeout().

void handle_post_init_timeout(timer_ptr, init_handler callback,
    lib::error_code const & ec)
{
    lib::error_code ret_ec;

    if (ec) {
        if (ec == transport::error::operation_aborted) {
            m_alog->write(log::alevel::devel,
                "asio post init timer cancelled");
            return;
        }
    // ...
}

ec == transport::error::operation_aborted invokes lib::error_code::operator==, which first checks if the two operands' error categories are equal. In my case, they should have been, but the websocketpp::transport::error::category singleton was included in two shared libraries, one of them having symbol visibility set to "hidden" by default. As the singleton symbol was not specifically exported from this library, it wasn't visible to the other library, and thus was not linked properly. This resulted in the address of one library's instance of the singleton being different than that of the other library's, and in the equality comparison returning the wrong result.

In this pull request, I have explicitly exported lib::error_category singletons as well as exception classes (see Problems with C++ exceptions here) via the new _WEBSOCKETPP_EXPORT_SYMBOL macro.

My changes were made with WebSocket++'s focus on portability and minimizing dependencies in mind, but there may still be some concerns. I believe the decreased risk of symbol conflicts is worth it, but it is up to the maintainers in the end.

I ran the provided tests on my machine (Ubuntu 22.04, using GCC 12), and all went well. I additionally verified that the correct symbols were exported.