[PATCH wayland v2] client: Fully flush during blocking dispatch

Jonas Ådahl jadahl at gmail.com
Mon Jan 11 20:31:29 PST 2016


wl_display_flush() may fail with EAGAIN which means that not all data
waiting in the buffer has been flushed. We later block until there
data to read, which could mean that we block on input from the
compositor without having sent out all data from the client. Avoid this
by fully flushing the socket before starting to wait.

Signed-off-by: Jonas Ådahl <jadahl at gmail.com>
---
 src/wayland-client.c | 39 +++++++++++++++++++++++++++++----------
 1 file changed, 29 insertions(+), 10 deletions(-)

diff --git a/src/wayland-client.c b/src/wayland-client.c
index 8bf6124..f47e395 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -1442,6 +1442,21 @@ wl_display_cancel_read(struct wl_display *display)
 	pthread_mutex_unlock(&display->mutex);
 }
 
+static int
+wl_display_poll(struct wl_display *display, short int events)
+{
+	int ret;
+	struct pollfd pfd[2];
+
+	pfd[0].fd = display->fd;
+	pfd[0].events = events;
+	do {
+		ret = poll(pfd, 1, -1);
+	} while (ret == -1 && errno == EINTR);
+
+	return ret;
+}
+
 /** Dispatch events in an event queue
  *
  * \param display The display context object
@@ -1485,27 +1500,31 @@ WL_EXPORT int
 wl_display_dispatch_queue(struct wl_display *display,
 			  struct wl_event_queue *queue)
 {
-	struct pollfd pfd[2];
 	int ret;
 
 	if (wl_display_prepare_read_queue(display, queue) == -1)
 		return wl_display_dispatch_queue_pending(display, queue);
 
+	while (true) {
+		ret = wl_display_flush(display);
+		if (ret == -1 && errno == EAGAIN) {
+			if (wl_display_poll(display, POLLOUT) == -1) {
+				wl_display_cancel_read(display);
+				return -1;
+			}
+		} else {
+			break;
+		}
+	}
+
 	/* Don't stop if flushing hits an EPIPE; continue so we can read any
 	 * protocol error that may have triggered it. */
-	ret = wl_display_flush(display);
-	if (ret < 0 && errno != EAGAIN && errno != EPIPE) {
+	if (ret < 0 && errno != EPIPE) {
 		wl_display_cancel_read(display);
 		return -1;
 	}
 
-	pfd[0].fd = display->fd;
-	pfd[0].events = POLLIN;
-	do {
-		ret = poll(pfd, 1, -1);
-	} while (ret == -1 && errno == EINTR);
-
-	if (ret == -1) {
+	if (wl_display_poll(display, POLLIN) == -1) {
 		wl_display_cancel_read(display);
 		return -1;
 	}
-- 
2.4.3



More information about the wayland-devel mailing list