2010-07-19 16 views
7

Tak więc mam kilka wątków roboczych, które wykonują prostą klasę zawijania, a każdy wątek roboczy ma swój własny lokalny uchwyt. Robią tylko wyszukiwania HEAD na losowych stronach internetowych. Dostępne są również funkcje blokowania umożliwiające włączenie wielowątkowego protokołu SSL zgodnie z dokumentacją here. Wszystko działa z wyjątkiem na 2 stronach internetowych ilsole24ore.com (obserwowane w przykładzie dół), a ninemsn.com.au/, czasami wytwarzają seg winy, jak pokazano na wyjściu śladowej pokazane tutajBłąd segmentacji w bibliotece libcurl, wielowątkowej

#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 

Moja funkcja wygląda mniej więcej tak to

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

teraz, kiedy wywołanie funkcji bez wątków, tylko wywołanie go z głównym nigdy nie łamie, więc myślałem jego podłączony do gwintów, czy może jak dane powrócić struktura jest zwracany, ale z tego co ja widziałeś w śladzie, wygląda na to, że błąd generowany jest w wywołaniu easy_perform(), a to mnie myli. Więc jeśli ktoś ma pojęcie, gdzie powinienem patrzeć dalej, byłoby to bardzo pomocne, dzięki.

Odpowiedz

13

Istnieje cała sekcja poświęcona libcurl to Multi-Threading.

Pierwszą podstawową zasadą jest to, że trzeba nigdy dzielić uchwyt libcurl (może to być proste lub Multi lub cokolwiek) między wiele wątków. Używaj tylko jednego uchwytu w jednym wątku na raz.

libcurl jest całkowicie bezpieczny dla wątków, , z wyjątkiem dwóch problemów: sygnałów i kopert SSL/TLS. Sygnały są używane do sprawdzania czasu rozstrzygnięcia nazwy (podczas wyszukiwania DNS ) - gdy są budowane bez obsługi c-ares , a nie w systemie Windows.

Jeśli dostęp HTTPS lub FTPS adresy URL w wielowątkowych sposób, ty są to oczywiście przy użyciu bazowego SSL library wielowątkowy i te libs może mieć swoje własne wymagania na ten temat. Zasadniczo, musisz podać jedną lub dwie funkcje , aby umożliwić prawidłowe działanie . Dla wszystkich informacji, patrz poniżej:

OpenSSL

http://www.openssl.org/docs/crypto/threads.html#DESCRIPTION

GnuTLS

http://www.gnu.org/software/gnutls/manual/html_node/Multi_002dthreaded-applications.html

KSW

jest uważana za bezpieczny wątku już bez niczego wymagane.

yassl

Wymagane działania nieznane.

Podczas korzystania z wielu wątków należy ustawić CURLOPT_NOSIGNAL opcję 1 dla wszystkich uchwytów.Wszystko będzie działało dobrze, z wyjątkiem tego, że limity czasu oczekiwania nie są honorowane podczas wyszukiwania DNS - które można obejść, budując libcurl z obsługą c-ares. c-ares to biblioteka udostępniająca asynchroniczną nazwę . Na niektórych platformach , libcurl po prostu nie będzie działać poprawnie z wieloma wątkami , chyba że ta opcja jest ustawiona.

Należy również pamiętać, że CURLOPT_DNS_USE_GLOBAL_CACHE nie jest bezpieczny dla wątków.

+0

Tak, przeczytałem tę część zwijania i mój program postępuje zgodnie ze wszystkimi wytycznymi. Ale zlokalizowałem problem i jego nie loki błąd, to tylko debugger wskazywał tam. Nauczyłem się nowych rzeczy na temat zwijania się, dzięki. – Mogwai

0

Jak wspomniano w error: longjmp causes uninitialized stack frame, najnowsze wersje libCurl (> = 7.32.0) w repozytoriach Debiana/Ubuntu zawierać nowe wielowątkowe rozpoznawania nazw, aby rozwiązać te problemy. Wsparcie c-Ares nie jest dobrym rozwiązaniem:

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

„Prawdziwym problemem jest to, że C-Ares nie jest jeszcze pełny zamiennik gethostby * funkcje (na przykład nie obsługuje multicast DNS) oraz umożliwienie to w pakietach libcurl może nie być dobrym posunięciem (zauważ, że są to słowa twórcy zarówno curla, jak i c-ares, nie mojego). "-

Powiązane problemy