xcb: fix thread synchronization issue in QXcbEventQueue::waitForNewEvents()

This patch amends 730cbad882

The issue was that the event reader thread (QXcbEventQueue::run()) can enqueue
events sometime between GUI thread has last time peeked at the queue and before
it has called waitForNewEvents() and hence started waiting for more events (via
QWaitCondition). This scenario is even mentioned in the QWaitCondition documentation:

"[..] if some of the threads are still in do_something() when the key is pressed,
they won't be woken up (since they're not waiting on the condition variable) and
so the task will not be performed for that key press. [..]"

And if there are no more events on the X11 connection, the waitForNewEvents()
in QXcbClipboard::waitForClipboardEvent() would timeout.

Fixes: QTBUG-75319
Change-Id: I8990a2a0c00571dfc334fb57d616dee999042885
Reviewed-by: Igor Kushnir <igorkuo@gmail.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
bb10
Gatis Paeglis 2019-07-07 13:44:26 +02:00
parent 1e9355fdf2
commit a41701904e
1 changed files with 7 additions and 2 deletions

View File

@ -226,11 +226,13 @@ void QXcbEventQueue::run()
};
while (!m_closeConnectionDetected && (event = xcb_wait_for_event(connection))) {
m_newEventsMutex.lock();
enqueueEvent(event);
while (!m_closeConnectionDetected && (event = xcb_poll_for_queued_event(connection)))
enqueueEvent(event);
m_newEventsCondition.wakeOne();
m_newEventsMutex.unlock();
wakeUpDispatcher();
}
@ -350,9 +352,12 @@ bool QXcbEventQueue::peekEventQueue(PeekerCallback peeker, void *peekerData,
void QXcbEventQueue::waitForNewEvents(unsigned long time)
{
m_newEventsMutex.lock();
QMutexLocker locker(&m_newEventsMutex);
QXcbEventNode *tailBeforeFlush = m_flushedTail;
flushBufferedEvents();
if (tailBeforeFlush != m_flushedTail)
return;
m_newEventsCondition.wait(&m_newEventsMutex, time);
m_newEventsMutex.unlock();
}
void QXcbEventQueue::sendCloseConnectionEvent() const