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

本文探讨了使用libcurl在多线程环境下并发访问HTTPS接口时出现的程序崩溃问题,尤其关注于调用curl_easy_cleanup时的崩溃现象。通过分析发现,问题源于libcurl与openssl版本兼容性,需设置回调函数locking_function和threadid_func。文章提供了基于C++11的解决方案,避免使用pthread,确保Windows平台下多线程调用的安全。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天发现如果使用多线程调用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<std::mutex> 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);

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值