From a607f8a20c6c5ac869598753097e3da06165cbd9 Mon Sep 17 00:00:00 2001
From: Jay Satiro <raysatiro@yahoo.com>
Date: Fri, 14 Nov 2014 03:59:46 -0500
Subject: [PATCH] examples: Don't call select() to sleep on windows

Windows does not support using select() for sleeping without a dummy
socket. Instead use Windows' Sleep() and sleep for 100ms which is the
minimum suggested value in the curl_multi_fdset() doc.

Prior to this change the multi examples would exit prematurely since
select() would error instead of sleeping when called without an fd.

Reported-by: Johan Lantz
Bug: http://curl.haxx.se/mail/lib-2014-11/0221.html
---
 docs/examples/fopen.c               | 31 ++++++++++++++++++++------
 docs/examples/imap-multi.c          | 34 ++++++++++++++++++++++-------
 docs/examples/multi-app.c           | 31 ++++++++++++++++++++------
 docs/examples/multi-debugcallback.c | 31 ++++++++++++++++++++------
 docs/examples/multi-double.c        | 31 ++++++++++++++++++++------
 docs/examples/multi-post.c          | 31 ++++++++++++++++++++------
 docs/examples/multi-single.c        | 31 ++++++++++++++++++++------
 docs/examples/pop3-multi.c          | 34 ++++++++++++++++++++++-------
 docs/examples/smtp-multi.c          | 34 ++++++++++++++++++++++-------
 9 files changed, 222 insertions(+), 66 deletions(-)

diff --git a/docs/examples/fopen.c b/docs/examples/fopen.c
index 6fe5c0f9fb..c26c0de04c 100644
--- a/docs/examples/fopen.c
+++ b/docs/examples/fopen.c
@@ -128,6 +128,7 @@ static int fill_buffer(URL_FILE *file, size_t want)
   fd_set fdexcep;
   struct timeval timeout;
   int rc;
+  CURLMcode mc; /* curl_multi_fdset() return code */
 
   /* only attempt to fill buffer if transactions still running and buffer
    * doesnt exceed required size already
@@ -158,15 +159,31 @@ static int fill_buffer(URL_FILE *file, size_t want)
     }
 
     /* get file descriptors from the transfers */
-    curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
+    mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
 
-    /* In a real-world program you OF COURSE check the return code of the
-       function calls.  On success, the value of maxfd is guaranteed to be
-       greater or equal than -1.  We call select(maxfd + 1, ...), specially
-       in case of (maxfd == -1), we call select(0, ...), which is basically
-       equal to sleep. */
+    if(mc != CURLM_OK)
+    {
+      fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
+      break;
+    }
 
-    rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    /* On success the value of maxfd is guaranteed to be >= -1. We call
+       select(maxfd + 1, ...); specially in case of (maxfd == -1) we call
+       select(0, ...), which is basically equal to sleeping the timeout. On
+       Windows we can't sleep via select without a dummy socket and instead
+       we Sleep() for 100ms which is the minimum suggested value in the
+       curl_multi_fdset() doc. */
+
+#ifdef _WIN32
+    if(maxfd == -1) {
+      Sleep(100);
+      rc = 0;
+    }
+    else
+#endif
+    {
+      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    }
 
     switch(rc) {
     case -1:
diff --git a/docs/examples/imap-multi.c b/docs/examples/imap-multi.c
index 601205a087..c8c67ff87b 100644
--- a/docs/examples/imap-multi.c
+++ b/docs/examples/imap-multi.c
@@ -88,6 +88,7 @@ int main(void)
     fd_set fdexcep;
     int maxfd = -1;
     int rc;
+    CURLMcode mc; /* curl_multi_fdset() return code */
 
     long curl_timeo = -1;
 
@@ -109,15 +110,32 @@ int main(void)
         timeout.tv_usec = (curl_timeo % 1000) * 1000;
     }
 
-    /* Get file descriptors from the transfers */
-    curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd);
+    /* get file descriptors from the transfers */
+    mc = curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd);
 
-    /* In a real-world program you OF COURSE check the return code of the
-       function calls.  On success, the value of maxfd is guaranteed to be
-       greater or equal than -1.  We call select(maxfd + 1, ...), specially in
-       case of (maxfd == -1), we call select(0, ...), which is basically equal
-       to sleep. */
-    rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
+    if(mc != CURLM_OK)
+    {
+      fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
+      break;
+    }
+
+    /* On success the value of maxfd is guaranteed to be >= -1. We call
+       select(maxfd + 1, ...); specially in case of (maxfd == -1) we call
+       select(0, ...), which is basically equal to sleeping the timeout. On
+       Windows we can't sleep via select without a dummy socket and instead
+       we Sleep() for 100ms which is the minimum suggested value in the
+       curl_multi_fdset() doc. */
+
+#ifdef _WIN32
+    if(maxfd == -1) {
+      Sleep(100);
+      rc = 0;
+    }
+    else
+#endif
+    {
+      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    }
 
     if(tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
       fprintf(stderr,
diff --git a/docs/examples/multi-app.c b/docs/examples/multi-app.c
index a5f71c5ac6..bf0f11ad5b 100644
--- a/docs/examples/multi-app.c
+++ b/docs/examples/multi-app.c
@@ -73,6 +73,7 @@ int main(void)
   do {
     struct timeval timeout;
     int rc; /* select() return code */
+    CURLMcode mc; /* curl_multi_fdset() return code */
 
     fd_set fdread;
     fd_set fdwrite;
@@ -99,15 +100,31 @@ int main(void)
     }
 
     /* get file descriptors from the transfers */
-    curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
+    mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
 
-    /* In a real-world program you OF COURSE check the return code of the
-       function calls.  On success, the value of maxfd is guaranteed to be
-       greater or equal than -1.  We call select(maxfd + 1, ...), specially in
-       case of (maxfd == -1), we call select(0, ...), which is basically equal
-       to sleep. */
+    if(mc != CURLM_OK)
+    {
+      fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
+      break;
+    }
 
-    rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    /* On success the value of maxfd is guaranteed to be >= -1. We call
+       select(maxfd + 1, ...); specially in case of (maxfd == -1) we call
+       select(0, ...), which is basically equal to sleeping the timeout. On
+       Windows we can't sleep via select without a dummy socket and instead
+       we Sleep() for 100ms which is the minimum suggested value in the
+       curl_multi_fdset() doc. */
+
+#ifdef _WIN32
+    if(maxfd == -1) {
+      Sleep(100);
+      rc = 0;
+    }
+    else
+#endif
+    {
+      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    }
 
     switch(rc) {
     case -1:
diff --git a/docs/examples/multi-debugcallback.c b/docs/examples/multi-debugcallback.c
index 8eedcee5b5..31dec5472a 100644
--- a/docs/examples/multi-debugcallback.c
+++ b/docs/examples/multi-debugcallback.c
@@ -147,6 +147,7 @@ int main(void)
   do {
     struct timeval timeout;
     int rc; /* select() return code */
+    CURLMcode mc; /* curl_multi_fdset() return code */
 
     fd_set fdread;
     fd_set fdwrite;
@@ -173,15 +174,31 @@ int main(void)
     }
 
     /* get file descriptors from the transfers */
-    curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
+    mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
 
-    /* In a real-world program you OF COURSE check the return code of the
-       function calls.  On success, the value of maxfd is guaranteed to be
-       greater or equal than -1.  We call select(maxfd + 1, ...), specially in
-       case of (maxfd == -1), we call select(0, ...), which is basically equal
-       to sleep. */
+    if(mc != CURLM_OK)
+    {
+      fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
+      break;
+    }
 
-    rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    /* On success the value of maxfd is guaranteed to be >= -1. We call
+       select(maxfd + 1, ...); specially in case of (maxfd == -1) we call
+       select(0, ...), which is basically equal to sleeping the timeout. On
+       Windows we can't sleep via select without a dummy socket and instead
+       we Sleep() for 100ms which is the minimum suggested value in the
+       curl_multi_fdset() doc. */
+
+#ifdef _WIN32
+    if(maxfd == -1) {
+      Sleep(100);
+      rc = 0;
+    }
+    else
+#endif
+    {
+      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    }
 
     switch(rc) {
     case -1:
diff --git a/docs/examples/multi-double.c b/docs/examples/multi-double.c
index 91422e6e2d..df0922a1c9 100644
--- a/docs/examples/multi-double.c
+++ b/docs/examples/multi-double.c
@@ -62,6 +62,7 @@ int main(void)
   do {
     struct timeval timeout;
     int rc; /* select() return code */
+    CURLMcode mc; /* curl_multi_fdset() return code */
 
     fd_set fdread;
     fd_set fdwrite;
@@ -88,15 +89,31 @@ int main(void)
     }
 
     /* get file descriptors from the transfers */
-    curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
+    mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
 
-    /* In a real-world program you OF COURSE check the return code of the
-       function calls.  On success, the value of maxfd is guaranteed to be
-       greater or equal than -1.  We call select(maxfd + 1, ...), specially in
-       case of (maxfd == -1), we call select(0, ...), which is basically equal
-       to sleep. */
+    if(mc != CURLM_OK)
+    {
+      fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
+      break;
+    }
 
-    rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    /* On success the value of maxfd is guaranteed to be >= -1. We call
+       select(maxfd + 1, ...); specially in case of (maxfd == -1) we call
+       select(0, ...), which is basically equal to sleeping the timeout. On
+       Windows we can't sleep via select without a dummy socket and instead
+       we Sleep() for 100ms which is the minimum suggested value in the
+       curl_multi_fdset() doc. */
+
+#ifdef _WIN32
+    if(maxfd == -1) {
+      Sleep(100);
+      rc = 0;
+    }
+    else
+#endif
+    {
+      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    }
 
     switch(rc) {
     case -1:
diff --git a/docs/examples/multi-post.c b/docs/examples/multi-post.c
index 965a2c3f69..a6cc8683cd 100644
--- a/docs/examples/multi-post.c
+++ b/docs/examples/multi-post.c
@@ -83,6 +83,7 @@ int main(void)
     do {
       struct timeval timeout;
       int rc; /* select() return code */
+      CURLMcode mc; /* curl_multi_fdset() return code */
 
       fd_set fdread;
       fd_set fdwrite;
@@ -109,15 +110,31 @@ int main(void)
       }
 
       /* get file descriptors from the transfers */
-      curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
+      mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
 
-      /* In a real-world program you OF COURSE check the return code of the
-         function calls.  On success, the value of maxfd is guaranteed to be
-         greater or equal than -1.  We call select(maxfd + 1, ...), specially in
-         case of (maxfd == -1), we call select(0, ...), which is basically equal
-         to sleep. */
+      if(mc != CURLM_OK)
+      {
+        fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
+        break;
+      }
 
-      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+      /* On success the value of maxfd is guaranteed to be >= -1. We call
+         select(maxfd + 1, ...); specially in case of (maxfd == -1) we call
+         select(0, ...), which is basically equal to sleeping the timeout. On
+         Windows we can't sleep via select without a dummy socket and instead
+         we Sleep() for 100ms which is the minimum suggested value in the
+         curl_multi_fdset() doc. */
+
+#ifdef _WIN32
+      if(maxfd == -1) {
+        Sleep(100);
+        rc = 0;
+      }
+      else
+#endif
+      {
+        rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+      }
 
       switch(rc) {
       case -1:
diff --git a/docs/examples/multi-single.c b/docs/examples/multi-single.c
index 37a01cd833..3d80c655fc 100644
--- a/docs/examples/multi-single.c
+++ b/docs/examples/multi-single.c
@@ -60,6 +60,7 @@ int main(void)
   do {
     struct timeval timeout;
     int rc; /* select() return code */
+    CURLMcode mc; /* curl_multi_fdset() return code */
 
     fd_set fdread;
     fd_set fdwrite;
@@ -86,15 +87,31 @@ int main(void)
     }
 
     /* get file descriptors from the transfers */
-    curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
+    mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
 
-    /* In a real-world program you OF COURSE check the return code of the
-       function calls.  On success, the value of maxfd is guaranteed to be
-       greater or equal than -1.  We call select(maxfd + 1, ...), specially in
-       case of (maxfd == -1), we call select(0, ...), which is basically equal
-       to sleep. */
+    if(mc != CURLM_OK)
+    {
+      fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
+      break;
+    }
 
-    rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    /* On success the value of maxfd is guaranteed to be >= -1. We call
+       select(maxfd + 1, ...); specially in case of (maxfd == -1) we call
+       select(0, ...), which is basically equal to sleeping the timeout. On
+       Windows we can't sleep via select without a dummy socket and instead
+       we Sleep() for 100ms which is the minimum suggested value in the
+       curl_multi_fdset() doc. */
+
+#ifdef _WIN32
+    if(maxfd == -1) {
+      Sleep(100);
+      rc = 0;
+    }
+    else
+#endif
+    {
+      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    }
 
     switch(rc) {
     case -1:
diff --git a/docs/examples/pop3-multi.c b/docs/examples/pop3-multi.c
index d14d1159b2..42142f9541 100644
--- a/docs/examples/pop3-multi.c
+++ b/docs/examples/pop3-multi.c
@@ -88,6 +88,7 @@ int main(void)
     fd_set fdexcep;
     int maxfd = -1;
     int rc;
+    CURLMcode mc; /* curl_multi_fdset() return code */
 
     long curl_timeo = -1;
 
@@ -109,15 +110,32 @@ int main(void)
         timeout.tv_usec = (curl_timeo % 1000) * 1000;
     }
 
-    /* Get file descriptors from the transfers */
-    curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd);
+    /* get file descriptors from the transfers */
+    mc = curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd);
 
-    /* In a real-world program you OF COURSE check the return code of the
-       function calls. On success, the value of maxfd is guaranteed to be
-       greater or equal than -1. We call select(maxfd + 1, ...), specially in
-       case of (maxfd == -1), we call select(0, ...), which is basically equal
-       to sleep. */
-    rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
+    if(mc != CURLM_OK)
+    {
+      fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
+      break;
+    }
+
+    /* On success the value of maxfd is guaranteed to be >= -1. We call
+       select(maxfd + 1, ...); specially in case of (maxfd == -1) we call
+       select(0, ...), which is basically equal to sleeping the timeout. On
+       Windows we can't sleep via select without a dummy socket and instead
+       we Sleep() for 100ms which is the minimum suggested value in the
+       curl_multi_fdset() doc. */
+
+#ifdef _WIN32
+    if(maxfd == -1) {
+      Sleep(100);
+      rc = 0;
+    }
+    else
+#endif
+    {
+      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    }
 
     if(tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
       fprintf(stderr,
diff --git a/docs/examples/smtp-multi.c b/docs/examples/smtp-multi.c
index 7f3d333dfe..998f69e3f5 100644
--- a/docs/examples/smtp-multi.c
+++ b/docs/examples/smtp-multi.c
@@ -155,6 +155,7 @@ int main(void)
     fd_set fdexcep;
     int maxfd = -1;
     int rc;
+    CURLMcode mc; /* curl_multi_fdset() return code */
 
     long curl_timeo = -1;
 
@@ -176,15 +177,32 @@ int main(void)
         timeout.tv_usec = (curl_timeo % 1000) * 1000;
     }
 
-    /* Get file descriptors from the transfers */
-    curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd);
+    /* get file descriptors from the transfers */
+    mc = curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd);
 
-    /* In a real-world program you OF COURSE check the return code of the
-       function calls.  On success, the value of maxfd is guaranteed to be
-       greater or equal than -1.  We call select(maxfd + 1, ...), specially in
-       case of (maxfd == -1), we call select(0, ...), which is basically equal
-       to sleep. */
-    rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    if(mc != CURLM_OK)
+    {
+      fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc);
+      break;
+    }
+
+    /* On success the value of maxfd is guaranteed to be >= -1. We call
+       select(maxfd + 1, ...); specially in case of (maxfd == -1) we call
+       select(0, ...), which is basically equal to sleeping the timeout. On
+       Windows we can't sleep via select without a dummy socket and instead
+       we Sleep() for 100ms which is the minimum suggested value in the
+       curl_multi_fdset() doc. */
+
+#ifdef _WIN32
+    if(maxfd == -1) {
+      Sleep(100);
+      rc = 0;
+    }
+    else
+#endif
+    {
+      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+    }
 
     if(tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) {
       fprintf(stderr,
-- 
GitLab