diff --git a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h index 7beaae61b9..192cf6c1e1 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h +++ b/libs/sofia-sip/libsofia-sip-ua/su/sofia-sip/su_wait.h @@ -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 */ diff --git a/libs/sofia-sip/libsofia-sip-ua/su/su_wait.c b/libs/sofia-sip/libsofia-sip-ua/su/su_wait.c index a281470fcb..bda0a070f8 100644 --- a/libs/sofia-sip/libsofia-sip-ua/su/su_wait.c +++ b/libs/sofia-sip/libsofia-sip-ua/su/su_wait.c @@ -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;