Last active
January 8, 2019 19:13
-
-
Save jeroen/9ae92521411479fe58a19d2ce588dec9 to your computer and use it in GitHub Desktop.
libcurl fd bug
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Test program to verify that CURLMOPT_MAX_TOTAL_CONNECTIONS works as expected */ | |
#include <stdio.h> | |
#include <string.h> | |
#include <sys/time.h> | |
#include <unistd.h> | |
#include <math.h> | |
#include <curl/curl.h> | |
/* Configure max concurrent connections */ | |
#define MY_MAXCON 4 | |
/* Count open connections from the FD's */ | |
int print_multi_fd(CURLM *multi_handle){ | |
int max_fd, i, num_read = 0, num_write = 0, num_exc = 0; | |
fd_set read_fd_set, write_fd_set, exc_fd_set; | |
FD_ZERO(&read_fd_set); | |
FD_ZERO(&write_fd_set); | |
FD_ZERO(&exc_fd_set); | |
curl_multi_fdset(multi_handle, &read_fd_set, &write_fd_set, &exc_fd_set, &max_fd); | |
for (i = 0; i <= max_fd; i++){ | |
if (FD_ISSET(i, &read_fd_set)) num_read++; | |
if (FD_ISSET(i, &write_fd_set)) num_write++; | |
if (FD_ISSET(i, &exc_fd_set)) num_exc++; | |
} | |
fprintf(stderr, "Open Descriptors: READ %d, WRITE %d, EXC %d\n", num_read, num_write, num_exc); | |
return num_read; | |
} | |
int main(void){ | |
int ret = 0; | |
CURLM *multi_handle; | |
FILE *output = fopen("/dev/null", "w"); | |
curl_global_init(CURL_GLOBAL_DEFAULT); | |
/* init a multi stack */ | |
multi_handle = curl_multi_init(); | |
/* disable multiplexing so request count matches connection count */ | |
curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_NOTHING); | |
curl_multi_setopt(multi_handle, CURLMOPT_MAX_TOTAL_CONNECTIONS, (long) MY_MAXCON); | |
curl_multi_setopt(multi_handle, CURLMOPT_MAX_HOST_CONNECTIONS, (long) MY_MAXCON); | |
/* Add some requests */ | |
for(int i = 7; i >= 0; i--){ | |
char url[100] = ""; | |
sprintf(url, "https://eu.httpbin.org/delay/%d", i); | |
CURL *http_handle = curl_easy_init(); | |
curl_easy_setopt(http_handle, CURLOPT_URL, url); | |
curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, output); | |
curl_multi_add_handle(multi_handle, http_handle); | |
} | |
/* we start some action by calling perform right away */ | |
int running_handles = 0; /* keep number of running handles */ | |
do { | |
curl_multi_perform(multi_handle, &running_handles); | |
int msgq = 0; | |
do { | |
CURLMsg *m = curl_multi_info_read(multi_handle, &msgq); | |
if(m && (m->msg == CURLMSG_DONE)){ | |
long res_status; | |
curl_easy_getinfo(m->easy_handle, CURLINFO_RESPONSE_CODE, &res_status); | |
fprintf(stderr, "Req complete (HTTP %ld). Remaining: %d (max con: %d)\n", res_status, running_handles, MY_MAXCON); | |
int expected_con = fmin(running_handles, MY_MAXCON); | |
int num_read = print_multi_fd(multi_handle); | |
if(num_read != expected_con){ | |
fprintf(stderr, "FAIL: read_fd_set does not have expected length %d!\n", expected_con); | |
ret = 1; | |
} | |
curl_multi_remove_handle(multi_handle, m->easy_handle); | |
curl_easy_cleanup(m->easy_handle); | |
} | |
} while(msgq > 0); | |
} while(running_handles > 0); | |
curl_multi_cleanup(multi_handle); | |
curl_global_cleanup(); | |
if(!ret) | |
fprintf(stderr, "SUCCESS! All good!\n"); | |
return ret; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment