Last active
September 6, 2026 02:19
-
-
Save jay/12dfe34079d4a425efe8c5a43b40cdd6 to your computer and use it in GitHub Desktop.
Use libcurl to test multiplexing with CURLOPT_FORBID_REUSE.
This file contains hidden or 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
| /* Use libcurl to test multiplexing with CURLOPT_FORBID_REUSE. | |
| This repro shows that a multiplexed connection with transfers marked forbid | |
| reuse will continue to be used until no transfers are using the connection. | |
| AFAICT the last transfer to complete on the connection (ie connection has no | |
| other transfers using it) determines whether or not the connection is closed | |
| due to forbid reuse. This is discussed in the issue. | |
| Issue: "CURLOPT_FORBID_REUSE.md: has no effect on multiplexed transfers" | |
| https://github.com/curl/curl/pull/22833 | |
| gcc -o a multiplex_with_forbid_reuse.c `curl-config --cflags --libs` | |
| * Copyright (C) 2026 Jay Satiro <raysatiro@yahoo.com> | |
| https://curl.haxx.se/docs/copyright.html | |
| https://gist.github.com/jay/12dfe34079d4a425efe8c5a43b40cdd6 | |
| */ | |
| #include <stdio.h> | |
| #include <curl/curl.h> | |
| int main(void) | |
| { | |
| CURL *curl1, *curl2; | |
| CURLM *multi; | |
| int curl2_transfer_count; | |
| time_t start; | |
| curl_global_init(CURL_GLOBAL_ALL); | |
| curl1 = curl_easy_init(); | |
| curl_easy_setopt(curl1, CURLOPT_VERBOSE, 1L); | |
| curl_easy_setopt(curl1, CURLOPT_URL, "https://httpbin.org/delay/10"); | |
| curl_easy_setopt(curl1, CURLOPT_SSL_VERIFYHOST, 0L); | |
| curl_easy_setopt(curl1, CURLOPT_SSL_VERIFYPEER, 0L); | |
| curl_easy_setopt(curl1, CURLOPT_FORBID_REUSE, 1L); | |
| curl2 = curl_easy_init(); | |
| curl_easy_setopt(curl2, CURLOPT_VERBOSE, 1L); | |
| curl_easy_setopt(curl2, CURLOPT_URL, "https://httpbin.org/delay/1"); | |
| curl_easy_setopt(curl2, CURLOPT_SSL_VERIFYHOST, 0L); | |
| curl_easy_setopt(curl2, CURLOPT_SSL_VERIFYPEER, 0L); | |
| curl_easy_setopt(curl2, CURLOPT_FORBID_REUSE, 1L); | |
| curl2_transfer_count = 0; | |
| multi = curl_multi_init(); | |
| curl_multi_add_handle(multi, curl1); | |
| start = time(NULL); /* for testing purposes only, not monotonic */ | |
| for(;;) { | |
| struct CURLMsg *m; | |
| int still_running; | |
| if(curl_multi_poll(multi, NULL, 0, 1000, NULL) != CURLM_OK || | |
| curl_multi_perform(multi, &still_running) != CURLM_OK) | |
| break; | |
| if(!still_running) { | |
| if(curl2_transfer_count == 2) { | |
| /* run the fourth transfer. no other transfers are running. | |
| if the last transfer to complete on the connection (curl1 the 10 sec | |
| transfer) had CURLOPT_FORBID_REUSE on then the connection was closed | |
| and cannot be reused. we expect the fourth transfer will use a new | |
| connection in this case. */ | |
| curl_multi_remove_handle(multi, curl2); | |
| curl_multi_add_handle(multi, curl2); | |
| curl2_transfer_count++; | |
| } | |
| else | |
| break; | |
| } | |
| /* at around ~3 seconds run the second transfer. we expect this | |
| transfer will multiplex on the connection in use by curl1. */ | |
| if(curl2_transfer_count == 0 && (time(NULL) - start) >= 3) { | |
| fprintf(stderr, "3 seconds\n"); | |
| curl_multi_add_handle(multi, curl2); | |
| curl2_transfer_count = 1; | |
| } | |
| do { | |
| int msgq = 0; | |
| m = curl_multi_info_read(multi, &msgq); | |
| if(m && (m->msg == CURLMSG_DONE)) { | |
| CURL *e = m->easy_handle; | |
| if(e == curl2) { | |
| curl_multi_remove_handle(multi, e); | |
| if(curl2_transfer_count == 1) { | |
| /* the second transfer is done so run the third. we expect this | |
| transfer will multiplex on the connection in use by curl1. */ | |
| curl_multi_add_handle(multi, e); | |
| curl2_transfer_count++; | |
| } | |
| } | |
| } | |
| } while(m); | |
| } | |
| curl_multi_remove_handle(multi, curl1); | |
| curl_multi_remove_handle(multi, curl2); | |
| curl_easy_cleanup(curl1); | |
| curl_easy_cleanup(curl2); | |
| curl_multi_cleanup(multi); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment