diff --git a/src/core/unix/SDL_poll.c b/src/core/unix/SDL_poll.c index ec0a53381..dc0abd13f 100644 --- a/src/core/unix/SDL_poll.c +++ b/src/core/unix/SDL_poll.c @@ -83,7 +83,7 @@ SDL_IOReady(int fd, int flags, int timeoutMS) result = select(fd + 1, rfdp, wfdp, NULL, tvp); #endif /* HAVE_POLL */ - } while ( result < 0 && errno == EINTR ); + } while ( result < 0 && errno == EINTR && !(flags & SDL_IOR_NO_RETRY)); return result; } diff --git a/src/core/unix/SDL_poll.h b/src/core/unix/SDL_poll.h index 10497d181..7716eabb2 100644 --- a/src/core/unix/SDL_poll.h +++ b/src/core/unix/SDL_poll.h @@ -28,6 +28,7 @@ #define SDL_IOR_READ 0x1 #define SDL_IOR_WRITE 0x2 +#define SDL_IOR_NO_RETRY 0x4 extern int SDL_IOReady(int fd, int flags, int timeoutMS); diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index 51d3bd64f..36baef677 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -827,6 +827,7 @@ SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Event * event, a) All pending events are batch processed after waking up from a wait b) Waiting can be completely skipped if events are already available to be pumped c) Periodic processing that takes place in some platform PumpEvents() functions happens + d) Signals received in WaitEventTimeout() are turned into SDL events */ SDL_PumpEvents(); @@ -847,7 +848,6 @@ SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Event * event, } if (status > 0) { /* There is an event, we can return. */ - SDL_SendPendingSignalEvents(); /* in case we had a signal handler fire, etc. */ return 1; } /* No events found in the queue, call WaitEventTimeout to wait for an event. */ diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 607c6a2f7..f52b261fc 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -58,6 +58,7 @@ #include #include #include +#include #include #include #include "../../events/imKStoUCS.h" @@ -259,12 +260,14 @@ Wayland_WaitEventTimeout(_THIS, int timeout) /* wl_display_prepare_read() will return -1 if the default queue is not empty. * If the default queue is empty, it will prepare us for our SDL_IOReady() call. */ if (WAYLAND_wl_display_prepare_read(d->display) == 0) { - if (SDL_IOReady(WAYLAND_wl_display_get_fd(d->display), SDL_IOR_READ, timeout) > 0) { + /* Use SDL_IOR_NO_RETRY to ensure SIGINT will break us out of our wait */ + int err = SDL_IOReady(WAYLAND_wl_display_get_fd(d->display), SDL_IOR_READ | SDL_IOR_NO_RETRY, timeout); + if (err > 0) { /* There are new events available to read */ WAYLAND_wl_display_read_events(d->display); WAYLAND_wl_display_dispatch_pending(d->display); return 1; - } else { + } else if (err == 0) { /* No events available within the timeout */ WAYLAND_wl_display_cancel_read(d->display); @@ -277,6 +280,17 @@ Wayland_WaitEventTimeout(_THIS, int timeout) } return 0; + } else { + /* Error returned from poll()/select() */ + WAYLAND_wl_display_cancel_read(d->display); + + if (errno == EINTR) { + /* If the wait was interrupted by a signal, we may have generated a + * SDL_QUIT event. Let the caller know to call SDL_PumpEvents(). */ + return 1; + } else { + return err; + } } } else { /* We already had pending events */ diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index ccab1fb3a..664055614 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -1585,14 +1585,25 @@ X11_WaitEventTimeout(_THIS, int timeout) } else { return 0; } - } else if (timeout > 0) { - if (SDL_IOReady(ConnectionNumber(display), SDL_IOR_READ, timeout) > 0) { - X11_XNextEvent(display, &xevent); - } else { - return 0; - } } else { - X11_XNextEvent(display, &xevent); + /* Use SDL_IOR_NO_RETRY to ensure SIGINT will break us out of our wait */ + int err = SDL_IOReady(ConnectionNumber(display), SDL_IOR_READ | SDL_IOR_NO_RETRY, timeout); + if (err > 0) { + X11_XNextEvent(display, &xevent); + } else if (err == 0) { + /* Timeout */ + return 0; + } else { + /* Error returned from poll()/select() */ + + if (errno == EINTR) { + /* If the wait was interrupted by a signal, we may have generated a + * SDL_QUIT event. Let the caller know to call SDL_PumpEvents(). */ + return 1; + } else { + return err; + } + } } X11_DispatchEvent(_this, &xevent);