diff -ur -x .svn -x *.patch -x *.lib current/docs/examples/fopen.c csapuntz/docs/examples/fopen.c
--- current/docs/examples/fopen.c	Wed Apr 29 14:58:45 2009
+++ csapuntz/docs/examples/fopen.c	Sun Sep  6 07:54:27 2009
@@ -158,7 +158,12 @@
         /* In a real-world program you OF COURSE check the return code of the
            function calls, *and* you make sure that maxfd is bigger than -1
            so that the call to select() below makes sense! */
-
+#ifdef _WIN32
+        if (maxfd == -1) {
+            Sleep(timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
+            rc = 0;
+        } else
+#endif
         rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
 
         switch(rc) {
diff -ur -x .svn -x *.patch -x *.lib current/docs/examples/multi-app.c csapuntz/docs/examples/multi-app.c
--- current/docs/examples/multi-app.c	Wed Apr 29 14:58:45 2009
+++ csapuntz/docs/examples/multi-app.c	Sun Sep  6 07:55:03 2009
@@ -83,7 +83,12 @@
     /* In a real-world program you OF COURSE check the return code of the
        function calls, *and* you make sure that maxfd is bigger than -1 so
        that the call to select() below makes sense! */
-
+#ifdef _WIN32
+    if (maxfd == -1) {
+        Sleep(timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
+        rc = 0;
+    } else
+#endif
     rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
 
     switch(rc) {
diff -ur -x .svn -x *.patch -x *.lib current/docs/examples/multi-double.c csapuntz/docs/examples/multi-double.c
--- current/docs/examples/multi-double.c	Wed Apr 29 14:58:45 2009
+++ csapuntz/docs/examples/multi-double.c	Sun Sep  6 07:55:39 2009
@@ -74,7 +74,12 @@
     /* In a real-world program you OF COURSE check the return code of the
        function calls, *and* you make sure that maxfd is bigger than -1 so
        that the call to select() below makes sense! */
-
+#ifdef _WIN32
+    if (maxfd == -1) {
+        Sleep(timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
+        rc = 0;
+    } else
+#endif
     rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
 
     switch(rc) {
diff -ur -x .svn -x *.patch -x *.lib current/docs/examples/multi-post.c csapuntz/docs/examples/multi-post.c
--- current/docs/examples/multi-post.c	Wed Apr 29 14:58:44 2009
+++ csapuntz/docs/examples/multi-post.c	Sun Sep  6 07:55:54 2009
@@ -94,7 +94,12 @@
       /* In a real-world program you OF COURSE check the return code of the
          function calls, *and* you make sure that maxfd is bigger than -1
          so that the call to select() below makes sense! */
-
+#ifdef _WIN32
+      if (maxfd == -1) {
+          Sleep(timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
+          rc = 0;
+      } else
+#endif
       rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
 
       switch(rc) {
diff -ur -x .svn -x *.patch -x *.lib current/docs/examples/multi-single.c csapuntz/docs/examples/multi-single.c
--- current/docs/examples/multi-single.c	Wed Apr 29 14:58:45 2009
+++ csapuntz/docs/examples/multi-single.c	Sun Sep  6 07:56:26 2009
@@ -68,7 +68,12 @@
     /* In a real-world program you OF COURSE check the return code of the
        function calls, *and* you make sure that maxfd is bigger than -1 so
        that the call to select() below makes sense! */
-
+#ifdef _WIN32
+    if (maxfd == -1) {
+        Sleep(timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
+        rc = 0;
+    } else
+#endif
     rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
 
     switch(rc) {
diff -ur -x .svn -x *.patch -x *.lib current/docs/libcurl/curl_multi_fdset.3 csapuntz/docs/libcurl/curl_multi_fdset.3
--- current/docs/libcurl/curl_multi_fdset.3	Wed Apr 29 14:58:46 2009
+++ csapuntz/docs/libcurl/curl_multi_fdset.3	Fri Aug  7 17:08:30 2009
@@ -25,6 +25,11 @@
 this function returns. Otherwise it will contain the higher descriptor number
 libcurl set.
 
+The function may return a \fImax_fd\fP of -1 even when there are operations
+still running. This means the curl library would like the caller to sleep
+before calling back. On Windows, since select() doesn't support a max_fd
+of -1, consider calling a sleep function like SleepEx instead.
+
 You should also be aware that when doing select(), you should consider using a
 rather small (single-digit number of seconds) timeout and call
 \fIcurl_multi_perform\fP regularly - even if no activity has been seen on the
diff -ur -x .svn -x *.patch -x *.lib current/docs/libcurl/curl_multi_setopt.3 csapuntz/docs/libcurl/curl_multi_setopt.3
--- current/docs/libcurl/curl_multi_setopt.3	Wed Apr 29 14:58:46 2009
+++ csapuntz/docs/libcurl/curl_multi_setopt.3	Fri Aug  7 17:18:24 2009
@@ -73,6 +73,18 @@
 you should instead use the \fICURLOPT_MAXCONNECTS\fP option.
 
 (Added in 7.16.3)
+.IP CURLMOPT_NODUMMY
+Pass a long. If non-zero, disable a workaround on Windows where the curl
+library passes back dummy descriptors so that select() operates like usleep().
+On Windows, select() returns an error if the descriptor set is empty, so
+dummy descriptors were used to simulate the usleep() like behavior of
+select() on Unix.  If non-zero, the application must be able to handle
+an empty descriptor set and call the appropriate Windows sleep function
+(e.g. SleepEx).
+
+The dummy descriptor trick does not seem to work on Windows XP SP3.
+
+
 .SH RETURNS
 The standard CURLMcode for multi interface error codes. Note that it returns a
 CURLM_UNKNOWN_OPTION if you try setting an option that this version of libcurl
diff -ur -x .svn -x *.patch -x *.lib current/docs/libcurl/curl_multi_socket_action.3 csapuntz/docs/libcurl/curl_multi_socket_action.3
--- current/docs/libcurl/curl_multi_socket_action.3	Sun Sep  6 07:24:57 2009
+++ csapuntz/docs/libcurl/curl_multi_socket_action.3	Sun Sep  6 07:38:00 2009
@@ -43,6 +43,10 @@
 \fIcurl_multi_timeout(3)\fP function to poll the value at any given time, but
 for an event-based system using the callback is far better than relying on
 polling the timeout value.
+
+Do not mix calls to \fIcurl_multi_socket_action(3)\fP and \fIcurl_multi_perform(3)\fP
+as \fIcurl_multi_perform(3)\fP does not call the socket and timer callbacks.
+
 .SH "CALLBACK DETAILS"
 
 The socket \fBcallback\fP function uses a prototype like this
@@ -86,6 +90,11 @@
 
 The \fIuserp\fP argument is a private pointer you have previously set with
 \fIcurl_multi_setopt(3)\fP and the CURLMOPT_SOCKETDATA option.
+
+It is possible for zero sockets to be registered on a multi handle. On Windows,
+be careful when calling select() as it does not support being passed all empty
+fd_sets.
+
 .SH "RETURN VALUE"
 CURLMcode type, general libcurl multi interface error code.
 
diff -ur -x .svn -x *.patch -x *.lib current/include/curl/multi.h csapuntz/include/curl/multi.h
--- current/include/curl/multi.h	Wed Apr 29 14:58:54 2009
+++ csapuntz/include/curl/multi.h	Fri Aug  7 14:36:21 2009
@@ -312,6 +312,9 @@
   /* maximum number of entries in the connection cache */
   CINIT(MAXCONNECTS, LONG, 6),
 
+  /* Windows - ok to return an empty fd set - caller will sleep */
+  CINIT(NODUMMY, LONG, 7),
+
   CURLMOPT_LASTENTRY /* the last unused */
 } CURLMoption;
 
diff -ur -x .svn -x *.patch -x *.lib current/lib/hostthre.c csapuntz/lib/hostthre.c
--- current/lib/hostthre.c	Sun Sep  6 07:25:08 2009
+++ csapuntz/lib/hostthre.c	Wed Aug 19 19:32:47 2009
@@ -104,6 +104,9 @@
   HANDLE thread_hnd;
   unsigned thread_id;
   DWORD  thread_status;
+  unsigned int poll_interval;
+  unsigned int interval_end;
+
   curl_socket_t dummy_sock;   /* dummy for Curl_resolv_fdset() */
   HANDLE mutex_waiting;  /* marks that we are still waiting for a resolve */
   HANDLE event_resolved; /* marks that the thread obtained the information */
@@ -503,7 +506,9 @@
    * should never become signalled for read/write since it's unbound but
    * Windows needs atleast 1 socket in select().
    */
-  td->dummy_sock = socket(AF_INET, SOCK_DGRAM, 0);
+  if (!Curl_multi_nodummy(conn->data->multi))
+    td->dummy_sock = socket(AF_INET, SOCK_DGRAM, 0);
+
   return TRUE;
 }
 
@@ -630,6 +635,32 @@
       return CURLE_COULDNT_RESOLVE_HOST;
     }
     *entry = conn->async.dns;
+  } else {
+    // poll for name lookup done with exponential backoff up to 250ms
+    struct thread_data *td = (struct thread_data*) conn->async.os_specific;
+    if (td) {
+      int elapsed;
+
+      elapsed = Curl_tvdiff(Curl_tvnow(), data->progress.t_startsingle);
+      if (elapsed < 0) {
+        elapsed = 0;
+      }
+
+      if (td->poll_interval == 0) {
+        /* Start at 1ms poll interval */
+        td->poll_interval = 1;
+      } else if (elapsed >= td->interval_end) {
+        /* Back-off exponentially if last interval expired  */
+        td->poll_interval *= 2;
+      }
+
+      if (td->poll_interval > 250)
+        td->poll_interval = 250;
+
+      td->interval_end = elapsed + td->poll_interval;
+
+      Curl_expire(conn->data, td->poll_interval);
+    }
   }
   return CURLE_OK;
 }
diff -ur -x .svn -x *.patch -x *.lib current/lib/multi.c csapuntz/lib/multi.c
--- current/lib/multi.c	Sun Sep  6 07:25:07 2009
+++ csapuntz/lib/multi.c	Fri Aug  7 16:58:19 2009
@@ -179,6 +179,10 @@
   void *timer_userp;
   struct timeval timer_lastcall; /* the fixed time for the timeout for the
                                     previous callback */
+
+  /* On Windows, whether the caller supports blank fd sets - i.e. calls
+     sleep instead of select*/
+  bool nodummy;
 };
 
 static bool multi_conn_using(struct Curl_multi *multi,
@@ -1968,6 +1972,9 @@
   case CURLMOPT_MAXCONNECTS:
     multi->maxconnects = va_arg(param, long);
     break;
+  case CURLMOPT_NODUMMY:
+    multi->nodummy = (bool)(0 != va_arg(param, long));
+    break;
   default:
     res = CURLM_UNKNOWN_OPTION;
     break;
@@ -2278,6 +2285,11 @@
   there->socketp = hashp;
 
   return CURLM_OK;
+}
+
+bool Curl_multi_nodummy(void * multi)
+{
+  return ((struct Curl_multi *)multi)->nodummy;
 }
 
 static bool multi_conn_using(struct Curl_multi *multi,
diff -ur -x .svn -x *.patch -x *.lib current/lib/multiif.h csapuntz/lib/multiif.h
--- current/lib/multiif.h	Wed Apr 29 14:58:43 2009
+++ csapuntz/lib/multiif.h	Fri Aug  7 14:28:46 2009
@@ -33,6 +33,8 @@
 bool Curl_multi_canPipeline(const struct Curl_multi* multi);
 void Curl_multi_handlePipeBreak(struct SessionHandle *data);
 
+bool Curl_multi_nodummy(void *multi);
+
 /* the write bits start at bit 16 for the *getsock() bitmap */
 #define GETSOCK_WRITEBITSTART 16
 

--- current/docs/examples/multi-debugcallback.c	Wed Apr 29 14:58:45 2009
+++ csapuntz/docs/examples/multi-debugcallback.c	Sun Sep  6 08:30:47 2009
@@ -156,7 +156,12 @@
     /* In a real-world program you OF COURSE check the return code of the
        function calls, *and* you make sure that maxfd is bigger than -1
        so that the call to select() below makes sense! */
-
+#ifdef _WIN32
+    if (maxfd == -1) {
+        Sleep(timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
+        rc = 0;
+    } else
+#endif
     rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
 
     switch(rc) {
