cURL / Mailing Lists / curl-library / Single Mail

curl-library

CURL7.20.0-1 core dump under load, near-zero hold-time on responses

From: John Lee <jhn134910_at_gmail.com>
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