wasm: manage wakeUp state correctly

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 <marten.nordheim@qt.io>
Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
(cherry picked from commit 55ce50cf4dd3c1d1dac8c5d938ed587be4d4b4cf)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Morten Sørvig 2023-11-14 12:23:31 +01:00 committed by Qt Cherry-pick Bot
parent 037aa20b37
commit ef1e2fdaa4

View File

@ -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<std::mutex> 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<std::mutex> 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<int, std::micro>::max();
bool wakeUpCalled = m_moreEvents.wait_for(lock, wait_time, [=] { return m_wakeUpCalled; });
return wakeUpCalled;