mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
wayland: wl_display_flush() never blocks
Since it doesn't block, we need to detect EAGAIN failures and ensure we actually flush everything. If we don't, we sooner or later end up in a wayland client library call that aborts due to the socket buffer being full. Ideally, we'd simply enable POLLOUT in the FDM. However, we cannot write *anything* to the wayland socket until we've actually managed to send everything. This means enabling POLLOUT in the FDM wont work since we may (*will*) end up trying to write more data to it before we've flushed it. So, add a wrapper function, wayl_flush(), that acts as a blocking variant of wl_display_flush(), by detecting EAGAIN failiures and calling poll() itself, on the wayland socket only, until all data has been sent.
This commit is contained in:
parent
2128d5912f
commit
abc36d8f09
3 changed files with 46 additions and 4 deletions
2
render.c
2
render.c
|
|
@ -867,7 +867,7 @@ grid_render(struct terminal *term)
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_surface_commit(term->window->surface);
|
wl_surface_commit(term->window->surface);
|
||||||
wl_display_flush(term->wl->display);
|
wayl_flush(term->wl);
|
||||||
|
|
||||||
#if TIME_FRAME_RENDERING
|
#if TIME_FRAME_RENDERING
|
||||||
struct timeval end_time;
|
struct timeval end_time;
|
||||||
|
|
|
||||||
47
wayland.c
47
wayland.c
|
|
@ -4,6 +4,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
#include <sys/timerfd.h>
|
#include <sys/timerfd.h>
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
|
|
@ -573,7 +574,7 @@ fdm_wayl(struct fdm *fdm, int fd, int events, void *data)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_display_flush(wayl->display);
|
wayl_flush(wayl);
|
||||||
return event_count != -1;
|
return event_count != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -983,7 +984,7 @@ wayl_cursor_set(struct wayland *wayl, const struct terminal *term)
|
||||||
|
|
||||||
wl_surface_set_buffer_scale(wayl->pointer.surface, scale);
|
wl_surface_set_buffer_scale(wayl->pointer.surface, scale);
|
||||||
wl_surface_commit(wayl->pointer.surface);
|
wl_surface_commit(wayl->pointer.surface);
|
||||||
wl_display_flush(wayl->display);
|
wayl_flush(wayl);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1029,6 +1030,46 @@ wayl_terminal_from_surface(struct wayland *wayl, struct wl_surface *surface)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
wayl_flush(struct wayland *wayl)
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
int r = wl_display_flush(wayl->display);
|
||||||
|
if (r >= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (errno != EAGAIN) {
|
||||||
|
LOG_ERRNO("failed to flush wayland socket");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pollfd fds[] = {
|
||||||
|
{.fd = wl_display_get_fd(wayl->display), .events = POLLOUT}
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
r = poll(fds, sizeof(fds) / sizeof(fds[0]), -1);
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
LOG_ERRNO("failed to poll");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fds[0].revents & POLLHUP)
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert(fds[0].revents & POLLOUT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wayl_roundtrip(struct wayland *wayl)
|
wayl_roundtrip(struct wayland *wayl)
|
||||||
{
|
{
|
||||||
|
|
@ -1037,5 +1078,5 @@ wayl_roundtrip(struct wayland *wayl)
|
||||||
|
|
||||||
while (wl_display_prepare_read(wayl->display) != 0)
|
while (wl_display_prepare_read(wayl->display) != 0)
|
||||||
wl_display_dispatch_pending(wayl->display);
|
wl_display_dispatch_pending(wayl->display);
|
||||||
wl_display_flush(wayl->display);
|
wayl_flush(wayl);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,7 @@ struct wayland {
|
||||||
struct wayland *wayl_init(const struct config *conf, struct fdm *fdm);
|
struct wayland *wayl_init(const struct config *conf, struct fdm *fdm);
|
||||||
void wayl_destroy(struct wayland *wayl);
|
void wayl_destroy(struct wayland *wayl);
|
||||||
|
|
||||||
|
void wayl_flush(struct wayland *wayl);
|
||||||
void wayl_roundtrip(struct wayland *wayl);
|
void wayl_roundtrip(struct wayland *wayl);
|
||||||
|
|
||||||
struct terminal *wayl_terminal_from_surface(
|
struct terminal *wayl_terminal_from_surface(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue