From 5fb4279ec7199e291d9bf4c903f89395f60a3d31 Mon Sep 17 00:00:00 2001 From: Dirk Manske Date: Thu, 30 Sep 2010 11:33:33 +0200 Subject: [PATCH] multi & hiper examples: updates and cleanups all multi and hiper examples: * don't loop curl_multi_perform calls, that was <7.20.0 style, currently the exported multi functions will not return CURLM_CALL_MULTI_PERFORM all hiper examples: * renamed check_run_count to check_multi_info * don't compare current running handle count with previous value, this was the wrong way to check for finished requests, simply call curl_multi_info_read * it's also safe to call curl_multi_remove_handle inside the curl_multi_info_read loop. ghiper.c: * replaced curl_multi_socket (that function is marked as obsolete) calls with curl_multi_socket_action calls (as in hiperfifo.c and evhiperfifo.c) ghiper.c and evhiperfifo.c: * be smart as hiperfifo.c, don't do uncessary curl_multi_* calls in new_conn and main --- docs/examples/10-at-a-time.c | 2 +- docs/examples/evhiperfifo.c | 96 +++++++++----------------- docs/examples/fopen.c | 10 +-- docs/examples/ghiper.c | 101 +++++++++++----------------- docs/examples/hiperfifo.c | 76 ++++++++------------- docs/examples/multi-app.c | 6 +- docs/examples/multi-debugcallback.c | 6 +- docs/examples/multi-double.c | 6 +- docs/examples/multi-post.c | 6 +- docs/examples/multi-single.c | 6 +- 10 files changed, 113 insertions(+), 202 deletions(-) diff --git a/docs/examples/10-at-a-time.c b/docs/examples/10-at-a-time.c index 51326422c..b215cbfd4 100644 --- a/docs/examples/10-at-a-time.c +++ b/docs/examples/10-at-a-time.c @@ -119,7 +119,7 @@ int main(void) } while (U) { - while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(cm, &U)); + curl_multi_perform(cm, &U); if (U) { FD_ZERO(&R); diff --git a/docs/examples/evhiperfifo.c b/docs/examples/evhiperfifo.c index 8695ffabf..6cdccf839 100644 --- a/docs/examples/evhiperfifo.c +++ b/docs/examples/evhiperfifo.c @@ -68,7 +68,6 @@ typedef struct _GlobalInfo struct ev_io fifo_event; struct ev_timer timer_event; CURLM *multi; - int prev_running; int still_running; FILE* input; } GlobalInfo; @@ -122,7 +121,6 @@ static void mcode_or_die(const char *where, CURLMcode code) switch ( code ) { case CURLM_CALL_MULTI_PERFORM: s="CURLM_CALL_MULTI_PERFORM"; break; - case CURLM_OK: s="CURLM_OK"; break; case CURLM_BAD_HANDLE: s="CURLM_BAD_HANDLE"; break; case CURLM_BAD_EASY_HANDLE: s="CURLM_BAD_EASY_HANDLE"; break; case CURLM_OUT_OF_MEMORY: s="CURLM_OUT_OF_MEMORY"; break; @@ -144,54 +142,33 @@ static void mcode_or_die(const char *where, CURLMcode code) /* Check for completed transfers, and remove their easy handles */ -static void check_run_count(GlobalInfo *g) +static void check_multi_info(GlobalInfo *g) { - DPRINT("%s prev %i still %i\n", __PRETTY_FUNCTION__, - g->prev_running, g->still_running); - if ( g->prev_running > g->still_running ) - { - char *eff_url=NULL; - CURLMsg *msg; - int msgs_left; - ConnInfo *conn=NULL; - CURL*easy; - CURLcode res; + char *eff_url; + CURLMsg *msg; + int msgs_left; + ConnInfo *conn; + CURL *easy; + CURLcode res; - fprintf(MSG_OUT, "REMAINING: %d\n", g->still_running); - /* - I am still uncertain whether it is safe to remove an easy - handle from inside the curl_multi_info_read loop, so here I - will search for completed transfers in the inner "while" - loop, and then remove them in the outer "do-while" loop... - */ - do - { - easy=NULL; - while ( (msg = curl_multi_info_read(g->multi, &msgs_left)) ) - { - if ( msg->msg == CURLMSG_DONE ) - { - easy=msg->easy_handle; - res=msg->data.result; - } - - if ( easy ) - { - curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn); - curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &eff_url); - fprintf(MSG_OUT, "DONE: %s => (%d) %s\n", eff_url, res, conn->error); - curl_multi_remove_handle(g->multi, easy); - free(conn->url); - curl_easy_cleanup(easy); - free(conn); - } - } - } while ( easy ); + fprintf(MSG_OUT, "REMAINING: %d\n", g->still_running); + while ((msg = curl_multi_info_read(g->multi, &msgs_left))) { + if (msg->msg == CURLMSG_DONE) { + easy = msg->easy_handle; + res = msg->data.result; + curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn); + curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &eff_url); + fprintf(MSG_OUT, "DONE: %s => (%d) %s\n", eff_url, res, conn->error); + curl_multi_remove_handle(g->multi, easy); + free(conn->url); + curl_easy_cleanup(easy); + free(conn); + } } - g->prev_running = g->still_running; } + /* Called by libevent when we get action on a multi socket */ static void event_cb(EV_P_ struct ev_io *w, int revents) { @@ -201,12 +178,9 @@ static void event_cb(EV_P_ struct ev_io *w, int revents) int action = (revents&EV_READ?CURL_POLL_IN:0)| (revents&EV_WRITE?CURL_POLL_OUT:0); - do - { - rc = curl_multi_socket_action(g->multi, w->fd, action, &g->still_running); - } while ( rc == CURLM_CALL_MULTI_PERFORM ); - mcode_or_die("event_cb: curl_multi_socket", rc); - check_run_count(g); + rc = curl_multi_socket_action(g->multi, w->fd, action, &g->still_running); + mcode_or_die("event_cb: curl_multi_socket_action", rc); + check_multi_info(g); if ( g->still_running <= 0 ) { fprintf(MSG_OUT, "last transfer done, kill timeout\n"); @@ -222,12 +196,9 @@ static void timer_cb(EV_P_ struct ev_timer *w, int revents) GlobalInfo *g = (GlobalInfo *)w->data; CURLMcode rc; - do - { - rc = curl_multi_socket_action(g->multi, CURL_SOCKET_TIMEOUT, 0, &g->still_running); - } while ( rc == CURLM_CALL_MULTI_PERFORM ); - mcode_or_die("timer_cb: curl_multi_socket", rc); - check_run_count(g); + rc = curl_multi_socket_action(g->multi, CURL_SOCKET_TIMEOUT, 0, &g->still_running); + mcode_or_die("timer_cb: curl_multi_socket_action", rc); + check_multi_info(g); } /* Clean up the SockInfo structure */ @@ -364,11 +335,11 @@ static void new_conn(char *url, GlobalInfo *g ) fprintf(MSG_OUT, "Adding easy %p to multi %p (%s)\n", conn->easy, g->multi, url); - rc =curl_multi_add_handle(g->multi, conn->easy); + rc = curl_multi_add_handle(g->multi, conn->easy); mcode_or_die("new_conn: curl_multi_add_handle", rc); - mcode_or_die("new_conn: curl_multi_socket_all", rc); - check_run_count(g); + /* note that the add_handle() will set a time-out to trigger very soon so + that the necessary socket_action() call will be called by this app */ } /* This gets called whenever data is received from the fifo */ @@ -448,10 +419,9 @@ int main(int argc, char **argv) curl_multi_setopt(g.multi, CURLMOPT_SOCKETDATA, &g); curl_multi_setopt(g.multi, CURLMOPT_TIMERFUNCTION, multi_timer_cb); curl_multi_setopt(g.multi, CURLMOPT_TIMERDATA, &g); - do - { - rc = curl_multi_socket_all(g.multi, &g.still_running); - } while ( CURLM_CALL_MULTI_PERFORM == rc ); + + /* we don't call any curl_multi_socket*() function yet as we have no handles + added! */ ev_loop(g.loop, 0); curl_multi_cleanup(g.multi); diff --git a/docs/examples/fopen.c b/docs/examples/fopen.c index f21526b29..1310993bd 100644 --- a/docs/examples/fopen.c +++ b/docs/examples/fopen.c @@ -184,12 +184,7 @@ fill_buffer(URL_FILE *file,int want,int waittime) default: /* timeout or readable/writable sockets */ - /* note we *could* be more efficient and not wait for - * CURLM_CALL_MULTI_PERFORM to clear here and check it on re-entry - * but that gets messy */ - while(curl_multi_perform(multi_handle, &file->still_running) == - CURLM_CALL_MULTI_PERFORM); - + curl_multi_perform(multi_handle, &file->still_running); break; } } while(file->still_running && (file->buffer_pos < want)); @@ -260,8 +255,7 @@ url_fopen(const char *url,const char *operation) curl_multi_add_handle(multi_handle, file->handle.curl); /* lets start the fetch */ - while(curl_multi_perform(multi_handle, &file->still_running) == - CURLM_CALL_MULTI_PERFORM ); + curl_multi_perform(multi_handle, &file->still_running); if((file->buffer_pos == 0) && (!file->still_running)) { diff --git a/docs/examples/ghiper.c b/docs/examples/ghiper.c index 4f3913d71..ac11790cc 100644 --- a/docs/examples/ghiper.c +++ b/docs/examples/ghiper.c @@ -58,10 +58,7 @@ callback. typedef struct _GlobalInfo { CURLM *multi; guint timer_event; - int prev_running; int still_running; - int requested; /* count: curl_easy_init() */ - int completed; /* count: curl_easy_cleanup() */ } GlobalInfo; @@ -95,7 +92,6 @@ static void mcode_or_die(const char *where, CURLMcode code) { const char *s; switch (code) { case CURLM_CALL_MULTI_PERFORM: s="CURLM_CALL_MULTI_PERFORM"; break; - case CURLM_OK: s="CURLM_OK"; break; case CURLM_BAD_HANDLE: s="CURLM_BAD_HANDLE"; break; case CURLM_BAD_EASY_HANDLE: s="CURLM_BAD_EASY_HANDLE"; break; case CURLM_OUT_OF_MEMORY: s="CURLM_OUT_OF_MEMORY"; break; @@ -113,62 +109,43 @@ static void mcode_or_die(const char *where, CURLMcode code) { /* Check for completed transfers, and remove their easy handles */ -static void check_run_count(GlobalInfo *g) +static void check_multi_info(GlobalInfo *g) { - if (g->prev_running > g->still_running) { - char *eff_url=NULL; - CURLMsg *msg; - int msgs_left; - ConnInfo *conn=NULL; - CURL*easy; - CURLcode res; + char *eff_url; + CURLMsg *msg; + int msgs_left; + ConnInfo *conn; + CURL *easy; + CURLcode res; - MSG_OUT("REMAINING: %d\n", g->still_running); - /* - I am still uncertain whether it is safe to remove an easy handle - from inside the curl_multi_info_read loop, so here I will search - for completed transfers in the inner "while" loop, and then remove - them in the outer "do-while" loop... - */ - do { - easy=NULL; - while ((msg = curl_multi_info_read(g->multi, &msgs_left))) { - if (msg->msg == CURLMSG_DONE) { - easy=msg->easy_handle; - res=msg->data.result; - break; - } - } - if (easy) { - curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn); - curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &eff_url); - MSG_OUT("DONE: %s => (%d) %s\n", eff_url, res, conn->error); - curl_multi_remove_handle(g->multi, easy); - g_free(conn->url); - curl_easy_cleanup(easy); - g_free(conn); - g->completed++; - } - } while ( easy ); - MSG_OUT("Requested: %d Completed:%d\n", g->requested, g->completed); + MSG_OUT("REMAINING: %d\n", g->still_running); + while ((msg = curl_multi_info_read(g->multi, &msgs_left))) { + if (msg->msg == CURLMSG_DONE) { + easy = msg->easy_handle; + res = msg->data.result; + curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn); + curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &eff_url); + MSG_OUT("DONE: %s => (%d) %s\n", eff_url, res, conn->error); + curl_multi_remove_handle(g->multi, easy); + free(conn->url); + curl_easy_cleanup(easy); + free(conn); + } } - g->prev_running = g->still_running; } - /* Called by glib when our timeout expires */ static gboolean timer_cb(gpointer data) { GlobalInfo *g = (GlobalInfo *)data; CURLMcode rc; - do { - rc = curl_multi_socket(g->multi, CURL_SOCKET_TIMEOUT, &g->still_running); - } while (rc == CURLM_CALL_MULTI_PERFORM); - mcode_or_die("timer_cb: curl_multi_socket", rc); - check_run_count(g); + rc = curl_multi_socket_action(g->multi, + CURL_SOCKET_TIMEOUT, 0, &g->still_running); + mcode_or_die("timer_cb: curl_multi_socket_action", rc); + check_multi_info(g); return FALSE; } @@ -198,11 +175,15 @@ static gboolean event_cb(GIOChannel *ch, GIOCondition condition, gpointer data) GlobalInfo *g = (GlobalInfo*) data; CURLMcode rc; int fd=g_io_channel_unix_get_fd(ch); - do { - rc = curl_multi_socket(g->multi, fd, &g->still_running); - } while (rc == CURLM_CALL_MULTI_PERFORM); - mcode_or_die("event_cb: curl_multi_socket", rc); - check_run_count(g); + + int action = + (condition & G_IO_IN ? CURL_CSELECT_IN : 0) | + (condition & G_IO_OUT ? CURL_CSELECT_OUT : 0); + + rc = curl_multi_socket_action(g->multi, fd, action, &g->still_running); + mcode_or_die("event_cb: curl_multi_socket_action", rc); + + check_multi_info(g); if(g->still_running) { return TRUE; } else { @@ -338,12 +319,9 @@ static void new_conn(char *url, GlobalInfo *g ) MSG_OUT("Adding easy %p to multi %p (%s)\n", conn->easy, g->multi, url); rc =curl_multi_add_handle(g->multi, conn->easy); mcode_or_die("new_conn: curl_multi_add_handle", rc); - g->requested++; - do { - rc = curl_multi_socket_all(g->multi, &g->still_running); - } while (CURLM_CALL_MULTI_PERFORM == rc); - mcode_or_die("new_conn: curl_multi_socket_all", rc); - check_run_count(g); + + /* note that the add_handle() will set a time-out to trigger very soon so + that the necessary socket_action() call will be called by this app */ } @@ -451,9 +429,10 @@ int main(int argc, char **argv) curl_multi_setopt(g->multi, CURLMOPT_SOCKETDATA, g); curl_multi_setopt(g->multi, CURLMOPT_TIMERFUNCTION, update_timeout_cb); curl_multi_setopt(g->multi, CURLMOPT_TIMERDATA, g); - do { - rc = curl_multi_socket_all(g->multi, &g->still_running); - } while (CURLM_CALL_MULTI_PERFORM == rc); + + /* we don't call any curl_multi_socket*() function yet as we have no handles + added! */ + g_main_loop_run(gmain); curl_multi_cleanup(g->multi); return 0; diff --git a/docs/examples/hiperfifo.c b/docs/examples/hiperfifo.c index f5b422b4a..c9096871b 100644 --- a/docs/examples/hiperfifo.c +++ b/docs/examples/hiperfifo.c @@ -62,7 +62,6 @@ typedef struct _GlobalInfo { struct event fifo_event; struct event timer_event; CURLM *multi; - int prev_running; int still_running; FILE* input; } GlobalInfo; @@ -110,7 +109,6 @@ static void mcode_or_die(const char *where, CURLMcode code) const char *s; switch (code) { case CURLM_CALL_MULTI_PERFORM: s="CURLM_CALL_MULTI_PERFORM"; break; - case CURLM_OK: s="CURLM_OK"; break; case CURLM_BAD_HANDLE: s="CURLM_BAD_HANDLE"; break; case CURLM_BAD_EASY_HANDLE: s="CURLM_BAD_EASY_HANDLE"; break; case CURLM_OUT_OF_MEMORY: s="CURLM_OUT_OF_MEMORY"; break; @@ -132,44 +130,29 @@ static void mcode_or_die(const char *where, CURLMcode code) /* Check for completed transfers, and remove their easy handles */ -static void check_run_count(GlobalInfo *g) +static void check_multi_info(GlobalInfo *g) { - if (g->prev_running > g->still_running) { - char *eff_url=NULL; - CURLMsg *msg; - int msgs_left; - ConnInfo *conn=NULL; - CURL*easy; - CURLcode res; + char *eff_url; + CURLMsg *msg; + int msgs_left; + ConnInfo *conn; + CURL *easy; + CURLcode res; - fprintf(MSG_OUT, "REMAINING: %d\n", g->still_running); - /* - I am still uncertain whether it is safe to remove an easy handle - from inside the curl_multi_info_read loop, so here I will search - for completed transfers in the inner "while" loop, and then remove - them in the outer "do-while" loop... - */ - do { - easy=NULL; - while ((msg = curl_multi_info_read(g->multi, &msgs_left))) { - if (msg->msg == CURLMSG_DONE) { - easy=msg->easy_handle; - res=msg->data.result; - break; - } - } - if (easy) { - curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn); - curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &eff_url); - fprintf(MSG_OUT, "DONE: %s => (%d) %s\n", eff_url, res, conn->error); - curl_multi_remove_handle(g->multi, easy); - free(conn->url); - curl_easy_cleanup(easy); - free(conn); - } - } while ( easy ); + fprintf(MSG_OUT, "REMAINING: %d\n", g->still_running); + while ((msg = curl_multi_info_read(g->multi, &msgs_left))) { + if (msg->msg == CURLMSG_DONE) { + easy = msg->easy_handle; + res = msg->data.result; + curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn); + curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &eff_url); + fprintf(MSG_OUT, "DONE: %s => (%d) %s\n", eff_url, res, conn->error); + curl_multi_remove_handle(g->multi, easy); + free(conn->url); + curl_easy_cleanup(easy); + free(conn); + } } - g->prev_running = g->still_running; } @@ -181,16 +164,13 @@ static void event_cb(int fd, short kind, void *userp) CURLMcode rc; int action = - (kind&EV_READ?CURL_CSELECT_IN:0)| - (kind&EV_WRITE?CURL_CSELECT_OUT:0); - - do { - rc = curl_multi_socket_action(g->multi, fd, action, &g->still_running); - } while (rc == CURLM_CALL_MULTI_PERFORM); + (kind & EV_READ ? CURL_CSELECT_IN : 0) | + (kind & EV_WRITE ? CURL_CSELECT_OUT : 0); + rc = curl_multi_socket_action(g->multi, fd, action, &g->still_running); mcode_or_die("event_cb: curl_multi_socket_action", rc); - check_run_count(g); + check_multi_info(g); if ( g->still_running <= 0 ) { fprintf(MSG_OUT, "last transfer done, kill timeout\n"); if (evtimer_pending(&g->timer_event, NULL)) { @@ -209,12 +189,10 @@ static void timer_cb(int fd, short kind, void *userp) (void)fd; (void)kind; - do { - rc = curl_multi_socket_action(g->multi, + rc = curl_multi_socket_action(g->multi, CURL_SOCKET_TIMEOUT, 0, &g->still_running); - } while (rc == CURLM_CALL_MULTI_PERFORM); mcode_or_die("timer_cb: curl_multi_socket_action", rc); - check_run_count(g); + check_multi_info(g); } @@ -340,7 +318,7 @@ static void new_conn(char *url, GlobalInfo *g ) curl_easy_setopt(conn->easy, CURLOPT_PROGRESSDATA, conn); fprintf(MSG_OUT, "Adding easy %p to multi %p (%s)\n", conn->easy, g->multi, url); - rc =curl_multi_add_handle(g->multi, conn->easy); + rc = curl_multi_add_handle(g->multi, conn->easy); mcode_or_die("new_conn: curl_multi_add_handle", rc); /* note that the add_handle() will set a time-out to trigger very soon so diff --git a/docs/examples/multi-app.c b/docs/examples/multi-app.c index bcc9f393a..a5e85c42f 100644 --- a/docs/examples/multi-app.c +++ b/docs/examples/multi-app.c @@ -56,8 +56,7 @@ int main(int argc, char **argv) curl_multi_add_handle(multi_handle, handles[i]); /* we start some action by calling perform right away */ - while(CURLM_CALL_MULTI_PERFORM == - curl_multi_perform(multi_handle, &still_running)); + curl_multi_perform(multi_handle, &still_running); while(still_running) { struct timeval timeout; @@ -108,8 +107,7 @@ int main(int argc, char **argv) default: /* one or more of curl's file descriptors say there's data to read or write */ - while(CURLM_CALL_MULTI_PERFORM == - curl_multi_perform(multi_handle, &still_running)); + curl_multi_perform(multi_handle, &still_running); break; } } diff --git a/docs/examples/multi-debugcallback.c b/docs/examples/multi-debugcallback.c index fa90bbc48..6d647e66e 100644 --- a/docs/examples/multi-debugcallback.c +++ b/docs/examples/multi-debugcallback.c @@ -130,8 +130,7 @@ int main(int argc, char **argv) curl_multi_add_handle(multi_handle, http_handle); /* we start some action by calling perform right away */ - while(CURLM_CALL_MULTI_PERFORM == - curl_multi_perform(multi_handle, &still_running)); + curl_multi_perform(multi_handle, &still_running); while(still_running) { struct timeval timeout; @@ -181,8 +180,7 @@ int main(int argc, char **argv) case 0: default: /* timeout or readable/writable sockets */ - while(CURLM_CALL_MULTI_PERFORM == - curl_multi_perform(multi_handle, &still_running)); + curl_multi_perform(multi_handle, &still_running); break; } } diff --git a/docs/examples/multi-double.c b/docs/examples/multi-double.c index 8ac939a96..702f9ae3d 100644 --- a/docs/examples/multi-double.c +++ b/docs/examples/multi-double.c @@ -47,8 +47,7 @@ int main(int argc, char **argv) curl_multi_add_handle(multi_handle, http_handle2); /* we start some action by calling perform right away */ - while(CURLM_CALL_MULTI_PERFORM == - curl_multi_perform(multi_handle, &still_running)); + curl_multi_perform(multi_handle, &still_running); while(still_running) { struct timeval timeout; @@ -96,8 +95,7 @@ int main(int argc, char **argv) case 0: default: /* timeout or readable/writable sockets */ - while(CURLM_CALL_MULTI_PERFORM == - curl_multi_perform(multi_handle, &still_running)); + curl_multi_perform(multi_handle, &still_running); break; } } diff --git a/docs/examples/multi-post.c b/docs/examples/multi-post.c index df574ae72..8ab4bb904 100644 --- a/docs/examples/multi-post.c +++ b/docs/examples/multi-post.c @@ -67,8 +67,7 @@ int main(int argc, char *argv[]) curl_multi_add_handle(multi_handle, curl); - while(CURLM_CALL_MULTI_PERFORM == - curl_multi_perform(multi_handle, &still_running)); + curl_multi_perform(multi_handle, &still_running); while(still_running) { struct timeval timeout; @@ -118,8 +117,7 @@ int main(int argc, char *argv[]) default: /* timeout or readable/writable sockets */ printf("perform!\n"); - while(CURLM_CALL_MULTI_PERFORM == - curl_multi_perform(multi_handle, &still_running)); + curl_multi_perform(multi_handle, &still_running); printf("running: %d!\n", still_running); break; } diff --git a/docs/examples/multi-single.c b/docs/examples/multi-single.c index d3f9cfde0..fdcb5d8a8 100644 --- a/docs/examples/multi-single.c +++ b/docs/examples/multi-single.c @@ -41,8 +41,7 @@ int main(int argc, char **argv) curl_multi_add_handle(multi_handle, http_handle); /* we start some action by calling perform right away */ - while(CURLM_CALL_MULTI_PERFORM == - curl_multi_perform(multi_handle, &still_running)); + curl_multi_perform(multi_handle, &still_running); while(still_running) { struct timeval timeout; @@ -92,8 +91,7 @@ int main(int argc, char **argv) case 0: default: /* timeout or readable/writable sockets */ - while(CURLM_CALL_MULTI_PERFORM == - curl_multi_perform(multi_handle, &still_running)); + curl_multi_perform(multi_handle, &still_running); break; } }