天天看點

多線程中使用curl緻coredump問題

coredump時的調用棧:

#0  0x081eff2c in addbyter ()

#1  0x081f05b8 in dprintf_formatf ()

#2  0x081f15cf in curl_mvsnprintf ()

#3  0x081f0079 in curl_msnprintf ()

#4  0x081ef55c in Curl_failf ()

#5  0x081fa1a3 in Curl_resolv_timeout ()

#6  0xeb8fbdd4 in ?? ()

#7  0x00000000 in ?? ()

coredump的原因是因為curl的DNS解析逾時控制是使用SIGALARM實作的。

這樣導緻發現SIGALARM會出現多線程修改同一個全局變量,由此産生了COREDUMP。

問題發生的前提是設定了CURLOPT_TIMEOUT或CURLOPT_CONNECTTIMEOUT,并且值不為0。

解決辦法:

1) 設定CURLOPT_NOSIGNAL的值為1

2) 使用c-ares(configure時指定參數--enable-ares)

lib/curl_setup.h(異步模式使用c-ares控制DNS解析逾時):

隻有當configure時指定了--enable-ares才會定義USE_ARES。

#ifdef USE_ARES

#  define CURLRES_ASYNCH

#  define CURLRES_ARES

/* now undef the stock libc functions just to avoid them being used */

#  undef HAVE_GETADDRINFO

#  undef HAVE_GETHOSTBYNAME

#elif defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)

#  define CURLRES_THREADED

#else

#  define CURLRES_SYNCH

#endif

lib/hostip.c(同步模式使用ALARM控制DNS解析逾時):

隻有定義了CURLRES_SYNCH,才可能定義USE_ALARM_TIMEOUT。

#if defined(CURLRES_SYNCH) && \

    defined(HAVE_ALARM) && defined(SIGALRM) && defined(HAVE_SIGSETJMP)

/* alarm-based timeouts can only be used with all the dependencies satisfied */

#define USE_ALARM_TIMEOUT

相關源代碼:

lib/asyn-ares.c:

Curl_resolver_getaddrinfo

lib/hostasyn.c(基于c-ares的異步版本Curl_getaddrinfo):

從緩存中找(hostip.c):

fetch_addr

hostip.c:

Curl_ipv4_resolve_r

curl_jmpenv

url.c:

Curl_resolv_timeout(hostname)

multi.c:

Curl_connect

transfer.c

Curl_reconnect_request

Curl_do

繼續閱讀