ps:小白一枚,都是从网上找的解决方案,简单记录一下
libcurl多线程无故crash 可能会影响的原因:
1.当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。
如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。所以需要:
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
2.关于libcurl库的初始化和关闭:curl_global_init()和curl_global_cleanup()
这两个函数并不是线程安全的。所以只能在主线程中进行一次的初始化和清除。
3.尝试给线程函数上锁,锁上以后运行两天出现了一次崩溃
4.给回调函数上锁
回调实例: curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData); //对返回的数据进行操作的函数地址
给OnWriteData 没啥用这各操作
5.openssl需要上锁 参考:https://blog.csdn.net/weiyuefei/article/details/51426000?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170132236616800197029623%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=170132236616800197029623&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-51426000-null-null.142^v96^pc_search_result_base2&utm_term=libcurl%E5%B4%A9%E6%BA%83&spm=1018.2226.3001.4187
6.openssl版本问题: openssl 1.0.2 不是线程安全的,当前我们程序用的是1.0.1
以上是针对此次问题做出的可能存在的问题以及解决办法,最后排查发现主要是问题2导致的,代码里有写curl_global_init,并且是在构造函数,但是我没有定位清除,因为还有个构造函数的重载,最后调的是另一个构造函数,所以导致每一个easu_init都调用global_init,导致的crash
针对方案3和4 用的下面代码:
std::mutex g_mutex;
std::lock_guard<std::mutex> lock(g_mutex); // 在回调函数中加锁
基本就是这样
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
上次这样做了还是有问题,现在针对openssl库加锁,是每次post请求都自己带锁和解锁,参考是的官方给的文档
//创建多线程
bool startThread()
{
openssl_crypto_init_locks();
// 要多线程调用前先设置openssl的lock回调
CRYPTO_set_locking_callback(openssl_crypto_locking_callback);
bool ret = true;
if(!m_isRunning)
{
m_isRunning = true;
m_thread = new std::thread(threadFun, this);
}
return ret;
}
//锁的初始化
void openssl_crypto_init_locks()
{
for(int i = 0; i < CRYPTO_num_locks(); ++i)
{
openssl_lock_list = std::vector<std::mutex>(CRYPTO_num_locks());
}
}
//锁的回调
void openssl_crypto_locking_callback(int mode, int type, const char * const, int line)
{
if (mode & CRYPTO_LOCK)
{
openssl_lock_list[type].lock();
}
else
{
openssl_lock_list[type].unlock();
}
}