curl_multi_perform hangs with slow/bad proxy server

Created on 1 Jun 2017  路  6Comments  路  Source: curl/curl

curl/libcurl version

Pulled down latest sources as of the morning of 6/1/2017 (commit 5598b0bd63f690c151074494ce47ef872f004ab4)
libcurl/7.54.1-DEV

operating system

Ubuntu 16.10

Issue

curl_multi_perform appears to hang when used with a slow/bad proxy server. My expectation was that when there was no work to perform, it would return, and then curl_multi_wait would actually do the waiting (with the supplied timeout to curl_multi_wait), but curl_multi_perform just doesn't return.

Repro:

// test.c
// compile with: gcc -o test test.c -lcurl
// run with: ./test

#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <curl/curl.h>

int main()
{
  curl_global_init(CURL_GLOBAL_ALL);
  CURLM* multi_handle = curl_multi_init();

  CURL* easy = curl_easy_init();
  curl_easy_setopt(easy, CURLOPT_VERBOSE, 1);
  curl_easy_setopt(easy, CURLOPT_URL, "https://api.ipify.org?format=json");

  // Good
  //curl_easy_setopt(easy, CURLOPT_PROXY, "http://103.254.16.21:8080");

  // BAD
  curl_easy_setopt(easy, CURLOPT_PROXY, "http://106.39.162.168:80");

  printf("Created request\n");
  curl_multi_add_handle(multi_handle, easy);
  printf("Added request\n");

  int still_running;
  do
  {
    printf("Calling curl_multi_perform\n");
    int numfds;
    CURLMcode mc = curl_multi_perform(multi_handle, &still_running);
    printf("Calling curl_multi_wait\n");
    curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds);
    printf("Called curl_multi_wait\n");
  } while(still_running);
  printf("Done\n");

  return 0;
}

When I run this with the "GOOD" proxy, I see:

Created request
Added request
Calling curl_multi_perform
* STATE: INIT => CONNECT handle 0x55f7d4ba0de8; line 1410 (connection #-5000)
* Rebuilt URL to: https://api.ipify.org/?format=json
* Added connection 0. The cache now contains 1 members
*   Trying 103.254.16.21...
* TCP_NODELAY set
* STATE: CONNECT => WAITCONNECT handle 0x55f7d4ba0de8; line 1462 (connection #0)
Calling curl_multi_wait
Called curl_multi_wait
Calling curl_multi_perform
Calling curl_multi_wait
Called curl_multi_wait
Calling curl_multi_perform
Calling curl_multi_wait
Called curl_multi_wait
Calling curl_multi_perform
Calling curl_multi_wait
Called curl_multi_wait
Calling curl_multi_perform
* Connected to 103.254.16.21 (103.254.16.21) port 8080 (#0)
* STATE: WAITCONNECT => WAITPROXYCONNECT handle 0x55f7d4ba0de8; line 1579 (connection #0)
* Marked for [keep alive]: HTTP default
* Establish HTTP proxy tunnel to api.ipify.org:443
> CONNECT api.ipify.org:443 HTTP/1.1
Host: api.ipify.org:443
Proxy-Connection: Keep-Alive

Calling curl_multi_wait
Called curl_multi_wait
Calling curl_multi_perform
* Read response immediately from proxy CONNECT
< HTTP/1.1 200 Connection established
<
* Proxy replied OK to CONNECT request
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: none
* STATE: WAITPROXYCONNECT => SENDPROTOCONNECT handle 0x55f7d4ba0de8; line 1558 (connection #0)
* STATE: SENDPROTOCONNECT => PROTOCONNECT handle 0x55f7d4ba0de8; line 1593 (connection #0)
Calling curl_multi_wait
Called curl_multi_wait
Calling curl_multi_perform
Calling curl_multi_wait
Called curl_multi_wait
Calling curl_multi_perform
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: OU=Domain Control Validated; OU=PositiveSSL; CN=api.ipify.org
*  start date: May 17 00:00:00 2017 GMT
*  expire date: May 17 23:59:59 2018 GMT
*  subjectAltName: host "api.ipify.org" matched cert's "api.ipify.org"
*  issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Domain Validation Secure Server CA
*  SSL certificate verify ok.
* STATE: PROTOCONNECT => DO handle 0x55f7d4ba0de8; line 1614 (connection #0)
> GET /?format=json HTTP/1.1
Host: api.ipify.org
Accept: */*

* STATE: DO => DO_DONE handle 0x55f7d4ba0de8; line 1676 (connection #0)
* STATE: DO_DONE => WAITPERFORM handle 0x55f7d4ba0de8; line 1801 (connection #0)
* STATE: WAITPERFORM => PERFORM handle 0x55f7d4ba0de8; line 1811 (connection #0)
Calling curl_multi_wait
Called curl_multi_wait
Calling curl_multi_perform
* HTTP 1.1 or later with persistent connection, pipelining supported
< HTTP/1.1 200 OK
* Server Cowboy is not blacklisted
< Server: Cowboy
< Connection: keep-alive
< Content-Type: application/json
< Date: Thu, 01 Jun 2017 13:18:01 GMT
< Content-Length: 22
< Via: 1.1 vegur
<
* STATE: PERFORM => DONE handle 0x55f7d4ba0de8; line 1981 (connection #0)
* multi_done
* Connection #0 to host 103.254.16.21 left intact
{"ip":"103.254.16.21"}Calling curl_multi_wait
Called curl_multi_wait
Done

but when I run this with the "BAD" proxy server, I get:

Created request
Added request
Calling curl_multi_perform
* STATE: INIT => CONNECT handle 0x55f1d8388de8; line 1410 (connection #-5000)
* Rebuilt URL to: https://api.ipify.org/?format=json
* Added connection 0. The cache now contains 1 members
*   Trying 106.39.162.168...
* TCP_NODELAY set
* STATE: CONNECT => WAITCONNECT handle 0x55f1d8388de8; line 1462 (connection #0)
Calling curl_multi_wait
Called curl_multi_wait
Calling curl_multi_perform
Calling curl_multi_wait
Called curl_multi_wait
Calling curl_multi_perform
* Connected to 106.39.162.168 (106.39.162.168) port 80 (#0)
* STATE: WAITCONNECT => WAITPROXYCONNECT handle 0x55f1d8388de8; line 1579 (connection #0)
* Marked for [keep alive]: HTTP default
* Establish HTTP proxy tunnel to api.ipify.org:443
> CONNECT api.ipify.org:443 HTTP/1.1
Host: api.ipify.org:443
Proxy-Connection: Keep-Alive

Calling curl_multi_wait
Called curl_multi_wait
Calling curl_multi_perform
Calling curl_multi_wait
Called curl_multi_wait
Calling curl_multi_perform
Calling curl_multi_wait
Called curl_multi_wait
Calling curl_multi_perform
* Read response immediately from proxy CONNECT

and then it just sits there.

connecting & proxies

Most helpful comment

I'll see what I can do to bring this onto my agenda to work on next...

All 6 comments

Yeah, this is unfortunately a known issue (since a long time): https://github.com/curl/curl/blob/master/docs/TODO#L407

Ah, ok, glad it's at least understood. Thanks.

I'll see what I can do to bring this onto my agenda to work on next...

WIP: #1547

1547 landed a while ago, this problem is no more!

Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Dirbaio picture Dirbaio  路  3Comments

alliquot picture alliquot  路  6Comments

gaul picture gaul  路  6Comments

jidanni picture jidanni  路  3Comments

MarcelRaad picture MarcelRaad  路  5Comments