Mog*_*wai 7 c curl pthreads segmentation-fault
所以我有一堆工作线程做简单的curl类,每个工作线程都有自己的curl easy handle.他们只在随机网站上进行HEAD查找.此外,还存在锁定功能以启用多线程SSL,如此处所述.一切正常,除了2个网页ilsole24ore.com(见例下)和ninemsn.com.au/,它们有时会产生seg故障,如此处所示的跟踪输出所示
#0 *__GI___libc_res_nquery (statp=0xb4d12df4, name=0x849e9bd "ilsole24ore.com", class=1, type=1, answer=0xb4d0ca10 "", anslen=1024, answerp=0xb4d0d234,
answerp2=0x0, nanswerp2=0x0, resplen2=0x0) at res_query.c:182
#1 0x00434e8b in __libc_res_nquerydomain (statp=0xb4d12df4, name=0xb4d0ca10 "", domain=0x0, class=1, type=1, answer=0xb4d0ca10 "", anslen=1024,
answerp=0xb4d0d234, answerp2=0x0, nanswerp2=0x0, resplen2=0x0) at res_query.c:576
#2 0x004352b5 in *__GI___libc_res_nsearch (statp=0xb4d12df4, name=0x849e9bd "ilsole24ore.com", class=1, type=1, answer=0xb4d0ca10 "", anslen=1024,
answerp=0xb4d0d234, answerp2=0x0, nanswerp2=0x0, resplen2=0x0) at res_query.c:377
#3 0x009c0bd6 in *__GI__nss_dns_gethostbyname3_r (name=0x849e9bd "ilsole24ore.com", af=2, result=0xb4d0d5fc, buffer=0xb4d0d300 "\177", buflen=512,
errnop=0xb4d12b30, h_errnop=0xb4d0d614, ttlp=0x0, canonp=0x0) at nss_dns/dns-host.c:197
#4 0x009c0f2b in _nss_dns_gethostbyname2_r (name=0x849e9bd "ilsole24ore.com", af=2, result=0xb4d0d5fc, buffer=0xb4d0d300 "\177", buflen=512,
errnop=0xb4d12b30, h_errnop=0xb4d0d614) at nss_dns/dns-host.c:251
#5 0x0079eacd in __gethostbyname2_r (name=0x849e9bd "ilsole24ore.com", af=2, resbuf=0xb4d0d5fc, buffer=0xb4d0d300 "\177", buflen=512, result=0xb4d0d618,
h_errnop=0xb4d0d614) at ../nss/getXXbyYY_r.c:253
#6 0x00760010 in gaih_inet (name=<value optimized out>, service=<value optimized out>, req=0xb4d0f83c, pai=0xb4d0d764, naddrs=0xb4d0d754)
at ../sysdeps/posix/getaddrinfo.c:531
#7 0x00761a65 in *__GI_getaddrinfo (name=0x849e9bd "ilsole24ore.com", service=0x0, hints=0xb4d0f83c, pai=0xb4d0f860) at ../sysdeps/posix/getaddrinfo.c:2160
#8 0x00917f9a in ?? () from /usr/lib/libkrb5support.so.0
#9 0x003b2f45 in krb5_sname_to_principal () from /usr/lib/libkrb5.so.3
#10 0x0028a278 in ?? () from /usr/lib/libgssapi_krb5.so.2
#11 0x0027eff2 in ?? () from /usr/lib/libgssapi_krb5.so.2
#12 0x0027fb00 in gss_init_sec_context () from /usr/lib/libgssapi_krb5.so.2
#13 0x00d8770e in ?? () from /usr/lib/libcurl.so.4
#14 0x00d62c27 in ?? () from /usr/lib/libcurl.so.4
#15 0x00d7e25b in ?? () from /usr/lib/libcurl.so.4
#16 0x00d7e597 in ?? () from /usr/lib/libcurl.so.4
#17 0x00d7f133 in curl_easy_perform () from /usr/lib/libcurl.so.4
Run Code Online (Sandbox Code Playgroud)
我的功能看起来像这样
int do_http_check(taskinfo *info,standardResult *data)
{
standardResultInit(data);
char errorBuffer[CURL_ERROR_SIZE];
CURL *curl;
CURLcode result;
curl = curl_easy_init();
if(curl)
{
//required options first
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer);
curl_easy_setopt(curl, CURLOPT_URL, info->address.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data->body);
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, writer);
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, &data->head);
curl_easy_setopt(curl, CURLOPT_DNS_USE_GLOBAL_CACHE,0);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30 );
curl_easy_setopt(curl, CURLOPT_NOSIGNAL,1);
curl_easy_setopt(curl, CURLOPT_NOBODY,1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT ,240);
//optional options
if(info->options.follow)
{
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, info->options.redirects);
}
result = curl_easy_perform(curl);
if (result == CURLE_OK)
{
data->success = true;
curl_easy_getinfo(curl,CURLINFO_RESPONSE_CODE,&data->httpMsg);
curl_easy_getinfo(curl,CURLINFO_REDIRECT_COUNT,&data->numRedirects);
data->msg = "OK";
}
else
{
... handle error
}
return 1;
}
Run Code Online (Sandbox Code Playgroud)
现在,当我在没有任何线程的情况下调用函数时,只是从main调用它永远不会中断,所以我认为它连接到线程,或者可能是如何返回数据返回结构,但是从我在trace中看到的看起来像是故障是在easy_perform()调用中生成,令我困惑.因此,如果有人知道我应该在哪里看,那将是最有帮助的,谢谢.
小智 13
整个部分专门用于多线程的libcurl.
第一个基本规则是,您必须永远不要在多个线程之间共享libcurl句柄(简单或多个或其他).一次只能在一个线程中使用一个句柄.
libcurl完全是线程安全的,除了两个问题:信号和SSL/TLS处理程序.信号用于超时名称解析(在DNS查找期间) - 在没有c-ares支持的情况下构建,而不是在Windows上构建.
如果您以多线程方式访问HTTPS或FTPS URL,那么您当然使用多线程的基础SSL库,并且这些库可能对此问题有自己的要求.基本上,您需要提供一个或两个功能才能使其正常运行.有关所有细节,请参阅:
OpenSSL的
http://www.openssl.org/docs/crypto/threads.html#DESCRIPTION
的GnuTLS
http://www.gnu.org/software/gnutls/manual/html_node/Multi_002dthreaded-applications.html
NSS
声称已经是线程安全的,没有任何要求.
yassl
所需行动未知.
使用多个线程时,应将CURLOPT_NOSIGNAL选项设置为1以用于所有句柄.一切都会或者可能正常工作,除了在DNS查找期间没有超时 - 你可以通过构建具有c-ares支持的libcurl来解决这个问题.c-ares是一个提供异步名称解析的库.在某些平台上,除非设置了此选项,否则libcurl将无法正常运行多线程.
另请注意,CURLOPT_DNS_USE_GLOBAL_CACHE不是线程安全的.
| 归档时间: |
|
| 查看次数: |
9909 次 |
| 最近记录: |