curl_easy_init 多线程使用导致的崩溃

当多个线程,同时进行curl_easy_init时,由于会调用非线程安全的curl_global_init,因此导致崩溃。
应该在主线程优先调用curl_global_init进行全局初始化。再在线程中使用curl_easy_init。

示例代码

/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * are also available at https://curl.haxx.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 * copies of the Software, and permit persons to whom the Software is
 * furnished to do so, under the terms of the COPYING file.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ***************************************************************************/
/* <DESC>
 * A multi-threaded example that uses pthreads to fetch several files at once
 * </DESC>
 */

#include <stdio.h>
#include <pthread.h>
#include <curl/curl.h>

#define NUMT 4

/*
  List of URLs to fetch.
  If you intend to use a SSL-based protocol here you might need to setup TLS
  library mutex callbacks as described here:
  https://curl.haxx.se/libcurl/c/threadsafe.html
*/
const char * const urls[NUMT]= {
  "https://curl.haxx.se/",
  "ftp://cool.haxx.se/",
  "https://www.cag.se/",
  "www.haxx.se"
};

static void *pull_one_url(void *url)
{
  CURL *curl;

  curl = curl_easy_init();
  curl_easy_setopt(curl, CURLOPT_URL, url);
  curl_easy_perform(curl); /* ignores error */
  curl_easy_cleanup(curl);

  return NULL;
}


/*
   int pthread_create(pthread_t *new_thread_ID,
   const pthread_attr_t *attr,
   void * (*start_func)(void *), void *arg);
*/

int main(int argc, char **argv)
{
  pthread_t tid[NUMT];
  int i;
  int error;

  /* Must initialize libcurl before any threads are started */
  curl_global_init(CURL_GLOBAL_ALL);

  for(i = 0; i< NUMT; i++) {
    error = pthread_create(&tid[i],
                           NULL, /* default attributes please */
                           pull_one_url,
                           (void *)urls[i]);
    if(0 != error)
      fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);
    else
      fprintf(stderr, "Thread %d, gets %s\n", i, urls[i]);
  }

  /* now wait for all threads to terminate */
  for(i = 0; i< NUMT; i++) {
    error = pthread_join(tid[i], NULL);
    fprintf(stderr, "Thread %d terminated\n", i);
  }

 curl_global_cleanup(); //liburl使用结束,手动close
  return 0;
}

另外,多线程访问https,也有可能发生崩溃,因为openssl默认是非线程安全的,需要为openssl设置互斥锁回调函数:

CRYPTO_set_locking_callback
CRYPTO_set_id_callback

libcurl 多线程使用注意事项(补充)——HTTPS,openssl多线程使用加锁
多线程使用libcurl的坑

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`curl_global_init`和`curl_easy_init`都是libcurl库中的初始化函数,但是它们的作用不同。 `curl_global_init`用于初始化libcurl库的全局环境,包括SSL、Winsock等。它只需要在程序运行时调用一次。如果在多线程中使用libcurl库,应该在每个线程中调用`curl_global_init`函数来初始化全局环境。如果没有调用`curl_global_init`,则在使用libcurl库时会自动调用它进行初始化。 `curl_easy_init`用于初始化一个CURL句柄,CURL句柄用于执行HTTP请求和处理响应。每个HTTP请求需要创建一个CURL句柄,当HTTP请求完成后,需要使用`curl_easy_cleanup`函数清理CURL句柄。 在使用libcurl库时,应该先调用`curl_global_init`函数初始化全局环境,然后在需要执行HTTP请求时,使用`curl_easy_init`函数初始化一个CURL句柄。在HTTP请求完成后,使用`curl_easy_cleanup`函数清理CURL句柄,并在程序结束时调用`curl_global_cleanup`函数释放所有全局资源。 以下是一个示例,用于初始化libcurl库的全局环境并执行HTTP请求: ```c #include <stdio.h> #include <curl/curl.h> int main(void) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); // 初始化全局环境 curl = curl_easy_init(); // 初始化CURL句柄 if (curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); res = curl_easy_perform(curl); // 执行HTTP请求 if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_easy_cleanup(curl); // 清理CURL句柄 } curl_global_cleanup(); // 释放全局资源 return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值