2010-07-19 28 views
7

所以我有一堆工作線程做簡單的捲曲類,每個工作線程都有自己的捲曲簡單句柄。他們只對隨機網站進行HEAD查找。還有鎖定功能可用於啓用多線程SSL,如文檔here所述。一切工作除了在2個網頁ilsole24ore.com(例如,在看到下),並ninemsn.com.au/,他們有時會產生賽格如圖跟蹤輸出這裏libcurl中的分段錯誤,多線程

#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 

出故障My功能看起來像這

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; 
} 

現在,當我打電話功能,無需任何線程,只需調用它從主就從來沒有斷,所以我想它的連接線,或被也許是如何返回數據結構中返回,但是從我在跟蹤中看到它看起來像是在easy_perform()調用中生成的故障,它令我困惑。 所以,如果有人有任何想法,我應該看看下一個這將是最有幫助的,謝謝。

回答

13

libcurl to Multi-Threading有專門的整節。

第一個基本規則是,你必須 從來沒有共享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不是 線程安全。

+0

是的,我讀過捲曲的一部分,我的計劃遵循所有的指導方針。但是我找到了這個問題,它沒有捲毛,只是調試器指向那裏。我確實學到了一些關於捲曲的新東西,無論如何。 – Mogwai 2010-07-20 11:28:44

0

error: longjmp causes uninitialized stack frame提到的,在於Debian/Ubuntu儲存庫中的最新版本的libcurl(> = 7.32.0)包含一個新的多線程分解器來解決這些問題。在C-戰神的支持是不是一個很好的解決方案:

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=570436#74

「真正的問題是,C-戰神尚未對gethostby *函數(例如,它不支持組播DNS)和啓用全部更換它有股票libcurl包可能不是一個好的舉措(請注意,這些都是捲曲和c - ares的上游作者的話,而不是我的)。「 -