From ef1e2fdaa4ea4d250d44487ec07563ad40e4ea85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20S=C3=B8rvig?= Date: Tue, 14 Nov 2023 12:23:31 +0100 Subject: [PATCH] wasm: manage wakeUp state correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were losing wakeups in cases where wakeUp() was called during processPostedEvents(), since wait() was unconditionally resetting m_wakeUpCalled. Fix this by setting m_wakeUpCalled to false before processing posted events, and then checking if it's still false before waiting. We don't hold the mutex while processing events so that can still race with wakeUp() calls, but this should now be harmless since at worst we'll spin and check for posted events one extra time before waiting. Pick-to: 6.5 Fixes: QTBUG-118416 Change-Id: I0183747c4d1f128bb6a46ba9c68f4eeb4d35a138 Reviewed-by: Mårten Nordheim Reviewed-by: Lorn Potter Reviewed-by: Jøger Hansegård Reviewed-by: Qt CI Bot (cherry picked from commit 55ce50cf4dd3c1d1dac8c5d938ed587be4d4b4cf) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/kernel/qeventdispatcher_wasm.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qeventdispatcher_wasm.cpp b/src/corelib/kernel/qeventdispatcher_wasm.cpp index db2a3bd1217..5e75ae2bd3a 100644 --- a/src/corelib/kernel/qeventdispatcher_wasm.cpp +++ b/src/corelib/kernel/qeventdispatcher_wasm.cpp @@ -223,6 +223,15 @@ bool QEventDispatcherWasm::processEvents(QEventLoop::ProcessEventsFlags flags) handleApplicationExec(); } +#if QT_CONFIG(thread) + { + // Reset wakeUp state: if wakeUp() was called at some point before + // this then processPostedEvents() below will service that call. + std::unique_lock lock(m_mutex); + m_wakeUpCalled = false; + } +#endif + processPostedEvents(); // The processPostedEvents() call above may process an event which deletes the @@ -413,7 +422,12 @@ bool QEventDispatcherWasm::wait(int timeout) if (isSecondaryThreadEventDispatcher()) { std::unique_lock lock(m_mutex); - m_wakeUpCalled = false; + // If wakeUp() was called there might be pending events in the event + // queue which should be processed. Don't block, instead return + // so that the event loop can spin and call processEvents() again. + if (m_wakeUpCalled) + return true; + auto wait_time = timeout > 0 ? timeout * 1ms : std::chrono::duration::max(); bool wakeUpCalled = m_moreEvents.wait_for(lock, wait_time, [=] { return m_wakeUpCalled; }); return wakeUpCalled;