Blame SOURCES/0014-xwayland-handle-global-object-destruction.patch

70130e
From a7da07002daaa1e1397a3fe32ea3c77df4f15071 Mon Sep 17 00:00:00 2001
70130e
From: Giovanni Campagna <gcampagn@redhat.com>
70130e
Date: Wed, 21 Aug 2013 09:53:26 +0200
70130e
Subject: [PATCH 14/39] xwayland: handle global object destruction
70130e
70130e
Certain global objects, such as outputs, can be destroyed during
70130e
the session. We must handle that and not crash.
70130e
---
70130e
 hw/xfree86/xwayland/xwayland-drm.c     |  7 ++++++
70130e
 hw/xfree86/xwayland/xwayland-input.c   |  7 ++++++
70130e
 hw/xfree86/xwayland/xwayland-output.c  | 40 +++++++++++++++++++++++++++++++---
70130e
 hw/xfree86/xwayland/xwayland-private.h |  6 ++++-
70130e
 hw/xfree86/xwayland/xwayland.c         | 17 +++++++++++----
70130e
 5 files changed, 69 insertions(+), 8 deletions(-)
70130e
70130e
diff --git a/hw/xfree86/xwayland/xwayland-drm.c b/hw/xfree86/xwayland/xwayland-drm.c
70130e
index ce56e4c..6e4c778 100644
70130e
--- a/hw/xfree86/xwayland/xwayland-drm.c
70130e
+++ b/hw/xfree86/xwayland/xwayland-drm.c
70130e
@@ -119,8 +119,15 @@ drm_handler(void *data, struct wl_registry *registry, uint32_t id,
70130e
     }
70130e
 }
70130e
 
70130e
+static void
70130e
+global_remove(void *data, struct wl_registry *registry, uint32_t name)
70130e
+{
70130e
+    /* Nothing to do here, wl_drm should not be removed */
70130e
+}
70130e
+
70130e
 static const struct wl_registry_listener drm_listener = {
70130e
     drm_handler,
70130e
+    global_remove
70130e
 };
70130e
 
70130e
 int
70130e
diff --git a/hw/xfree86/xwayland/xwayland-input.c b/hw/xfree86/xwayland/xwayland-input.c
70130e
index 2f8e0c7..d031b34 100644
70130e
--- a/hw/xfree86/xwayland/xwayland-input.c
70130e
+++ b/hw/xfree86/xwayland/xwayland-input.c
70130e
@@ -597,8 +597,15 @@ input_handler(void *data, struct wl_registry *registry, uint32_t id,
70130e
     }
70130e
 }
70130e
 
70130e
+static void
70130e
+global_remove(void *data, struct wl_registry *registry, uint32_t name)
70130e
+{
70130e
+    /* FIXME */
70130e
+}
70130e
+
70130e
 static const struct wl_registry_listener input_listener = {
70130e
     input_handler,
70130e
+    global_remove,
70130e
 };
70130e
 
70130e
 void
70130e
diff --git a/hw/xfree86/xwayland/xwayland-output.c b/hw/xfree86/xwayland/xwayland-output.c
70130e
index 8f087f6..46238f4 100644
70130e
--- a/hw/xfree86/xwayland/xwayland-output.c
70130e
+++ b/hw/xfree86/xwayland/xwayland-output.c
70130e
@@ -95,6 +95,14 @@ crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
70130e
 {
70130e
 }
70130e
 
70130e
+static void
70130e
+crtc_destroy(xf86CrtcPtr crtc)
70130e
+{
70130e
+    /* Nothing to do here, we only destroy CRTCs when instructed to do
70130e
+       so by wl_output changes
70130e
+    */
70130e
+}
70130e
+
70130e
 static const xf86CrtcFuncsRec crtc_funcs = {
70130e
     .dpms                = crtc_dpms,
70130e
     .set_mode_major      = crtc_set_mode_major,
70130e
@@ -106,7 +114,7 @@ static const xf86CrtcFuncsRec crtc_funcs = {
70130e
     .shadow_create       = crtc_shadow_create,
70130e
     .shadow_allocate     = crtc_shadow_allocate,
70130e
     .shadow_destroy      = crtc_shadow_destroy,
70130e
-    .destroy		 = NULL, /* XXX */
70130e
+    .destroy		 = crtc_destroy,
70130e
 };
70130e
 
70130e
 static void
70130e
@@ -246,7 +254,7 @@ display_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
70130e
     xwl_output->x = x;
70130e
     xwl_output->y = y;
70130e
 
70130e
-    xwl_screen->xwl_output = xwl_output;
70130e
+    xorg_list_append (&xwl_output->link, &xwl_screen->output_list);
70130e
 }
70130e
 
70130e
 static void
70130e
@@ -277,13 +285,39 @@ global_handler(void *data, struct wl_registry *registry, uint32_t id,
70130e
 	xwl_output = xwl_output_create(xwl_screen);
70130e
 	xwl_output->output = wl_registry_bind(registry, id,
70130e
 	                                      &wl_output_interface, 1);
70130e
+	xwl_output->name = id;
70130e
 	wl_output_add_listener(xwl_output->output,
70130e
 			       &output_listener, xwl_output);
70130e
     }
70130e
 }
70130e
 
70130e
+void
70130e
+xwl_output_remove(struct xwl_output *xwl_output)
70130e
+{
70130e
+    xorg_list_del (&xwl_output->link);
70130e
+    xf86OutputDestroy (xwl_output->xf86output);
70130e
+    xf86CrtcDestroy (xwl_output->xf86crtc);
70130e
+
70130e
+    wl_output_destroy (xwl_output->output);
70130e
+}
70130e
+
70130e
+static void
70130e
+global_remove(void *data, struct wl_registry *registry, uint32_t name)
70130e
+{
70130e
+    struct xwl_screen *xwl_screen = data;
70130e
+    struct xwl_output *xwl_output, *tmp;
70130e
+
70130e
+    xorg_list_for_each_entry_safe (xwl_output, tmp, &xwl_screen->output_list, link) {
70130e
+	if (xwl_output->name == name) {
70130e
+	    xwl_output_remove(xwl_output);
70130e
+	    break;
70130e
+	}
70130e
+    }
70130e
+}
70130e
+
70130e
 static const struct wl_registry_listener global_listener = {
70130e
     global_handler,
70130e
+    global_remove
70130e
 };
70130e
 
70130e
 void
70130e
@@ -299,7 +333,7 @@ xwayland_screen_preinit_output(struct xwl_screen *xwl_screen, ScrnInfoPtr scrnin
70130e
     wl_registry_add_listener(xwl_screen->output_registry, &global_listener,
70130e
                              xwl_screen);
70130e
 
70130e
-    while (!xwl_screen->xwl_output) {
70130e
+    while (xwl_screen->output_list.next == &xwl_screen->output_list) {
70130e
         ret = wl_display_roundtrip(xwl_screen->display);
70130e
         if (ret == -1)
70130e
             FatalError("failed to dispatch Wayland events: %s\n", strerror(errno));
70130e
diff --git a/hw/xfree86/xwayland/xwayland-private.h b/hw/xfree86/xwayland/xwayland-private.h
70130e
index e427316..7005db2 100644
70130e
--- a/hw/xfree86/xwayland/xwayland-private.h
70130e
+++ b/hw/xfree86/xwayland/xwayland-private.h
70130e
@@ -44,7 +44,6 @@ struct xwl_screen {
70130e
     ScrnInfoPtr			 scrninfo;
70130e
     int				 drm_fd;
70130e
     int				 wayland_fd;
70130e
-    struct xwl_output		*xwl_output;
70130e
     struct wl_display		*display;
70130e
     struct wl_registry          *registry;
70130e
     struct wl_registry          *drm_registry;
70130e
@@ -58,6 +57,7 @@ struct xwl_screen {
70130e
     uint32_t			 flags;
70130e
     char			*device_name;
70130e
     uint32_t			 authenticated;
70130e
+    struct xorg_list		 output_list;
70130e
     struct xorg_list		 seat_list;
70130e
     struct xorg_list		 damage_window_list;
70130e
     struct xorg_list		 window_list;
70130e
@@ -74,12 +74,14 @@ struct xwl_screen {
70130e
 };
70130e
 
70130e
 struct xwl_output {
70130e
+    struct xorg_list             link;
70130e
     struct wl_output		*output;
70130e
     struct xwl_screen		*xwl_screen;
70130e
     int32_t			 x, y, width, height;
70130e
     xf86Monitor			 xf86monitor;
70130e
     xf86OutputPtr		 xf86output;
70130e
     xf86CrtcPtr			 xf86crtc;
70130e
+    int32_t                      name;
70130e
 };
70130e
 
70130e
 
70130e
@@ -127,6 +129,8 @@ Bool xwl_drm_initialised(struct xwl_screen *screen);
70130e
 
70130e
 void xwl_seat_set_cursor(struct xwl_seat *xwl_seat);
70130e
 
70130e
+void xwl_output_remove(struct xwl_output *output);
70130e
+
70130e
 extern const struct xserver_listener xwl_server_listener;
70130e
 
70130e
 #endif /* _XWAYLAND_PRIVATE_H_ */
70130e
diff --git a/hw/xfree86/xwayland/xwayland.c b/hw/xfree86/xwayland/xwayland.c
70130e
index 880b7ec..2047a85 100644
70130e
--- a/hw/xfree86/xwayland/xwayland.c
70130e
+++ b/hw/xfree86/xwayland/xwayland.c
70130e
@@ -103,8 +103,15 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id,
70130e
     }
70130e
 }
70130e
 
70130e
+static void
70130e
+global_remove(void *data, struct wl_registry *registry, uint32_t name)
70130e
+{
70130e
+    /* Nothing to do here, wl_compositor and wl_shm should not be removed */
70130e
+}
70130e
+
70130e
 static const struct wl_registry_listener registry_listener = {
70130e
     registry_global,
70130e
+    global_remove
70130e
 };
70130e
 
70130e
 static void
70130e
@@ -230,6 +237,7 @@ xwl_screen_pre_init(ScrnInfoPtr scrninfo, struct xwl_screen *xwl_screen,
70130e
 	return FALSE;
70130e
     }
70130e
 
70130e
+    xorg_list_init(&xwl_screen->output_list);
70130e
     xorg_list_init(&xwl_screen->seat_list);
70130e
     xorg_list_init(&xwl_screen->damage_window_list);
70130e
     xorg_list_init(&xwl_screen->window_list);
70130e
@@ -318,12 +326,13 @@ void xwl_screen_close(struct xwl_screen *xwl_screen)
70130e
 
70130e
 void xwl_screen_destroy(struct xwl_screen *xwl_screen)
70130e
 {
70130e
-    if (xwl_screen->xwl_output) {
70130e
-	xf86OutputDestroy(xwl_screen->xwl_output->xf86output);
70130e
-	xf86CrtcDestroy(xwl_screen->xwl_output->xf86crtc);
70130e
+    struct xwl_output *xwl_output, *tmp;
70130e
+
70130e
+    xorg_list_for_each_entry_safe (xwl_output, tmp, &xwl_screen->output_list, link) {
70130e
+	xwl_output_remove(xwl_output);
70130e
+	break;
70130e
     }
70130e
 
70130e
-    free(xwl_screen->xwl_output);
70130e
     free(xwl_screen);
70130e
 }
70130e
 
70130e
-- 
70130e
1.8.3.1
70130e