From: Kevin Puetz <PuetzKevinA(a)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) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/969