cURL / Mailing Lists / curl-library / Single Mail

curl-library

About libcurl HTTPS and Multithreading crash

From: Woods <woods.biz_at_gmail.com>
Date: Sun, 4 Mar 2012 14:27:24 +0800

Hi

I asked this issue months back, which is about libcurl crashes when I
request https urls in multithreading manner.
According to your advice, I read through the multithreading and init
global sections in the tutorial, and they seem do not solve my
problem. I have tested the code, attached below, on Centos and Mac
platform, both crashes after I request over few hundreds of urls with
a pool of threads in size of 100 to 200 threads. In contract, if the
code only request Http urls, there is no such problem, it is stable.
I hope you can give me some advice on this, or if this is a know issue
in libcurl. Thank you!

Woods

The dump out information when crashes happen:
----------------------------------------------------------------------------
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1376396384 (LWP 15717)]
0x00649400 in lh_free () from /lib/libcrypto.so.4
(gdb) bt
#0 0x00649400 in lh_free () from /lib/libcrypto.so.4
#1 0x006496ff in lh_insert () from /lib/libcrypto.so.4
#2 0x0064baf5 in ERR_set_implementation () from /lib/libcrypto.so.4
#3 0x0064c434 in ERR_get_state () from /lib/libcrypto.so.4
#4 0x0064c48c in ERR_get_state () from /lib/libcrypto.so.4
#5 0x0064c71d in ERR_peek_error () from /lib/libcrypto.so.4
#6 0x00779a7c in SSL_get_error () from /lib/libssl.so.4
#7 0x08065cdd in ossl_connect_common ()
#8 0x08066ca7 in Curl_ossl_connect ()
#9 0x08053fc4 in Curl_ssl_connect ()
#10 0x08058e21 in Curl_http_connect ()
#11 0x0805f754 in Curl_protocol_connect ()
#12 0x0805ff96 in Curl_setup_conn ()
#13 0x080600a0 in Curl_connect ()
#14 0x0806ca26 in Curl_do_perform ()
#15 0x0804cdaa in ThreadProc () at src/test/testHttp.cpp:49
#16 0x004c65cc in start_thread () from /lib/tls/libpthread.so.0
#17 0x0041e35e in clone () from /lib/tls/libc.so.6

Another crash information is :
------------------------------------------------------------------------------
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1408226400 (LWP 11473)]
0x00649498 in lh_retrieve () from /lib/libcrypto.so.4
(gdb) bt
#0 0x00649498 in lh_retrieve () from /lib/libcrypto.so.4
#1 0x0077d02b in SSL_CTX_flush_sessions () from /lib/libssl.so.4
#2 0x00778fbb in SSL_CTX_free () from /lib/libssl.so.4
#3 0x080637d9 in Curl_ossl_close ()
#4 0x0805d413 in Curl_disconnect ()
#5 0x0806219f in Curl_done ()
#6 0x0806cb21 in Curl_do_perform ()
#7 0x0804cdaa in ThreadProc () at src/test/testHttp.cpp:49
#8 0x004c65cc in start_thread () from /lib/tls/libpthread.so.0
#9 0x0041e35e in clone () from /lib/tls/libc.so.6

My code is :
-------------------------------------------------------------------------------------
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <memory>
#include <pthread.h>
#include <string>

extern "C"
{
#include <curl/curl.h>
}

#include "Semaphore.h"
static Semaphore* pSem = NULL;

using namespace std;

size_t sWriteFunction(void *p_pPtr, size_t p_Size, size_t p_Nmemb,
void *p_pParam)
{
    vector<uint8_t> *pHead = reinterpret_cast<vector<uint8_t>*>(p_pParam);
    int bytesToRead = p_Size * p_Nmemb;
    pHead->insert(pHead->end(), static_cast<uint8_t*>(p_pPtr),
static_cast<uint8_t*>(p_pPtr) + bytesToRead);
    return bytesToRead;
}

static void* ThreadProc(void* p_pParam)
{
    vector<uint8_t> head;
    vector<uint8_t> body;

    printf("thread started\n");
    string* pUrl = static_cast<string*>(p_pParam);

    CURL* curl = curl_easy_init();
    curl_easy_setopt(curl, CURLOPT_URL, pUrl->c_str());
    curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 30);
    curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, sWriteFunction);
    curl_easy_setopt(curl, CURLOPT_HEADERDATA, &head);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, sWriteFunction);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &body);
    curl_easy_setopt(curl, CURLOPT_NOBODY, 1L);

    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);

    CURLcode res = curl_easy_perform(curl);
    const char* msg = curl_easy_strerror(res);
    printf("result = %s\n", msg);

    curl_easy_cleanup(curl);

    pSem->Post();
    printf("thread exited\n");
    return NULL;
}

int main(int argc, char* argv[])
{
    if (argc < 3)
    {
        printf("Usage : %s url.txt poolSize\n", argv[0]);
        return 0;
    }

    printf("Start\n");

    // read all urls
    FILE* fp = fopen(argv[1], "r");
    if (fp == NULL)
    {
        printf("Invalid file %s\n", argv[1]);
        return 0;
    }

    vector<string> targets;

    char line[4096];
    while (fgets(line, 4096, fp))
    {
        string url(line);
        if (url.find("https") == 0)
        {
            targets.push_back(string(line));
        }
    }
    fclose(fp);

    int poolSize = atoi(argv[2]);
    if (poolSize <= 0)
    {
        printf("Invalid pool size = %d\n", poolSize);
    }
    pSem = new Semaphore(poolSize, poolSize);

    curl_global_init(CURL_GLOBAL_ALL);

   // start to request continuously
    while (true)
    {
        int i = 0;
        for (vector<string>::iterator itr = targets.begin(); itr !=
targets.end(); ++itr)
        {
            pSem->Wait();
            pthread_t tid;
            pthread_attr_t tattr;
            pthread_attr_init(&tattr);
            pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
            int error = pthread_create(&tid, &tattr, ThreadProc, &(*itr));
            if (error != 0)
            {
                printf("pthread_create error = %d\n", error);
                return 0;
            }
            printf("pthread [%d] created\n", i++);
        }
    }

    delete pSem;
    printf("Exit\n");

    return 0;
}

-- 
Woods
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette:  http://curl.haxx.se/mail/etiquette.html
Received on 2012-03-04