]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
multi: fix slow write/upload performance on Windows
authorMarc Hoersken <info@marc-hoersken.de>
Tue, 15 Dec 2020 06:22:13 +0000 (07:22 +0100)
committerMarc Hoersken <info@marc-hoersken.de>
Wed, 21 Apr 2021 18:32:24 +0000 (20:32 +0200)
Reset FD_WRITE by sending zero bytes which is permissible
and will be treated by implementations as successful send.

Without this we won't be notified in case a socket is still
writable if we already received such a notification and did
not send any data afterwards on the socket. This would lead
to waiting forever on a writable socket being writable again.

Assisted-by: Tommy Odom
Reviewed-by: Jay Satiro
Reviewed-by: Marcel Raad
Tested-by: tmkk on github
Bug: #6146
Closes #6245

lib/multi.c

index 38af89d0df5829f42c86ceac05da2f897fc8301b..d373ba9b3dfce85775e262919e8766811d80de41 100644 (file)
@@ -1174,24 +1174,27 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
         long mask = 0;
 #endif
         if(bitmap & GETSOCK_READSOCK(i)) {
+          s = sockbunch[i];
 #ifdef USE_WINSOCK
           mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
 #endif
-          ufds[nfds].fd = sockbunch[i];
+          ufds[nfds].fd = s;
           ufds[nfds].events = POLLIN;
           ++nfds;
-          s = sockbunch[i];
         }
         if(bitmap & GETSOCK_WRITESOCK(i)) {
+          s = sockbunch[i];
 #ifdef USE_WINSOCK
           mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
+          send(s, NULL, 0, 0); /* reset FD_WRITE */
 #endif
-          ufds[nfds].fd = sockbunch[i];
+          ufds[nfds].fd = s;
           ufds[nfds].events = POLLOUT;
           ++nfds;
-          s = sockbunch[i];
         }
+        /* s is only set if either being readable or writable is checked */
         if(s == CURL_SOCKET_BAD) {
+          /* break on entry not checked for being readable or writable */
           break;
         }
 #ifdef USE_WINSOCK
@@ -1215,8 +1218,10 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
       mask |= FD_READ|FD_ACCEPT|FD_CLOSE;
     if(extra_fds[i].events & CURL_WAIT_POLLPRI)
       mask |= FD_OOB;
-    if(extra_fds[i].events & CURL_WAIT_POLLOUT)
+    if(extra_fds[i].events & CURL_WAIT_POLLOUT) {
       mask |= FD_WRITE|FD_CONNECT|FD_CLOSE;
+      send(extra_fds[i].fd, NULL, 0, 0); /* reset FD_WRITE */
+    }
     if(WSAEventSelect(extra_fds[i].fd, multi->wsa_event, mask) != 0) {
       if(ufds_malloc)
         free(ufds);
@@ -1317,8 +1322,10 @@ static CURLMcode multi_wait(struct Curl_multi *multi,
               }
               WSAEventSelect(sockbunch[i], multi->wsa_event, 0);
             }
-            else
+            else {
+              /* break on entry not checked for being readable or writable */
               break;
+            }
           }
 
           data = data->next;