diff options
| author | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2026-01-04 09:38:16 +0100 |
|---|---|---|
| committer | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2026-01-04 09:38:16 +0100 |
| commit | 357336bd40d868fd65e95c61d1adaf9de0fb7811 (patch) | |
| tree | cf6687c5c75d9819420881edc1fae5c63094aa74 | |
| parent | 62c2497ff5d8354485d1e105d02bba468f18aba4 (diff) | |
Fix "Wayland's wl_display_dispatch() can block a Vulkan application" (#1354)
This rewriting of the FLTK callback function that runs when there are data available
for reading in the socket connecting the app and the Wayland compositor is meant to
facilitate the integration of Vulkan.
This rewriting reproduces the recommended code to read from the socket
documented in Wayland function wl_display_prepare_read_queue() when several threads
potentially read from the socket.
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx index 215f3650d..a0911cb51 100644 --- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx @@ -1368,24 +1368,38 @@ static const struct wl_registry_listener registry_listener = { extern int fl_send_system_handlers(void *); -static void wayland_socket_callback(int fd, struct wl_display *display) { +static void wayland_socket_callback(int fd, struct wl_display *display) +{ if (fl_send_system_handlers(NULL)) return; + if (wl_display_prepare_read(display) == -1) { + wl_display_dispatch_pending(display); + return; + } + wl_display_flush(display); struct pollfd fds = (struct pollfd) { fd, POLLIN, 0 }; - do { - if (wl_display_dispatch(display) == -1) { - int err = wl_display_get_error(display); - if (err == EPROTO) { - const struct wl_interface *interface; - int code = wl_display_get_protocol_error(display, &interface, NULL); - Fl::fatal("Fatal error no %d in Wayland protocol: %s", code, - (interface ? interface->name : "unknown") ); - } else { - Fl::fatal("Fatal error while communicating with the Wayland server: %s", - strerror(errno)); - } - } + if (poll(&fds, 1, 0) <= 0) { + wl_display_cancel_read(display); + return; + } + if (fds.revents & (POLLERR | POLLHUP)) { + wl_display_cancel_read(display); + goto fatal; + } + if (wl_display_read_events(display) == -1) + goto fatal; + if (wl_display_dispatch_pending(display) == -1) + goto fatal; + return; +fatal: + if (wl_display_get_error(display) == EPROTO) { + const struct wl_interface *interface; + int code = wl_display_get_protocol_error(display, &interface, NULL); + Fl::fatal("Fatal error %d in Wayland protocol: %s", + code, (interface ? interface->name : "unknown") ); + } else { + Fl::fatal("Fatal error while communicating with Wayland server: %s", + strerror(errno)); } - while (poll(&fds, 1, 0) > 0); } |
