diff options
author | Sheng Mao <shngmao@gmail.com> | 2020-11-13 22:34:46 -0700 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2020-11-30 23:11:04 +0100 |
commit | dbd1c8b047700bb6d0adae848d6cbb89fa2fcfff (patch) | |
tree | b653c7e6840113d9e0c2e54d0a32e6010c23da29 /src/plugins/platforms/xcb/qxcbconnection.cpp | |
parent | 92a57e0b016f811876ec1d62328ca8edfe452a3a (diff) |
Let QXcbConnection::getTimestamp properly exit when X server quits
QXcbConnection::getTimestamp uses dummy events to get timestamp from
X server. However, in some cases, X server shuts down while client tries
to get timestamp. In this case, QXcbConnection::getTimestamp keeps
getting null event and thus falls into indefinite loop.
This fix checks if xcb connection is still valid and use a special
xcb_timestamp_t value, CurrentTime (0L), as returned value.
CurrentTime should not be generated by X server and if getTimestamp
returns this value, it means an "exception" case is triggered.
This fix is introduced because in kwin_x11 (KDE project), X server can
exit on logout. kwin_x11 should handle disconnection from X server.
But the indefinite loop prevents kwin_x11 to process disconnection
event and therefore kwin_x11 cannot quit properly.
Fixes: QTBUG-88435
Pick-to: 5.12 5.15 6.0
Change-Id: Iaf7ef3f8a35fa8389d22a608e3c49041bf90e1b9
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Liang Qi <liang.qi@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbconnection.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 7435e124dc..1fcee9cd89 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -767,7 +767,10 @@ xcb_timestamp_t QXcbConnection::getTimestamp() xcb_generic_event_t *event = nullptr; - while (!event) { + // When disconnection is caused by X server, event will never be able to hold + // a valid pointer. isConnected(), which calls xcb_connection_has_error(), + // can handle this type of disconnection and properly quits the loop. + while (isConnected() && !event) { connection()->sync(); event = eventQueue()->peek([window, dummyAtom](xcb_generic_event_t *event, int type) { if (type != XCB_PROPERTY_NOTIFY) @@ -777,6 +780,14 @@ xcb_timestamp_t QXcbConnection::getTimestamp() }); } + if (!event) { + // https://www.x.org/releases/X11R7.7/doc/xproto/x11protocol.html#glossary + // > One timestamp value (named CurrentTime) is never generated by the + // > server. This value is reserved for use in requests to represent the + // > current server time. + return XCB_CURRENT_TIME; + } + xcb_property_notify_event_t *pn = reinterpret_cast<xcb_property_notify_event_t *>(event); xcb_timestamp_t timestamp = pn->time; free(event); |