-
-
Notifications
You must be signed in to change notification settings - Fork 6.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
curl_multi_fdset() returns a write fd instead of read fd #14915
Comments
您好,我已经收悉您的邮件,随后将回复您!
祝您身体健康,工作顺利!
|
@thanhphamhuu , could you provide more details and attach a minimal sample that shows the problem? I've tried on version #include <cstdio>
#include <curl/curl.h>
void print_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(stdout, "FDs: read: %d, write: %d, exc: %d\n", num_read, num_write,
num_exc);
}
int main(int argc, char *argv[]) {
FILE *output = fopen("/dev/null", "w");
CURLMsg *msg = NULL;
curl_global_init(CURL_GLOBAL_DEFAULT);
CURLM *multi_handle = curl_multi_init();
curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_NOTHING);
curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
fprintf(stdout, "Version libcurl: %s\n", data->version);
for (int i = 0; i < 10; i++) {
CURL *easy_handle = curl_easy_init();
curl_easy_setopt(easy_handle, CURLOPT_URL, "https://example.com");
curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, output);
curl_multi_add_handle(multi_handle, easy_handle);
}
int running_handles = 0;
do {
curl_multi_perform(multi_handle, &running_handles);
int msgs_left = 0;
while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
if (msg && (msg->msg == CURLMSG_DONE)) {
long res_status;
curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE,
&res_status);
fprintf(stdout, "Request complete (HTTP code: %ld), remaining: %d\n",
res_status, running_handles);
print_fd(multi_handle);
curl_multi_remove_handle(multi_handle, msg->easy_handle);
curl_easy_cleanup(msg->easy_handle);
}
}
} while (running_handles);
curl_multi_cleanup(multi_handle);
curl_global_cleanup();
return 0;
}
|
@bagder, sorry, i am late reply
Issue:
Q&A:
? |
Why do you consider this is an error? |
@bagder , I don't consider it a bug but since it returns us fdwrite so not satisfying this condition causes my system to loop infinitely in while(true) loop on version 8.4.0 which is not the case on version 7.81.0 |
Your assumption that a transfer only progresses on being in |
That assumption is your error. |
|
can you explain more? i am handling it by calling curl_multi_perform multiple times. Is it ok? |
libcurl exports knowledge about what to wait for in this function - it does not say that it will provide those sockets and bits in a specific order or that it will ask for a readable socket first. Presumably, we refactored something between those two versions that changes how it behaves for you. Possibly your old version could still end up in that situation, just under different conditions. It could also be because you built the two different versions differently. |
Your code checks that In newer curl versions, the settings in The correct way to use the curl API is to run |
And only call it once, independently of how many sockets that are readable and writable. Then loop. |
The multi-double example shows how this can be done a little simpler. |
@bagder @icing , so what should we do to best fix this bug. can we use curl_multi_wait or curl_multi_poll ? to fix this error? |
Maybe take another loop over the documentation and existing examples that show this. |
I did this
my system makes a request to the center to verify the PIN code via HTTP.
we use
+mc = curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
+ret = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
+CURLMcode mc = curl_multi_perform(multi, &still_running);
in version V7.81.0 our system was fine but in version V8.4.0 the system had a problem.
the problem we encountered was that curl_multi_fdset returned fdwrite instead of fdread
I tested on version from V7.81.0 - V7.86.0 it still returned fdread but from version V7.87.0 our system had an error.
I expected the following
mc = curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
returns fdread on version v8.4.0
curl/libcurl version
curl 8.4.0
operating system
Linux
The text was updated successfully, but these errors were encountered: