From 6dfe941a7309a5af2088061ab0a745555f31b879 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 30 Sep 2021 18:31:39 +0100 Subject: [PATCH] Windows Pageant: fix hang due to queued callbacks. In the Windows Pageant message loop, we were alternating between MsgWaitForMultipleObjects with timeout=INFINITE, and run_toplevel_callbacks. But run_toplevel_callbacks doesn't loop until the callback queue is empty: it just runs at least one of the currently queued callbacks, so that some progress was made. So if two or more callbacks were queued, we'd leave the rest in the queue and go back into MsgWaitForMultipleObjects, which could hang indefinitely. (A very silly workaround was available: move the mouse over the Pageant systray icon! Every mouse event would terminate the wait and let you get one more iteration of run_toplevel_callbacks.) Now we do the same thing as in other main loops: if any further callbacks are pending, then we still run MsgWaitForMultipleObjects, but we do it with timeout=0 instead of timeout=INFINITE, so that we won't go back to a _blocking_ sleep until all callbacks have been serviced. --- windows/pageant.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/windows/pageant.c b/windows/pageant.c index c1bc55cc..0e25cc5d 100644 --- a/windows/pageant.c +++ b/windows/pageant.c @@ -1648,8 +1648,9 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) HandleWaitList *hwl = get_handle_wait_list(); + DWORD timeout = toplevel_callback_pending() ? 0 : INFINITE; n = MsgWaitForMultipleObjects(hwl->nhandles, hwl->handles, false, - INFINITE, QS_ALLINPUT); + timeout, QS_ALLINPUT); if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)hwl->nhandles) handle_wait_activate(hwl, n - WAIT_OBJECT_0);