xserver: Branch 'master' - 3 commits

Adam Jackson ajax at kemper.freedesktop.org
Wed Sep 28 18:46:42 UTC 2016


 hw/xwayland/xwayland-cursor.c |    7 +++---
 hw/xwayland/xwayland-shm.c    |   46 +++++++++++++++++-------------------------
 hw/xwayland/xwayland.c        |   34 ++++++++++++++++++++++++++++---
 hw/xwayland/xwayland.h        |    1 
 4 files changed, 55 insertions(+), 33 deletions(-)

New commits:
commit 862a3dab287b5186a958d0131d70779468348e3e
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Thu Sep 22 09:38:50 2016 +0200

    xwayland: Clear up x_cursor on UnrealizeCursor()
    
    In Xwayland's xwl_unrealize_cursor(), the x_cursor is cleared up only
    when a device value is provided to the UnrealizeCursor() routine, but
    if the device is NULL as called from FreeCursor(), the corresponding
    x_cursor for the xwl_seat is left untouched.
    
    This might cause a segfault when trying to access the unrealized
    cursor's devPrivates in xwl_seat_set_cursor().
    
    A possible occurrence of this is the client changing the cursor, the
    Xserver calling FreeCursor() which does UnrealizeCursor() and then
    the Wayland server sending a pointer enter event, which invokes
    xwl_seat_set_cursor() while the seat's x_cursor has just been
    unrealized.
    
    To avoid this, walk through all the xwl_seats and clear up all x_cursor
    matching the cursor being unrealized.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Jonas Ã…dahl <jadahl at gmail.com>
    Reviewed-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c
index 7d14a3d..b2ae93f 100644
--- a/hw/xwayland/xwayland-cursor.c
+++ b/hw/xwayland/xwayland-cursor.c
@@ -76,6 +76,7 @@ static Bool
 xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
 {
     PixmapPtr pixmap;
+    struct xwl_screen *xwl_screen;
     struct xwl_seat *xwl_seat;
 
     pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key);
@@ -85,9 +86,9 @@ xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
     dixSetPrivate(&cursor->devPrivates, &xwl_cursor_private_key, NULL);
 
     /* When called from FreeCursor(), device is always NULL */
-    if (device) {
-        xwl_seat = device->public.devicePrivate;
-        if (xwl_seat && cursor == xwl_seat->x_cursor)
+    xwl_screen = xwl_screen_get(screen);
+    xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
+        if (cursor == xwl_seat->x_cursor)
             xwl_seat->x_cursor = NULL;
     }
 
commit b79eaf1184f6514ede9dcd9baaa24a40ef724a15
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Thu Sep 15 15:59:07 2016 +0200

    xwayland: handle EAGAIN on Wayland fd
    
    wl_display_flush() can fail with EAGAIN and Xwayland would make this a
    fatal error.
    
    When this happens, it means that Xwayland has flooded the Wayland file
    descriptor, either because the Wayland compositor cannot cope or more
    likely because of a deadlock situation where the Wayland compositor is
    blocking, waiting for an X reply while Xwayland tries to write data to
    the Wayland file descriptor.
    
    The general consensus to avoid the deadlock is for the Wayland
    compositor to never issue blocking X11 roundtrips, but in practice
    blocking rountrips can occur in various places, including Xlib calls
    themselves so this is not always achievable without major surgery in the
    Wayland compositor/Window manager.
    
    What this patch does is to avoid dispatching to the Wayland file
    descriptor until it becomes available for writing again, while at the
    same time continue processing X11 requests to release the deadlock.
    
    This is not perfect, as there is still the possibility of another X
    client hammering the connection and we'll still fail writing to the
    Wayland connection eventually, but this improves things enough to avoid
    a 100% repeatable crash with vlc and gtkperf.
    
    Also, it is worth considering that window managers and Wayland
    compositors such as mutter already have a higher priority than other
    regular X clients thanks to XSyncSetPriority(), mitigating the risk.
    
    Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1278159
    Bugzilla: https://bugzilla.gnome.org/show_bug.cgi?id=763400
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Daniel Stone <daniels at collabora.com>

diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
index 847321e..46a2dfc 100644
--- a/hw/xwayland/xwayland.c
+++ b/hw/xwayland/xwayland.c
@@ -33,6 +33,7 @@
 #include <compositeext.h>
 #include <glx_extinit.h>
 #include <os.h>
+#include <xserver_poll.h>
 
 #ifdef XF86VIDMODE
 #include <X11/extensions/xf86vmproto.h>
@@ -470,6 +471,9 @@ xwl_read_events (struct xwl_screen *xwl_screen)
 {
     int ret;
 
+    if (xwl_screen->wait_flush)
+        return;
+
     ret = wl_display_read_events(xwl_screen->display);
     if (ret == -1)
         FatalError("failed to read Wayland events: %s\n", strerror(errno));
@@ -481,10 +485,25 @@ xwl_read_events (struct xwl_screen *xwl_screen)
         FatalError("failed to dispatch Wayland events: %s\n", strerror(errno));
 }
 
+static int
+xwl_display_pollout (struct xwl_screen *xwl_screen, int timeout)
+{
+    struct pollfd poll_fd;
+
+    poll_fd.fd = wl_display_get_fd(xwl_screen->display);
+    poll_fd.events = POLLOUT;
+
+    return xserver_poll(&poll_fd, 1, timeout);
+}
+
 static void
 xwl_dispatch_events (struct xwl_screen *xwl_screen)
 {
-    int ret;
+    int ret = 0;
+    int ready;
+
+    if (xwl_screen->wait_flush)
+        goto pollout;
 
     while (xwl_screen->prepare_read == 0 &&
            wl_display_prepare_read(xwl_screen->display) == -1) {
@@ -496,9 +515,18 @@ xwl_dispatch_events (struct xwl_screen *xwl_screen)
 
     xwl_screen->prepare_read = 1;
 
-    ret = wl_display_flush(xwl_screen->display);
-    if (ret == -1)
+pollout:
+    ready = xwl_display_pollout(xwl_screen, 5);
+    if (ready == -1 && errno != EINTR)
+        FatalError("error polling on XWayland fd: %s\n", strerror(errno));
+
+    if (ready > 0)
+        ret = wl_display_flush(xwl_screen->display);
+
+    if (ret == -1 && errno != EAGAIN)
         FatalError("failed to write to XWayland fd: %s\n", strerror(errno));
+
+    xwl_screen->wait_flush = (ready == 0 || ready == -1 || ret == -1);
 }
 
 static void
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index db3dd0b..3ce7a63 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -83,6 +83,7 @@ struct xwl_screen {
 #define XWL_FORMAT_RGB565   (1 << 2)
 
     int prepare_read;
+    int wait_flush;
 
     char *device_name;
     int drm_fd;
commit 36e1a058c5826398ceea9dba6c166ae40c75646e
Author: Rui Matos <tiagomatos at gmail.com>
Date:   Fri Feb 5 14:44:29 2016 +0100

    xwayland: Close the shm fd as early as possible
    
    Keeping the shm fd open beyond pixmap creation means we can easily
    reach the open file descriptor limit if an X client asks us to create
    that many pixmaps. Instead, let's get the wl_buffer immediatly so that
    we can destroy the shm pool and close the fd before being asked to
    create more.
    Tested-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Olivier Fourdan <ofourdan at redhat.com>

diff --git a/hw/xwayland/xwayland-shm.c b/hw/xwayland/xwayland-shm.c
index c199e5e..daf6148 100644
--- a/hw/xwayland/xwayland-shm.c
+++ b/hw/xwayland/xwayland-shm.c
@@ -40,7 +40,6 @@
 
 struct xwl_pixmap {
     struct wl_buffer *buffer;
-    int fd;
     void *data;
     size_t size;
 };
@@ -184,9 +183,13 @@ PixmapPtr
 xwl_shm_create_pixmap(ScreenPtr screen,
                       int width, int height, int depth, unsigned int hint)
 {
-    PixmapPtr pixmap;
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
     struct xwl_pixmap *xwl_pixmap;
+    struct wl_shm_pool *pool;
+    PixmapPtr pixmap;
     size_t size, stride;
+    uint32_t format;
+    int fd;
 
     if (hint == CREATE_PIXMAP_USAGE_GLYPH_PICTURE ||
         (width == 0 && height == 0) || depth < 15)
@@ -204,12 +207,12 @@ xwl_shm_create_pixmap(ScreenPtr screen,
     size = stride * height;
     xwl_pixmap->buffer = NULL;
     xwl_pixmap->size = size;
-    xwl_pixmap->fd = os_create_anonymous_file(size);
-    if (xwl_pixmap->fd < 0)
+    fd = os_create_anonymous_file(size);
+    if (fd < 0)
         goto err_free_xwl_pixmap;
 
     xwl_pixmap->data = mmap(NULL, size, PROT_READ | PROT_WRITE,
-                                  MAP_SHARED, xwl_pixmap->fd, 0);
+                                  MAP_SHARED, fd, 0);
     if (xwl_pixmap->data == MAP_FAILED)
         goto err_close_fd;
 
@@ -218,6 +221,15 @@ xwl_shm_create_pixmap(ScreenPtr screen,
                                         stride, xwl_pixmap->data))
         goto err_munmap;
 
+    format = shm_format_for_depth(pixmap->drawable.depth);
+    pool = wl_shm_create_pool(xwl_screen->shm, fd, xwl_pixmap->size);
+    xwl_pixmap->buffer = wl_shm_pool_create_buffer(pool, 0,
+                                                   pixmap->drawable.width,
+                                                   pixmap->drawable.height,
+                                                   pixmap->devKind, format);
+    wl_shm_pool_destroy(pool);
+    close(fd);
+
     xwl_pixmap_set_private(pixmap, xwl_pixmap);
 
     return pixmap;
@@ -225,7 +237,7 @@ xwl_shm_create_pixmap(ScreenPtr screen,
  err_munmap:
     munmap(xwl_pixmap->data, size);
  err_close_fd:
-    close(xwl_pixmap->fd);
+    close(fd);
  err_free_xwl_pixmap:
     free(xwl_pixmap);
  err_destroy_pixmap:
@@ -243,7 +255,6 @@ xwl_shm_destroy_pixmap(PixmapPtr pixmap)
         if (xwl_pixmap->buffer)
             wl_buffer_destroy(xwl_pixmap->buffer);
         munmap(xwl_pixmap->data, xwl_pixmap->size);
-        close(xwl_pixmap->fd);
         free(xwl_pixmap);
     }
 
@@ -253,26 +264,7 @@ xwl_shm_destroy_pixmap(PixmapPtr pixmap)
 struct wl_buffer *
 xwl_shm_pixmap_get_wl_buffer(PixmapPtr pixmap)
 {
-    struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
-    struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
-    struct wl_shm_pool *pool;
-    uint32_t format;
-
-    if (xwl_pixmap->buffer)
-        return xwl_pixmap->buffer;
-
-    pool = wl_shm_create_pool(xwl_screen->shm,
-                              xwl_pixmap->fd, xwl_pixmap->size);
-
-    format = shm_format_for_depth(pixmap->drawable.depth);
-    xwl_pixmap->buffer = wl_shm_pool_create_buffer(pool, 0,
-                                                   pixmap->drawable.width,
-                                                   pixmap->drawable.height,
-                                                   pixmap->devKind, format);
-
-    wl_shm_pool_destroy(pool);
-
-    return xwl_pixmap->buffer;
+    return xwl_pixmap_get(pixmap)->buffer;
 }
 
 Bool


More information about the xorg-commit mailing list