From afdb40af61a6aa12d97a8ad64c659c7cb65b1152 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 5 Aug 2019 23:38:48 -0700 Subject: [PATCH] Fixed bug 4689 - SDL fails to detect compositor shutdown on Wayland -- program keeps running M Stoeckl To reproduce: 1. Run any SDL-based program with a Wayland compositor, orphaning it so that it doesn't have an immediate parent process. (For example, from a terminal, running `supertux2 & disown`.) The program should use the wayland backend, i.e. by setting environment variable SDL_VIDEODRIVER=wayland. 2. Kill the compositor process. Results: - The SDL program will keep running. Expected results: - The SDL program should close. (What close should mean here, I'm not sure - is injecting an SDL_Quit the appropriate action when a video driver disconnects?) Build data: 2019-06-22, hg tip (12901:bf8d9d29cbf1), Linux, can reproduce with sway, weston, and other Wayland oompositors. --- src/video/wayland/SDL_waylandevents.c | 16 ++++++++++++---- src/video/wayland/SDL_waylandvideo.c | 3 +-- src/video/wayland/SDL_waylandvideo.h | 1 + 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index f9397fd0106a1..2f842e1948700 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -178,15 +178,23 @@ void Wayland_PumpEvents(_THIS) { SDL_VideoData *d = _this->driverdata; + int err; WAYLAND_wl_display_flush(d->display); if (SDL_IOReady(WAYLAND_wl_display_get_fd(d->display), SDL_FALSE, 0)) { - WAYLAND_wl_display_dispatch(d->display); + err = WAYLAND_wl_display_dispatch(d->display); + } else { + err = WAYLAND_wl_display_dispatch_pending(d->display); } - else - { - WAYLAND_wl_display_dispatch_pending(d->display); + if (err == -1 && !d->display_disconnected) { + /* Something has failed with the Wayland connection -- for example, + * the compositor may have shut down and closed its end of the socket, + * or there is a library-specific error. No recovery is possible. */ + d->display_disconnected = 1; + /* Only send a single quit message, as application shutdown might call + * SDL_PumpEvents */ + SDL_SendQuit(); } } diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index b128bb84bc2b8..c85860614b406 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -412,10 +412,9 @@ static const struct wl_registry_listener registry_listener = { int Wayland_VideoInit(_THIS) { - SDL_VideoData *data = SDL_malloc(sizeof *data); + SDL_VideoData *data = SDL_calloc(1, sizeof(*data)); if (data == NULL) return SDL_OutOfMemory(); - memset(data, 0, sizeof *data); _this->driverdata = data; diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h index b6499d000c204..127c8c0826b41 100644 --- a/src/video/wayland/SDL_waylandvideo.h +++ b/src/video/wayland/SDL_waylandvideo.h @@ -48,6 +48,7 @@ struct qt_windowmanager; typedef struct { struct wl_display *display; + int display_disconnected; struct wl_registry *registry; struct wl_compositor *compositor; struct wl_shm *shm;