Home > Software design >  Libcurl multi retry mechanism skips over requesting data
Libcurl multi retry mechanism skips over requesting data

Time:11-12

I was making a small project where I wanted to get request multiple pieces of data at once using libcurl multi. Here is an example

CURL* array[] = {
    curl_easy_init(),
    curl_easy_init(),
    curl_easy_init()
};
CURLM* multi = curl_multi_init();

curl_easy_setopt(array[0], CURLOPT_URL, "https://www.example.com/");
curl_easy_setopt(array[1], CURLOPT_URL, "https://www.example.com/");
curl_easy_setopt(array[2], CURLOPT_URL, "https://americas.api.riotgames.com/riot/account/v1/accounts/by-puuid/Dxon1TsoGLOAvUykGYErrEPAT_U9YkQ_jNFZpRxYpfRFwnaYVFULVshNQnZapa4qR_pe5sSBn5MQvw");
for (int i = 0; i < 3; i  ) {
    curl_multi_add_handle(multi, array[i]);
}
int retry = 3;
loop:
int run = 1;
while (run) {
    CURLMcode mc = curl_multi_perform(multi, &run);
    if (mc == CURLM_OK) {
        mc = curl_multi_poll(multi, NULL, 0, 0, NULL);
    }
    if (mc != CURLM_OK) { // no else because catch both error possibilities
        exit(0); // error in curl multi
    }
}
CURLMsg *msg;
long rerun = 0;
int msgNum = 0;
while (msg = curl_multi_info_read(multi, &msgNum)) {
    if (msg->msg == CURLMSG_DONE) {
        if (msg->data.result != CURLE_OK) {
            puts("ERROR");
            exit(0); // error with transfer
        }
        long httpCode;
        curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &httpCode);
        if (httpCode == 200) {
            curl_multi_remove_handle(multi, msg->easy_handle);
        } else { // error with serverside
            rerun = httpCode;
            printf("\nError : %d\n", rerun);
        }
    } else {
        puts("ERROR");
        exit(0); // return num not compelted?
    }
}
puts("NExt");
if (rerun && --retry) {
    printf("%d - %d\n", retry, rerun);
    Sleep(1000);
    goto loop;
}
puts("Finisheed");

exit(0);

So first I make an array of curl easy handles, fill in all the info, and put them into curl_multi to perform a request. The code works fine IF I set all the URLs to "https://www.example.com/".

But in my case, I request from a site that might not work at all (the URL in array[2]) so I made a retry mechanism. If there's an httpCode that's not 200, then I redo the request but only with the ones that failed (I remove all the easy handles that completed sucessfully).

However, the retry mechanism only seems to retry once (when it should retry 3 times) and seems to skip the rest. This is the output I get

...stuff from example.com...
Error : 401
NExt
2 - 401
NExt
Finisheed

As you can see, it only retries once and then stops, but there's obviously an error because it doesn't print out the correct response.

Can anyone point me in the right direction?

CodePudding user response:

curl easy is not subject for rerun if it is kept in curl multi. Remove and re-add it again. Otherwise you get !run and !msg on the second iteration.

if (msg->msg == CURLMSG_DONE) {
    // ...
    curl_multi_remove_handle(multi, msg->easy_handle);
    long httpCode;
    curl_easy_getinfo(msg->easy_handle, CURLINFO_RESPONSE_CODE, &httpCode);
    if (httpCode != 200) {
        rerun = httpCode;
        printf("\nError : %d\n", rerun);
        curl_multi_add_handle(multi, msg->easy_handle);
    }
    // ...
}
  • Related