[clutter/wip/wayland: 3/45] cogland: Fix crash when frame callback is destroyed before emitted



commit 5e0e53a66e44a49d03e4c420c69321af0d4a64ab
Author: Robert Bragg <robert linux intel com>
Date:   Tue Jan 3 23:45:29 2012 +0000

    cogland: Fix crash when frame callback is destroyed before emitted
    
    If a frame callback is destroyed before it is invoked then the struct
    would be freed but it would not be removed from the array of callbacks
    so when cogland later tried to emit the callback it would crash. This
    patch instead stores the callbacks in a GQueue with embedded list nodes
    so that they can be removed from the list in the resource destructor.
    That way it doesn't matter how the resource is destroyed, it will still
    get removed from the list.
    
    This patch was based on an equivalent patch made to cogland by Neil
    Roberts.

 tests/interactive/test-wayland-surface.c |   24 +++++++++++++++++-------
 1 files changed, 17 insertions(+), 7 deletions(-)
---
diff --git a/tests/interactive/test-wayland-surface.c b/tests/interactive/test-wayland-surface.c
index f8938f6..015e0e2 100644
--- a/tests/interactive/test-wayland-surface.c
+++ b/tests/interactive/test-wayland-surface.c
@@ -74,6 +74,12 @@ typedef struct
 
 typedef struct
 {
+  /* GList node used as an embedded list */
+  GList node;
+
+  /* Pointer back to the compositor */
+  TWSCompositor *compositor;
+
   struct wl_resource resource;
 } TWSFrameCallback;
 
@@ -86,7 +92,7 @@ struct _TWSCompositor
   GList *outputs;
   GSource *wayland_event_source;
   GList *surfaces;
-  GArray *frame_callbacks;
+  GQueue frame_callbacks;
 
   int xwayland_display_index;
   char *xwayland_lockfile;
@@ -324,6 +330,9 @@ destroy_frame_callback (struct wl_resource *callback_resource)
 {
   TWSFrameCallback *callback = callback_resource->data;
 
+  g_queue_unlink (&callback->compositor->frame_callbacks,
+                  &callback->node);
+
   g_slice_free (TWSFrameCallback, callback);
 }
 
@@ -336,6 +345,8 @@ tws_surface_frame (struct wl_client *client,
   TWSSurface *surface = surface_resource->data;
 
   callback = g_slice_new0 (TWSFrameCallback);
+  callback->compositor = surface->compositor;
+  callback->node.data = callback;
   callback->resource.object.interface = &wl_callback_interface;
   callback->resource.object.id = callback_id;
   callback->resource.destroy = destroy_frame_callback;
@@ -343,7 +354,8 @@ tws_surface_frame (struct wl_client *client,
 
   wl_client_add_resource (client, &callback->resource);
 
-  g_array_append_val (surface->compositor->frame_callbacks, callback);
+  g_queue_push_tail_link (&surface->compositor->frame_callbacks,
+                          &callback->node);
 }
 
 const struct wl_surface_interface tws_surface_interface = {
@@ -466,18 +478,16 @@ static void
 paint_finished_cb (ClutterActor *self, void *user_data)
 {
   TWSCompositor *compositor = user_data;
-  int i;
 
-  for (i = 0; i < compositor->frame_callbacks->len; i++)
+  while (!g_queue_is_empty (&compositor->frame_callbacks))
     {
       TWSFrameCallback *callback =
-        g_array_index (compositor->frame_callbacks, TWSFrameCallback *, i);
+        g_queue_peek_head (&compositor->frame_callbacks);
 
       wl_resource_post_event (&callback->resource,
                               WL_CALLBACK_DONE, get_time ());
       wl_resource_destroy (&callback->resource, 0);
     }
-  g_array_set_size (compositor->frame_callbacks, 0);
 }
 
 static void
@@ -1029,7 +1039,7 @@ test_wayland_surface_main (int argc, char **argv)
   if (compositor.wayland_display == NULL)
     g_error ("failed to create wayland display");
 
-  compositor.frame_callbacks = g_array_new (FALSE, FALSE, sizeof (void *));
+  g_queue_init (&compositor.frame_callbacks);
 
   if (!wl_display_add_global (compositor.wayland_display,
                               &wl_compositor_interface,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]