Fixed bug 4689 - SDL fails to detect compositor shutdown on Wayland -- program keeps running
authorSam Lantinga <slouken@libsdl.org>
Mon, 05 Aug 2019 23:38:48 -0700
changeset 13000e6407f3ddba3
parent 12999 a7ca9815bc79
child 13001 1353fb9be62b
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:5cbf6472a916), Linux, can reproduce with sway, weston, and other Wayland oompositors.
src/video/wayland/SDL_waylandevents.c
src/video/wayland/SDL_waylandvideo.c
src/video/wayland/SDL_waylandvideo.h
     1.1 --- a/src/video/wayland/SDL_waylandevents.c	Sun Aug 04 00:01:38 2019 -0400
     1.2 +++ b/src/video/wayland/SDL_waylandevents.c	Mon Aug 05 23:38:48 2019 -0700
     1.3 @@ -178,15 +178,23 @@
     1.4  Wayland_PumpEvents(_THIS)
     1.5  {
     1.6      SDL_VideoData *d = _this->driverdata;
     1.7 +    int err;
     1.8  
     1.9      WAYLAND_wl_display_flush(d->display);
    1.10  
    1.11      if (SDL_IOReady(WAYLAND_wl_display_get_fd(d->display), SDL_FALSE, 0)) {
    1.12 -        WAYLAND_wl_display_dispatch(d->display);
    1.13 +        err = WAYLAND_wl_display_dispatch(d->display);
    1.14 +    } else {
    1.15 +        err = WAYLAND_wl_display_dispatch_pending(d->display);
    1.16      }
    1.17 -    else
    1.18 -    {
    1.19 -        WAYLAND_wl_display_dispatch_pending(d->display);
    1.20 +    if (err == -1 && !d->display_disconnected) {
    1.21 +        /* Something has failed with the Wayland connection -- for example,
    1.22 +         * the compositor may have shut down and closed its end of the socket,
    1.23 +         * or there is a library-specific error. No recovery is possible. */
    1.24 +        d->display_disconnected = 1;
    1.25 +        /* Only send a single quit message, as application shutdown might call
    1.26 +         * SDL_PumpEvents */
    1.27 +        SDL_SendQuit();
    1.28      }
    1.29  }
    1.30  
     2.1 --- a/src/video/wayland/SDL_waylandvideo.c	Sun Aug 04 00:01:38 2019 -0400
     2.2 +++ b/src/video/wayland/SDL_waylandvideo.c	Mon Aug 05 23:38:48 2019 -0700
     2.3 @@ -412,10 +412,9 @@
     2.4  int
     2.5  Wayland_VideoInit(_THIS)
     2.6  {
     2.7 -    SDL_VideoData *data = SDL_malloc(sizeof *data);
     2.8 +    SDL_VideoData *data = SDL_calloc(1, sizeof(*data));
     2.9      if (data == NULL)
    2.10          return SDL_OutOfMemory();
    2.11 -    memset(data, 0, sizeof *data);
    2.12  
    2.13      _this->driverdata = data;
    2.14  
     3.1 --- a/src/video/wayland/SDL_waylandvideo.h	Sun Aug 04 00:01:38 2019 -0400
     3.2 +++ b/src/video/wayland/SDL_waylandvideo.h	Mon Aug 05 23:38:48 2019 -0700
     3.3 @@ -48,6 +48,7 @@
     3.4  
     3.5  typedef struct {
     3.6      struct wl_display *display;
     3.7 +    int display_disconnected;
     3.8      struct wl_registry *registry;
     3.9      struct wl_compositor *compositor;
    3.10      struct wl_shm *shm;