client: Do not poll when flushing display fails if it's for roundtrip 22/290922/6
authorSeunghun Lee <shiin.lee@samsung.com>
Wed, 5 Apr 2023 04:40:57 +0000 (13:40 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Thu, 6 Apr 2023 07:56:22 +0000 (07:56 +0000)
It was observed that a process was stuck at somewhere in the
wl_display_roundtrip_queue().

I've looked into log messages recorded on the issue situation, and found
out that the compositor didn't get any messages from the process. So I
highly suspect that wl_display_flush() failed for some reason with EPIPE
errno and the process blocked on polling until there is data to read.

Let's find out if it's true with display_roundtrip_queue_ensure_flush().
This is the same as wl_display_roundtrip_queue() except it will return
-1 on failure flushing display with EPIPE.

Change-Id: Id97039e0722cdc591cde8e2b78927940b8db8634

src/wayland-client.c

index 5a60357..d1ab883 100644 (file)
@@ -1517,6 +1517,9 @@ static const struct wl_callback_listener sync_listener = {
        sync_callback
 };
 
+static int display_dispatch_queue_ensure_flush(struct wl_display *display,
+        struct wl_event_queue *queue);
+
 /** Block until all pending request are processed by the server
  *
  * \param display The display context object
@@ -1559,7 +1562,7 @@ wl_display_roundtrip_queue(struct wl_display *display, struct wl_event_queue *qu
 
        wl_callback_add_listener(callback, &sync_listener, &done);
        while (!done && ret >= 0)
-               ret = wl_display_dispatch_queue(display, queue);
+               ret = display_dispatch_queue_ensure_flush(display, queue);
 
        if (ret == -1 && !done)
                wl_callback_destroy(callback);
@@ -2859,3 +2862,52 @@ wl_display_get_name(struct wl_display *display)
        return display->name;
 }
 // END
+
+// TIZEN_ONLY(20230405) : Do not poll when flushing display fails if it's for roundtrip
+static int
+display_dispatch_queue_ensure_flush(struct wl_display *display,
+                         struct wl_event_queue *queue)
+{
+       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)
+                       break;
+
+               if (wl_display_poll(display, POLLOUT) == -1) {
+                       wl_display_cancel_read(display);
+                       wl_log("wl_display_poll failed (display:%p)\n", display);
+                       return -1;
+               }
+       }
+
+       if (ret < 0) {
+               wl_log("Error flushing display(%p) errno(%d, %m)", display, errno);
+               wl_display_cancel_read(display);
+               return -1;
+       }
+
+       if (wl_display_poll(display, POLLIN) == -1) {
+               wl_log("wl_display_poll failed (display:%p)\n", display);
+               wl_display_cancel_read(display);
+               return -1;
+       }
+
+       if (wl_display_read_events(display) == -1) {
+               wl_log("wl_display_read_events failed (display:%p)\n", display);
+               return -1;
+       }
+
+       ret = wl_display_dispatch_queue_pending(display, queue);
+
+       if (ret < 0)
+               wl_log("wl_display_dispatch_queue_pending failed (display:%p)\n", display);
+
+       return ret;
+}
+// END