From: Kevin Puetz PuetzKevinA@JohnDeere.com
There is a potential race condition for very small timeouts, as GetTickCount() could increment between `start_time` and the first update of `now`, causing the loop to immediately return timeout (RPC_S_CALLPENDING) without having even checked the handles.
The !message_loop else has no reason to do this; it only runs once, and then always exits via the `break` statement. The only `continue` that can cause the loop to iterate again is in the messages available branch In an the one-and-only call to WaitForMultipleObjectsEx should simply get the entire specified timeout.
The message_loop (STA) case has the same race condition, but it will be fixed in a later commit (after some preparatory refactoring). --- dlls/combase/combase.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index 0695bb77405..08a648451f0 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -2086,16 +2086,16 @@ HRESULT WINAPI CoWaitForMultipleHandles(DWORD flags, DWORD timeout, ULONG handle
while (TRUE) { - DWORD now = GetTickCount(), res; - - if (now - start_time > timeout) - { - hr = RPC_S_CALLPENDING; - break; - } - if (message_loop) { + DWORD now = GetTickCount(), res; + + if (now - start_time > timeout) + { + hr = RPC_S_CALLPENDING; + break; + } + TRACE("waiting for rpc completion or window message\n");
res = WAIT_TIMEOUT; @@ -2174,7 +2174,7 @@ HRESULT WINAPI CoWaitForMultipleHandles(DWORD flags, DWORD timeout, ULONG handle TRACE("Waiting for rpc completion\n");
res = WaitForMultipleObjectsEx(handle_count, handles, !!(flags & COWAIT_WAITALL), - (timeout == INFINITE) ? INFINITE : start_time + timeout - now, !!(flags & COWAIT_ALERTABLE)); + timeout, !!(flags & COWAIT_ALERTABLE)); }
switch (res)