Search code examples
crashboost-asiocpprest-sdkwebsocket++

Boost asio crashes


I have a program using cpprestsdk for http querying and websocketpp for subscribing a data stream. The program will crash immediately(it says Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)). But if I comment either of the http querying or subcribing data stream, the program won't crash.

#include <websocketpp/config/asio_client.hpp>
#include <websocketpp/client.hpp>
#include "json.hpp"
#include <iostream>
#include <ctime>
#include <iostream>
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <vector>
#include <string>


using std::string;
using namespace web;
using std::cout, std::endl;
using std::vector;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;

typedef websocketpp::client<websocketpp::config::asio_tls_client> client;
typedef websocketpp::config::asio_client::message_type::ptr message_ptr;


void on_stream_data(websocketpp::connection_hdl hdl, message_ptr msg) {
}

class OrderBook {
public:
    void initialize() {
        web::http::client::http_client_config cfg;
        std::string uri = string("https://fapi.binance.com/fapi/v1/depth?symbol=btcusdt&limit=1000");
        web::http::client::http_client client(U(uri), cfg);
        web::http::http_request request(web::http::methods::GET);
        request.headers().add("Content-Type", "application/x-www-form-urlencoded");
        web::http::http_response response = client.request(request).get();
    }

    int start_stream() {
        client c;
        std::string uri = string("wss://fstream.binance.com/ws/btcusdt@depth@100ms");
        try {
            c.set_access_channels(websocketpp::log::alevel::all);
            c.clear_access_channels(websocketpp::log::alevel::frame_payload);
            c.init_asio();
            c.set_message_handler(bind(on_stream_data, ::_1, ::_2));
            websocketpp::lib::error_code ec;
            client::connection_ptr con = c.get_connection(uri, ec);
            if (ec) {
                std::cout << "could not create connection because: " << ec.message() << std::endl;
                return 0;
            }
            c.connect(con);
            c.run();
        } catch (websocketpp::exception const &e) {
            std::cout << e.what() << std::endl;
        }
    }
};

int main(int argc, char *argv[]) {
    OrderBook ob;
    ob.initialize();  // comment either of these two lines, the program won't crash, otherwise the program will crash once start
    std::this_thread::sleep_for(std::chrono::milliseconds(10000000));
    ob.start_stream();  // comment either of these two lines, the program won't crash, otherwise the program will crash once start
}

When I run this program in Clion debug mode, Clion show that the crash comes from function in /opt/homebrew/Cellar/boost/1.76.0/include/boost/asio/ssl/detail/impl/engine.ipp

int engine::do_connect(void*, std::size_t)
{
  return ::SSL_connect(ssl_);
}

It says Exception: EXC_BAD_ACCESS (code=1, address=0xf000000000)

What's wrong with it? is it because I run two pieces of code using boost::asio, and something shouldn't be initialized twice?


Solution

  • I can compile this and run it fine.

    My best bet is that you might be mixing versions, particularly boost versions. A common mode of failure is caused when ODR violations lead to Undefined Behaviour.

    Note that these header-only libraries depend on a number of boost libraries that are not header-only (e.g. Boost System, Thread and/or Chrono). You need to compile against the same version as the libraries you link.

    If you use distribution packaged versions of any library (cpprestsdk, websocketpp or whatever json library that is you're using) then you'd be safest also using the distribution packaged version of Boost.

    I'd personally simplify the situation by just using Boost (Beast for HTTP/websocket, Json for, you guessed it).

    Running it all on a test Ubuntu 18.04 the OS Boost 1.65 version, the start_stream sequence triggers this informative error:

    [2022-05-22 13:42:11] [fatal] Required tls_init handler not present.
    could not create connection because: Connection creation attempt failed
    

    While being UBSAN/ASAN clean. Perhaps that error helps you, once you figure out the configuration problems that made your program crash.