Jardanian
Jardanian

Reputation: 761

When does libcurl's curl_multi_perform start the transfer?

I am trying to understand the functionality of curl_multi_perform so that I can use it in my project. I found a sample code at https://gist.github.com/clemensg/4960504.

Below is the code where my doubt is:

for (i = 0; i < CNT; ++i) {
        init(cm, i); // this is setting options in curl easy handles.
    }

// I thought this statement will start transfer.
//A--    curl_multi_perform(cm, &still_running);
         sleep(5); // put this to check when transfer starts.

    do {
        int numfds=0;
        int res = curl_multi_wait(cm, NULL, 0, MAX_WAIT_MSECS, &numfds);
        if(res != CURLM_OK) {
            fprintf(stderr, "error: curl_multi_wait() returned %d\n", res);
            return EXIT_FAILURE;
        }
        /*
         if(!numfds) {
            fprintf(stderr, "error: curl_multi_wait() numfds=%d\n", numfds);
            return EXIT_FAILURE;
         }
        */
   //B--         curl_multi_perform(cm, &still_running);

    } while(still_running);

My understanding is that when curl_multi_perform is called the transfer starts but in the above code the curl_multi_perform at label A does not start the transfer. I checked in the wireshark logs. I see the first log output when the control moves past the sleep() statement.

I even tried below code:

for (i = 0; i < CNT; ++i) {
    init(cm, i); // this is setting options in curl easy handles.
    curl_multi_perform(cm, &still_running);
    sleep(5);
}

but, the result was the same. I didn't see any log in the wireshark while the control was in this loop, but, once I started seeing the logs in wireshark they were at 5 seconds interval.

Apart from these doubts, the other doubts I have are:

  1. Why there are two curl_multi_perform at label A & B?
  2. Can I call curl_multi_perform multiple times while adding handles in between the calls?

Help appreciated. Thanks

Upvotes: 1

Views: 1752

Answers (1)

Daniel Stenberg
Daniel Stenberg

Reputation: 58114

curl_multi_perform works in a non-blocking way. It'll do as much as it can without blocking and then it returns, expecting to get called again when needed. The first call is thus most likely to start resolving the name used in the URL, and then perhaps the second or third call starts the actual transfer or something. It is designed so that an application shouldn't have to care about which exact function call number that does it.

Then you keep calling it until all the transfers are completed.

I've tried to explain this concept in a chapter in the "everything curl" book: Driving with the "multi" interface

Upvotes: 2

Related Questions