cURL / Mailing Lists / curl-library / Single Mail

curl-library

libcurl/openssl crashes when remote site partially goes down

From: Magnus Cederlöf <magnus.cederlof_at_gmail.com>
Date: Thu, 17 Jan 2008 13:21:15 +0100

Hello,

I have an application with libcurl/openssl that makes an HTTP POST to a
remote machine over HTTPS. This remote machine has stunnel + a special HTTP
server (without SSL support). If the HTTP server on the remote machine goes
down, but stunnel is still up and running, libcurl/openssl in my application
crashes (makes an exit).

I currently use libcurl version 7.17.1 and OpenSSL 0.9.8g on Ubuntu
7.10(but with libcurl and openssl fetched from the Hardy release). But
I have
tried it on older versions as well with the same result.

Maybe I have misconfigured libcurl or there is a bug somewhere. Anyway, I
really need to make libcurl to not make an exit when the remote HTTP server
goes down. Please help.

Here is a test program that reproduces the error:

--------------- curltest.cpp ------------------------

#include <string>
using std::string;
#include <curl/curl.h>

size_t write_libcurl_callback(void *ptr, size_t size, size_t nmemb, void
*response_ok)
{
    *((bool *)response_ok) = true;
    return size*nmemb;
}

int main(void)
{
    curl_global_init(CURL_GLOBAL_ALL);

    string send_data = "Hello!";

    while (true)
    {
        bool response_ok = false;
        CURLcode res;
        CURL *curl;

        curl = curl_easy_init();

        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
write_libcurl_callback);
        curl_easy_setopt(curl, CURLOPT_POST, true);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
        curl_easy_setopt(curl, CURLOPT_URL, "https://localhost:1500");
        curl_easy_setopt(curl, CURLOPT_READDATA, &send_data);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_ok);
        curl_easy_setopt(curl, CURLOPT_FAILONERROR, true);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE,
(curl_off_t)send_data.length());
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void
*)(send_data.c_str()));

        res = curl_easy_perform(curl);

        curl_easy_cleanup(curl);

        if (res == CURLE_OK && response_ok)
            printf("Curl OK\n");
        else
            printf("Curl Error\n");

        sleep(1);

    }
    return 0;
}
-------------------------------------------------

Compile and run:
> g++ -o curltest curltest.cpp -lcurl
> ./curltest

Notice that libcurl cannot connect to localhost:1500, but it still loops
around and retries every second.

Create a self signed test certificate for stunnel:
> openssl req -new -x509 -days 365 -nodes -config
/usr/share/doc/stunnel4/examples/stunnel.cnf -out stunnel.pem -keyout
stunnel.pem
> chmod 600 stunnel.pem

Start stunnel (forward from port 1500 to port 1600):
> sudo stunnel -p stunnel.pem -d 1500 -r 127.0.0.1:1600 -o stunnel.log

When stunnel has been started but there is nothing at the other end of the
SSL tunnel, libcurl/openssl will make an exit with the following printout:
* SSL read: error:00000000:lib(0):func(0):reason(0), errno 104
* Empty reply from server
* Connection #0 to host localhost left intact
* Server returned nothing (no headers, no data)
* Closing connection #0

Thanks in advance,
Magnus
Received on 2008-01-17