backend/wayland: handle display errors more gracefully

Previously, an error on the remote Wayland display would result in an
infinite loop priting:

    2020-01-09 13:39:03 - [wayland] Source dispatch function returned negative value!
    2020-01-09 13:39:03 - [wayland] This would previously accidentally suppress a follow-up dispatch

This happens when the remote compositor disconnects the client because
of a protocol error, for instance.

Handle wl_display_dispatch and wl_display_dispatch_pending returning -1
by terminating the local display and printing an error.
This commit is contained in:
Simon Ser 2020-01-09 13:52:36 +01:00 committed by Drew DeVault
parent e6fd880686
commit 802ef9da8a

View file

@ -34,25 +34,32 @@ static int dispatch_events(int fd, uint32_t mask, void *data) {
struct wlr_wl_backend *wl = data; struct wlr_wl_backend *wl = data;
if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) { if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) {
if (mask & WL_EVENT_ERROR) {
wlr_log(WLR_ERROR, "Failed to read from remote Wayland display");
}
wl_display_terminate(wl->local_display); wl_display_terminate(wl->local_display);
return 0; return 0;
} }
int count = 0;
if (mask & WL_EVENT_READABLE) { if (mask & WL_EVENT_READABLE) {
return wl_display_dispatch(wl->remote_display); count = wl_display_dispatch(wl->remote_display);
} }
if (mask & WL_EVENT_WRITABLE) { if (mask & WL_EVENT_WRITABLE) {
wl_display_flush(wl->remote_display); wl_display_flush(wl->remote_display);
return 0;
} }
if (mask == 0) { if (mask == 0) {
int count = wl_display_dispatch_pending(wl->remote_display); count = wl_display_dispatch_pending(wl->remote_display);
wl_display_flush(wl->remote_display); wl_display_flush(wl->remote_display);
return count;
} }
if (count < 0) {
wlr_log(WLR_ERROR, "Failed to dispatch remote Wayland display");
wl_display_terminate(wl->local_display);
return 0; return 0;
} }
return count;
}
static void xdg_wm_base_handle_ping(void *data, static void xdg_wm_base_handle_ping(void *data,
struct xdg_wm_base *base, uint32_t serial) { struct xdg_wm_base *base, uint32_t serial) {