summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2026-01-04 09:38:16 +0100
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2026-01-04 09:38:16 +0100
commit357336bd40d868fd65e95c61d1adaf9de0fb7811 (patch)
treecf6687c5c75d9819420881edc1fae5c63094aa74 /src/drivers
parent62c2497ff5d8354485d1e105d02bba468f18aba4 (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.
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx44
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);
}