[mutter] clutter/stage: Steal and manually free pending_queue_redraw entries



commit 261447a498e8ef3db40c4d30d5e08ec87daa43d3
Author: Daniel van Vugt <daniel van vugt canonical com>
Date:   Mon Nov 30 18:03:01 2020 +0800

    clutter/stage: Steal and manually free pending_queue_redraw entries
    
    New entries indirectly added to `pending_queue_redraw` during the loop
    would make our iterator invalid and cause `g_hash_table_iter_next` to
    fail without having visited all elements. That was seen as assertion
    failures but also likely resulted in incomplete paint clips.
    
    Now we steal the iterator's entry before such corruption can happen,
    free it manually, and reset the iterator to the beginning on every
    iteration. This is actually safe and efficient because we're removing each
    entry we visit. So no time is wasted in resuming from the (new) beginning
    of the hash table.
    
    Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1557
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1615>

 clutter/clutter/clutter-stage.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)
---
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index fd12c0381a..626193e2a0 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -2800,6 +2800,8 @@ clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage)
       QueueRedrawEntry *entry = value;
       ClutterPaintVolume old_actor_pv, new_actor_pv;
 
+      g_hash_table_iter_steal (&iter);
+
       _clutter_paint_volume_init_static (&old_actor_pv, NULL);
       _clutter_paint_volume_init_static (&new_actor_pv, NULL);
 
@@ -2829,7 +2831,15 @@ clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage)
           add_to_stage_clip (stage, NULL);
         }
 
-      g_hash_table_iter_remove (&iter);
+      g_object_unref (redraw_actor);
+      free_queue_redraw_entry (entry);
+
+      /* get_paint_volume() vfuncs might queue redraws and can cause our
+       * iterator to now be invalidated. So start over. This isn't wasting
+       * any time since we already stole (removed) the elements previously
+       * visited.
+       */
+      g_hash_table_iter_init (&iter, priv->pending_queue_redraws);
     }
 }
 


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