]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Workaround for Windows limit in su_wait
authorStefano Picerno <stefano.picerno@keytech.it>
Mon, 22 Sep 2014 14:00:26 +0000 (16:00 +0200)
committerStefano Picerno <stefano.picerno@gmail.com>
Tue, 23 Sep 2014 11:09:57 +0000 (13:09 +0200)
Windows has a 64 descriptor limit in WSAWaitForMultipleEvents system call.
Implemented some custom login in su_wait to work around this limitation.
Changed SU_WAIT_MAX from 64 to 0x7fffffff, like on other plaftorms.

libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h
libs/sofia-sip/libsofia-sip-ua/su/su_wait.c

index 7beaae61b9ec4a4ea0a292a55746c5651b30975c..192cf6c1e1b3c8ab7c820ebc0e41054c70d63713 100644 (file)
@@ -129,7 +129,7 @@ SOFIA_BEGIN_DECLS
 
 #define SU_WAIT_INIT    NULL
 
-#define SU_WAIT_MAX    (64)
+#define SU_WAIT_MAX    (0x7fffffff)
 
 #else
 /* If nothing works, try these */
index a281470fcbf7791f43b493cc9cd25eb0402a5963..bda0a070f8e4d49dbf016d8727fba0bf5938075b 100644 (file)
@@ -224,10 +224,37 @@ int su_wait(su_wait_t waits[], unsigned n, su_duration_t timeout)
 #if SU_HAVE_WINSOCK
   DWORD i;
 
-  if (n > 0)
-    i = WSAWaitForMultipleEvents(n, waits, FALSE, timeout, FALSE);
-  else
+  if (n > 0) {
+    #define WAIT_EVENT_BLOCK_SIZE WSA_MAXIMUM_WAIT_EVENTS
+
+    /* Handle at most WAIT_EVENT_BLOCK_SIZE wait objects at a time */
+    int blocks = (n + WAIT_EVENT_BLOCK_SIZE - 1) / WAIT_EVENT_BLOCK_SIZE;
+    int block_index = 0;
+    int first_wait_index = 0;
+    int millisec_per_block = timeout / blocks;
+
+    if (timeout > 0)
+      millisec_per_block  = max(1, millisec_per_block);
+
+    i = WSA_WAIT_TIMEOUT;
+    for(block_index = 0; block_index < blocks; block_index++,first_wait_index+=WAIT_EVENT_BLOCK_SIZE)
+    {
+      int remaining_blocks = n - block_index * WAIT_EVENT_BLOCK_SIZE;
+      int waits_in_current_block = min( WAIT_EVENT_BLOCK_SIZE, remaining_blocks );
+
+      i = WSAWaitForMultipleEvents(waits_in_current_block, waits + first_wait_index, FALSE, millisec_per_block, FALSE);
+      if (i != WSA_WAIT_TIMEOUT) {
+        /* Did not timeout, return something NOW, ignore remaining blocks */
+        if (i != WSA_WAIT_FAILED) {
+          /* Return the right index */
+          i += first_wait_index;
+        }
+        break;
+      }
+    }
+  } else {
     return Sleep(timeout), SU_WAIT_TIMEOUT;
+  }
 
   if (i == WSA_WAIT_TIMEOUT)
     return SU_WAIT_TIMEOUT;