cURL / Mailing Lists / curl-library / Single Mail

curl-library

crash using libcurl 7.19 multi interface

From: Hendrik Schober <spamtrap_at_gmx.de>
Date: Thu, 12 Mar 2009 16:53:29 +0100

Hi,

for days I've been trying to figure out a crash appearing in one of
our unit tests that uses libcurl's multi interface. The app sometimes
crashes in 'Curl_llist_insert_next()' ("llist.c"). This is on Win32
where I had it crashing in ~50% of all runs. (The program did crash
on Linux and OSX, too, but only very rarely and nobody investigated
whether it's even the same issue.)

I have boiled the problem down to the attached program. I would very
much appreciate it if someone could have a look at it and tell me
whether there's something stupid in there that causes the problem.
To me thsi very much looks like this must be a bug in libcurl, but
since I hadn't used libcurl before I was assigned the task to find
out about this, I might overlook something very stupid. If so, then
this might be the/an issue in the original code or I might have
introduced it when I tried to isolate the problem.

Thanks in advance!

Schobi

#include <iostream>
#include <string>
#include <sstream>

#include <curl/curl.h>

template< typename T >
std::string as_string(const T& obj)
{
    std::ostringstream oss;
    oss << obj;
    if( !oss ) {
        std::cerr << "Dang!\n";
        std::exit(42);
    }
    return oss.str();
}

void checkCurlStatus(CURLcode theStatusCode) {
    if (theStatusCode != CURLE_OK) {
        std::cerr << "Dang!\n";
        std::exit(1);
    }
}

void checkCurlStatus(CURLMcode theStatusCode) {
    if (theStatusCode != CURLM_OK && theStatusCode != CURLM_CALL_MULTI_PERFORM) {
        std::cerr << "Dang!\n";
        std::exit(2);
    }
}

int main(int /*argc*/, char** /*argv*/)
{
    const int runningCount = 1000;

    std::cout << curl_version();

    curl_global_init(CURL_GLOBAL_ALL);
    CURLM * myCurlMultiHandle = curl_multi_init();

    for( unsigned int u = 0; u< runningCount; ++u ) {
        const std::string myURL = "http://go.microsoft.com/fwlink/?LinkId="+as_string(10000+u);

        CURL * myCurlHandle = curl_easy_init();
        CURLcode myStatus = curl_easy_setopt(myCurlHandle, CURLOPT_URL, myURL.c_str());
        checkCurlStatus(myStatus);
        CURLMcode myMStatus = curl_multi_add_handle(myCurlMultiHandle, myCurlHandle);
        checkCurlStatus(myMStatus);
    }

    int myRunningCount = runningCount;
    std::cerr << "Handling " << myRunningCount << " requests...\n";
    while (myRunningCount) {
        CURLMcode myStatus;
        int myNewRunningCount;
        do {
            myStatus = curl_multi_perform(myCurlMultiHandle, &myNewRunningCount);
            checkCurlStatus(myStatus);

            CURLMsg * myMessage = 0;
            do {
                int myMessageCount = 0;
                myMessage = curl_multi_info_read(myCurlMultiHandle, &myMessageCount);
                if (myMessage) {
                    if (myMessage->msg == CURLMSG_DONE) {
                        std::cerr << "Dang!\n";
                        std::exit(3);
                    }
                    checkCurlStatus(myMessage->data.result);
                }
            } while (myMessage);
        } while (myStatus == CURLM_CALL_MULTI_PERFORM);
        if( myRunningCount != myNewRunningCount ) {
            std::cerr << "Request handled, " << myNewRunningCount << " requests left to handle.\n";
        }
        myRunningCount = myNewRunningCount;
    }
    std::cerr << "...curl finished handling requests.\n";

    return 0;
}
Received on 2009-03-12