Revert "e_compositor: Remove obsolete implementation" 55/316755/1
authorShawn Lee <seunghun.shawn@gmail.com>
Tue, 27 Aug 2024 13:11:25 +0000 (22:11 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Wed, 28 Aug 2024 00:15:29 +0000 (09:15 +0900)
This reverts commit b2618459adfe7bba81cba8c8ea3271e325263c70.

The frame callback resource may be destroyed by external implementation
especially when wl_client is destroyed. That's what I missed.

This fixes crash caused by dangling pointer.

 #0  0xb541c238 in wl_list_remove (elm=0x161d718) at /usr/src/debug/wayland-1.22.0-0.arm/builddir/../src/wayland-util.c:66
 #1  0xb541db6c in remove_and_destroy_resource (element=0x161d708, data=data@entry=0x0, flags=0) at /usr/src/debug/wayland-1.22.0-0.arm/builddir/../src/wayland-server.c:943
 #2  0xb541dc22 in wl_resource_destroy (resource=<optimized out>) at /usr/src/debug/wayland-1.22.0-0.arm/builddir/../src/wayland-server.c:986
 #3  0x000fd67a in _e_surface_destroy (surface=0x1a45c48) at /usr/src/debug/enlightenment-0.20.0-tz9_30.0.0.arm/src/bin/server/e_compositor.c:865

Change-Id: I3b7e09fe1571c3e2b6b5b6ed01e50bcfba5e08c4

src/bin/server/e_comp_wl.c
src/bin/server/e_comp_wl_intern.h
src/bin/server/e_compositor.c

index aa95fa6..8ecdcee 100644 (file)
@@ -6157,6 +6157,40 @@ e_comp_wl_client_surface_pending_input_region_set(E_Client *ec, Eina_Tiler *regi
 }
 
 EINTERN void
+e_comp_wl_client_surface_pending_frame_callback_add(E_Client *ec, struct wl_resource *callback_resource)
+{
+   ec->comp_data->pending.frames = eina_list_prepend(ec->comp_data->pending.frames, callback_resource);
+}
+
+EINTERN void
+e_comp_wl_client_surface_frame_callback_remove(E_Client *ec, struct wl_resource *callback_resource)
+{
+   E_Comp_Wl_Subsurf_Data *sdata;
+
+   if (!ec->comp_data)
+     return;
+
+   if (ec->comp_data->frames)
+     {
+        ec->comp_data->frames =
+           eina_list_remove(ec->comp_data->frames, callback_resource);
+     }
+
+   if (ec->comp_data->pending.frames)
+     {
+        ec->comp_data->pending.frames =
+           eina_list_remove(ec->comp_data->pending.frames, callback_resource);
+     }
+
+   sdata = ec->comp_data->sub.data;
+   if ((sdata) && (sdata->cached.frames))
+     {
+        sdata->cached.frames =
+           eina_list_remove(sdata->cached.frames, callback_resource);
+     }
+}
+
+EINTERN void
 e_comp_wl_client_surface_pending_commit(E_Client *ec)
 {
    if (e_object_is_del(E_OBJECT(ec))) return;
index ee94a67..d8480f7 100644 (file)
@@ -93,6 +93,8 @@ EINTERN void e_comp_wl_client_surface_finish(E_Client *ec);
 EINTERN void e_comp_wl_client_surface_pending_buffer_set(E_Client *ec, E_Comp_Wl_Buffer *buffer, int32_t sx, int32_t sy);
 EINTERN void e_comp_wl_client_surface_pending_opaque_region_set(E_Client *ec, Eina_Tiler *region);
 EINTERN void e_comp_wl_client_surface_pending_input_region_set(E_Client *ec, Eina_Tiler *region);
+EINTERN void e_comp_wl_client_surface_pending_frame_callback_add(E_Client *ec, struct wl_resource *callback_resource);
+EINTERN void e_comp_wl_client_surface_frame_callback_remove(E_Client *ec, struct wl_resource *callback_resource);
 EINTERN void e_comp_wl_client_surface_pending_commit(E_Client *ec);
 
 EINTERN Eina_Bool e_comp_wl_client_subsurface_cyclic_reference_check(E_Client *ec, E_Client *parent);
index 14420e8..270f131 100644 (file)
@@ -20,6 +20,7 @@
 typedef struct _E_Compositor E_Compositor;
 typedef struct _E_Subsurface E_Subsurface;
 typedef struct _E_Subsurface_View E_Subsurface_View;
+typedef struct _E_Frame_Callback E_Frame_Callback;
 
 struct _E_Compositor
 {
@@ -625,7 +626,6 @@ e_surface_frame_done_send(E_Surface *surface)
      {
         wl_callback_send_done(resource, (unsigned int)(ecore_loop_time_get() * 1000));
         wl_resource_destroy(resource);
-        surface->base.frames = eina_list_remove_list(surface->base.frames, l);
      }
 }
 
@@ -1160,17 +1160,41 @@ _e_surface_pending_buffer_scale_update(E_Surface *surface)
 }
 
 static void
+_frame_callback_cb_destroy(struct wl_listener *listener, void *data)
+{
+   struct wl_resource *resource = data;
+   E_Frame_Callback *frame_callback;
+
+   frame_callback = wl_container_of(listener, frame_callback, destroy);
+   e_comp_wl_client_surface_frame_callback_remove(frame_callback->ec, resource);
+   e_object_unref(E_OBJECT(frame_callback->ec));
+   free(frame_callback);
+}
+
+static void
 _e_surface_pending_frame_callback_update(E_Surface *surface)
 {
    struct ds_surface *ds_surface = surface->ds_surface;
-   struct wl_resource *resource, *tmp;
+   E_Client *ec = surface->ec;
+   E_Frame_Callback *frame_callback;
+   struct wl_resource *resource;
 
-   wl_resource_for_each_safe(resource, tmp, &ds_surface->current.frame_callback_list)
+   wl_resource_for_each(resource, &ds_surface->current.frame_callback_list)
      {
-        wl_list_remove(wl_resource_get_link(resource));
-        wl_list_init(wl_resource_get_link(resource));
-        surface->base.pending.frames = eina_list_prepend(surface->base.pending.frames, resource);
+        frame_callback = E_NEW(E_Frame_Callback, 1);
+        if (!frame_callback)
+          continue;
+
+        e_object_ref(E_OBJECT(ec));
+        frame_callback->ec = ec;
+
+        frame_callback->destroy.notify = _frame_callback_cb_destroy;
+        wl_resource_add_destroy_listener(resource, &frame_callback->destroy);
+
+        e_comp_wl_client_surface_pending_frame_callback_add(ec, resource);
      }
+
+   wl_list_init(&ds_surface->current.frame_callback_list);
 }
 
 static void