curl-library
CURL7.20.0-1 core dump under load, near-zero hold-time on responses
Date: Wed, 9 Mar 2011 12:36:32 +0000
Chugs along for hundreds of thousands of HTTP request/responses and then
bang....
Similar core backtraces:
(gdb) bt
#0 Curl_splay (i={tv_sec = 1624023, tv_usec = 680044}, t=0x0) at splay.c:53
#1 0x0015b200 in Curl_splaygetbest (i={tv_sec = 1624023, tv_usec = 680044},
t=0x9f309e0,
removed=0xb61cf18c) at splay.c:213
#2 0x00153c1f in curl_multi_perform (multi_handle=0x954506c,
running_handles=0xb61cf37c)
at multi.c:1607
#3 0x00aece88 in http_client_send_request () at http_client.c:488
#4 0x0804c1ca in http_client_loop (arg=0x0) at ussdmain.c:493
#5 0x009a43cc in start_thread () from /lib/tls/libpthread.so.0
#6 0x005e4f0e in clone () from /lib/tls/libc.so.6
(gdb)
(gdb) bt
#0 Curl_splay (i={tv_sec = 1628422, tv_usec = 184510}, t=0xa440c80) at
splay.c:57
#1 0x00354200 in Curl_splaygetbest (i={tv_sec = 1628422, tv_usec = 184510},
t=0xa440c80,
removed=0xb61b218c) at splay.c:213
#2 0x0034cc1f in curl_multi_perform (multi_handle=0xa37606c,
running_handles=0xb61b237c)
at multi.c:1607
#3 0x00748e73 in http_client_send_request () at http_client.c:488
#4 0x0804c1ca in http_client_loop (arg=0x0) at ussdmain.c:493
#5 0x009a43cc in start_thread () from /lib/tls/libpthread.so.0
#6 0x00914f0e in clone () from /lib/tls/libc.so.6
(gdb)
Pseudo-code : Using multi-interface (Leaving out error handling for
clarity):
Thread #1
Function #1 : Initialization function and settings that shall apply to all
connections.
curl_global_init(CURL_GLOBAL_ALL);
multi_handle = curl_multi_init();
for(i=0; i<configured_number_of_connections; i++)
{
client_connection_array[i].easy_handle = curl_easy_init();
curl_easy_setopt(client_connection_array[i].easy_handle,
CURLOPT_TIMEOUT, transmission_timeout);
curl_easy_setopt(client_connection_array[i].easy_handle,
CURLOPT_CONNECTTIMEOUT, connection_timeout);
}
curl_easy_setopt(client_connection_array[i].easy_handle, CURLOPT_NOSIGNAL,
1L);
Function #2 : Create POST bundle function.
curl_easy_setopt( client_connection_array[i].easy_handle,CURLOPT_URL,
.client_connection_array[i].config.url);
curl_easy_setopt( client_connection_array[i].easy_handle, CURLOPT_POST,
TRUE);
curl_easy_setopt( client_connection_array[i].easy_handle,
CURLOPT_POSTFIELDSIZE,
strlen(client_connection_array[i].config.request_payload);
curl_easy_setopt( client_connection_array[i].easy_handle,
CURLOPT_POSTFIELDS, client_connection_array[i].config.request_payload);
curl_easy_setopt( client_connection_array[i].easy_handle,
CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt( client_connection_array[i].easy_handle,
CURLOPT_WRITEDATA, &client_connection_array[i].read_response);
curl_multi_add_handle(multi_handle, client_connection_array[i].easy_handle);
Function #3 :Shutdown
for(i=0; i<configured_number_of_connections; i++)
{
if(NULL != client_connection_array[i].easy_handle)
{
curl_multi_remove_handle( multi_handle,
client_connection_array[i].easy_handle);
curl_easy_cleanup(client_connection_array[i].easy_handle);
}
}
curl_multi_cleanup(multi_handle);
free(client_connection_array);
Thread #2 - Called every 10ms
Function #1 :
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(multi_handle, &still_running));
while(still_running)
{
if((++iterate)>TUNING_ITERATIONS) break;
struct timeval timeout;
int rc; /* select() return code */
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
/* set a suitable timeout to play around with */
timeout.tv_sec = 1;
timeout.tv_usec = 0;
/* get file descriptors from the transfers */
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
switch(rc) {
case -1:
/* select error */
break;
case 0:
/* timeout, do something else */
break;
default:
/* One or more of curl's file descriptors say there's
data to read or write */
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(multi_handle, &still_running));
break;
}
}
while ((msg = curl_multi_info_read(multi_handle, &msgs_left)))
{
if(msg->msg == CURLMSG_DONE)
{
/* Find out which handle this message is about */
for(idx=0; idx<configured_number_of_connections; idx++)
{
found =
((msg->easy_handle ==
client_connection_array[idx].easy_handle)
&& (client_connection_array[idx].state == BUSY));
if(found)
break;
}
if((msg->data.result == CURLE_OK) && (found))
{
client_process_response pr =
client_connection_array[idx].config.response_callbk;
(*pr)( client_connection_array[idx].read_response.writeptr,
client_connection_array[idx].read_response.write_size);
}
else if((msg->data.result == CURLE_OPERATION_TIMEOUTED) &&
(found))
{
timeout_client_connection_notify tn =
client_connection_array[idx].config.timeout_client_callbk;
(*tn)(
client_connection_array[idx].config.destination_module,
client_connection_array[idx].config.destination_instance);
}
else
{
client_request_failure rf =
client_connection_array[idx].config.failure_client_callbk;
(*rf)(
client_connection_array[idx].config.destination_module,
client_connection_array[idx].config.destination_instance);
}
if((resm=curl_multi_remove_handle(multi_handle,
client_connection_array[idx].easy_handle)))
{
printf("Failed to remove easy handle from multi-stack, ret
%d\n",
resm);
}
client_connection_array[idx].state = IDLE;
if(NULL != client_connection_array[idx].read_response.writeptr)
free(client_connection_array[idx].read_response.writeptr);
}
}
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2011-03-09