Pulled down latest sources as of the morning of 6/1/2017 (commit 5598b0bd63f690c151074494ce47ef872f004ab4)
libcurl/7.54.1-DEV
Ubuntu 16.10
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.
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
Thanks!
Most helpful comment
I'll see what I can do to bring this onto my agenda to work on next...