From 55ce50cf4dd3c1d1dac8c5d938ed587be4d4b4cf 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.6 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 --- 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 930ff068712..cc24b5ff7c1 100644 --- a/src/corelib/kernel/qeventdispatcher_wasm.cpp +++ b/src/corelib/kernel/qeventdispatcher_wasm.cpp @@ -290,6 +290,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 @@ -486,7 +495,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;