cURL / Mailing Lists / curl-library / Single Mail

curl-library

libcurl blocking in multi-mode when doing proxied https fetch from bad host

From: Adam D. Moss <adam_at_gimp.org>
Date: Mon, 22 Jan 2007 18:04:57 +0000

Hi all!

I'm having an unpleasant problem in a server where a particular type
of bogus https:// fetch is blocking (for 60 seconds!) despite my
using multi-mode, when connecting via a Squid proxy (the app needs
this proxy to function).

This is stalling the whole (single-threaded) server, which of course
isn't ideal. :)

I attach a minimal reproduction case. It's basically just minimal code
for a fetch from a bogus https://6.6.6.6 server with verbose mode turned
on and a little ASCII 'spinner' added to illustrate blocking (or lack
thereof).

If you run via a Squid proxy like so:
HTTPS_PROXY=localhost:1234 ./testnonblock5m
... then you should see that the program blocks on
'Establish HTTP proxy tunnel to 6.6.6.6:443' for about sixty seconds.

If you just run without a proxy, you should get 'Trying 6.6.6.6...'
without blocking (i.e. the spinner spins for sixty seconds while waiting
for the timeout).

This seems particular to https:// URLs. I'm mainly using libcurl
7.12.2; I've tried 7.16.0 but the problem persisted there also. If it's
relevant, the Squid being connected to is squid/2.5.STABLE9. I'm
guessing that this is a libcurl problem since even if Squid itself is
undesirably blocking, libcurl probably shouldn't be communicating with
it in a blocking manner.

I'd appreciate any ideas for workarounds or such!

Thanks,
--Adam

/* meant to demonstrate libcurl erroneously blocking while talking
   to a squid proxy. Set HTTPS_PROXY to your squid proxy to see the
   problem. */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* somewhat unix-specific */
#include <sys/time.h>
#include <unistd.h>

/* curl stuff */
#include <curl/curl.h>

static int debug_callback (CURL *ch, curl_infotype ci,
                           char *data, size_t datasize, void *user) {
        if (CURLINFO_TEXT == ci) {
                while (datasize--)
                        fprintf(stderr, "%c", *(data++));
                fprintf(stderr, "\n");
        }
        return 0;
}

int main(int argc, char **argv)
{
  CURL *http_handle;
  CURLM *multi_handle;
  CURLcode code;

  int still_running; /* keep number of running handles */

  http_handle = curl_easy_init();

  curl_easy_setopt(http_handle, CURLOPT_URL, "https://6.6.6.6");

  curl_easy_setopt(http_handle, CURLOPT_DEBUGFUNCTION, debug_callback);
  curl_easy_setopt(http_handle, CURLOPT_VERBOSE, 1);

  /* init a multi stack */
  multi_handle = curl_multi_init();

  /* add the individual transfers */
  curl_multi_add_handle(multi_handle, http_handle);

  /* show an on-screen spinner to indicate that we're (not) blocking. */
  while(CURLM_CALL_MULTI_PERFORM ==
        curl_multi_perform(multi_handle, &still_running) ||
        still_running)
  {
            static char spinner[] = "-\\|/";
            static int counter = 0;
            fprintf(stderr, "%c\b", spinner[counter]);
            counter = (counter + 1) % 4;
  }
  fprintf(stderr, "\nFinished.\n");

  curl_multi_cleanup(multi_handle);

  curl_easy_cleanup(http_handle);

  return 0;
}
Received on 2007-01-22