[gnome-builder] egg-slider: re-entrant safety on ::forall



commit 5bc8b69510cb1aac6e8673ebf71f7308cb86a607
Author: Christian Hergert <christian hergert me>
Date:   Sun Jan 17 09:23:04 2016 -0800

    egg-slider: re-entrant safety on ::forall
    
    We need to be safe against gtk_widget_destroy() used as a callback, which
    could mutate our priv->children array.

 contrib/egg/egg-slider.c |   29 ++++++++++++++++++++++++-----
 1 files changed, 24 insertions(+), 5 deletions(-)
---
diff --git a/contrib/egg/egg-slider.c b/contrib/egg/egg-slider.c
index ba68b29..09c23e3 100644
--- a/contrib/egg/egg-slider.c
+++ b/contrib/egg/egg-slider.c
@@ -365,17 +365,36 @@ egg_slider_forall (GtkContainer *container,
 {
   EggSlider *self = (EggSlider *)container;
   EggSliderPrivate *priv = egg_slider_get_instance_private (self);
-  gsize i;
+  GtkWidget **children;
+  guint len;
+  guint i;
 
   g_assert (EGG_IS_SLIDER (self));
 
-  for (i = 0; i < priv->children->len; i++)
+  /*
+   * We need to be widget re-entrant safe, meaning that the callback could
+   * remove a child during callback(), using gtk_widget_destroy or similar. So
+   * we create a local array containing a ref'd copy of all of the widgets in
+   * case the callback removes widgets.
+   */
+
+  len = priv->children->len;
+  children = g_new0 (GtkWidget *, len);
+
+  for (i = 0; i < len; i++)
     {
-      EggSliderChild *child;
+      EggSliderChild *child = g_ptr_array_index (priv->children, i);
 
-      child = g_ptr_array_index (priv->children, i);
-      callback (child->widget, callback_data);
+      children [i] = g_object_ref (child->widget);
+    }
+
+  for (i = 0; i < len; i++)
+    {
+      callback (children [i], callback_data);
+      g_object_unref (children [i]);
     }
+
+  g_free (children);
 }
 
 static EggSliderChild *


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