多线程调用libcurl基于https会导致的crash

今天发现如果使用多线程调用curl_easy的接口,并发访问若干https的接口,程序会出现偶尔的崩溃。崩溃位于调用curl_easy_cleanup的时候,最后崩溃的函数位于LIBEAY32.dll中的getrn。google搜索之后发现这是libcurl在使用openssl的时候,根据openssl版本的不同,可能需要设置回调的函数
https://curl.haxx.se/libcurl/c/threadsafe.html

我的libcurl是使用vcpkg安装的,它依赖的openssl版本为1.0.2o,因此需要设置回调函数locking_function和threadid_func。当然,openssl 1.0.2的文档也提到

threadid_func(CRYPTO_THREADID *id) is needed to record the currently-executing thread's identifier into id. The implementation of this callback should not fill in id directly, but should use CRYPTO_THREADID_set_numeric() if thread IDs are numeric, or CRYPTO_THREADID_set_pointer() if they are pointer-based. If the application does not register such a callback using CRYPTO_THREADID_set_callback(), then a default implementation is used - on Windows and BeOS this uses the system's default thread identifying APIs, and on all other platforms it uses the address of errno. The latter is satisfactory for thread-safety if and only if the platform has a thread-local error number facility.

也就是说windows上有获取线程ID的实现,不需要注册threadid的回调

网上的很多例子都是基于官网例子改的,使用了pthread库的相关函数
https://curl.haxx.se/libcurl/c/opensslthreadlock.html

在windows上面使用pthread并不是那么方便。可以参考基于c++11的实现
https://stackoverflow.com/questions/34998440/curl-crashes-in-threaded-calls

基于boost的实现
https://curl.haxx.se/mail/lib-2016-11/0175.html

std::vector openssl_lock_list(CRYPTO_num_locks());

void openssl_crypto_locking_callback(
    int mode, int type, const char * const, int)
{
    if (mode & CRYPTO_LOCK) {
        openssl_lock_list[type].lock();
    }
    else {
        openssl_lock_list[type].unlock();
    }
}

    // 要多线程调用前先设置openssl的lock回调
    CRYPTO_set_locking_callback(openssl_crypto_locking_callback);

 

你可能感兴趣的:(OpenSSL)