[gnome-builder/gnome-builder-3-26] config-manager: backport safety fixes



commit 9e8239f8f40a34b814118ae125f16720d7fa9ce9
Author: Christian Hergert <chergert redhat com>
Date:   Sun Jan 21 02:23:22 2018 -0800

    config-manager: backport safety fixes
    
    This backports various fixes from master to remove threading from the
    configuration initialization as well as some other cleanup.

 libide/buildsystem/ide-configuration-manager.c | 233 ++++++++++++++-----------
 1 file changed, 129 insertions(+), 104 deletions(-)
---
diff --git a/libide/buildsystem/ide-configuration-manager.c b/libide/buildsystem/ide-configuration-manager.c
index c2f940381..4f3200741 100644
--- a/libide/buildsystem/ide-configuration-manager.c
+++ b/libide/buildsystem/ide-configuration-manager.c
@@ -40,8 +40,6 @@ struct _IdeConfigurationManager
   GPtrArray        *configurations;
   IdeConfiguration *current;
   PeasExtensionSet *extensions;
-  GCancellable     *cancellable;
-  guint             providers_loading;
 };
 
 static void async_initable_iface_init           (GAsyncInitableIface *iface);
@@ -67,6 +65,25 @@ enum {
 static GParamSpec *properties [LAST_PROP];
 static guint signals [N_SIGNALS];
 
+static void
+ide_configuration_manager_track_buildconfig (PeasExtensionSet *set,
+                                             PeasPluginInfo   *plugin_info,
+                                             PeasExtension    *exten,
+                                             gpointer          user_data)
+{
+  IdeConfigurationProvider *provider = (IdeConfigurationProvider *)exten;
+  IdeConfiguration *config = user_data;
+
+  g_assert (PEAS_IS_EXTENSION_SET (set));
+  g_assert (plugin_info != NULL);
+  g_assert (IDE_IS_CONFIGURATION_PROVIDER (provider));
+  g_assert (!config || IDE_IS_BUILDCONFIG_CONFIGURATION (config));
+
+  if (IDE_IS_BUILDCONFIG_CONFIGURATION_PROVIDER (provider) && config != NULL)
+    ide_buildconfig_configuration_provider_track_config (IDE_BUILDCONFIG_CONFIGURATION_PROVIDER (provider),
+                                                         IDE_BUILDCONFIG_CONFIGURATION (config));
+}
+
 static void
 ide_configuration_manager_add_default (IdeConfigurationManager *self)
 {
@@ -76,7 +93,6 @@ ide_configuration_manager_add_default (IdeConfigurationManager *self)
   g_assert (IDE_IS_CONFIGURATION_MANAGER (self));
 
   context = ide_object_get_context (IDE_OBJECT (self));
-
   config = g_object_new (IDE_TYPE_BUILDCONFIG_CONFIGURATION,
                          "id", "default",
                          "context", context,
@@ -85,9 +101,12 @@ ide_configuration_manager_add_default (IdeConfigurationManager *self)
                          NULL);
   ide_configuration_set_display_name (IDE_CONFIGURATION (config), _("Default"));
   ide_configuration_manager_add (self, IDE_CONFIGURATION (config));
-
   if (self->configurations->len == 1)
     ide_configuration_manager_set_current (self, IDE_CONFIGURATION (config));
+
+  peas_extension_set_foreach (self->extensions,
+                              ide_configuration_manager_track_buildconfig,
+                              config);
 }
 
 static void
@@ -229,10 +248,16 @@ ide_configuration_manager_get_configuration (IdeConfigurationManager *self,
 
   for (guint i = 0; i < self->configurations->len; i++)
     {
-      IdeConfiguration *configuration = g_ptr_array_index (self->configurations, i);
+      IdeConfiguration *config = g_ptr_array_index (self->configurations, i);
+      const gchar *config_id;
 
-      if (g_strcmp0 (id, ide_configuration_get_id (configuration)) == 0)
-        return configuration;
+      g_assert (config != NULL);
+      g_assert (IDE_IS_CONFIGURATION (config));
+
+      config_id = ide_configuration_get_id (config);
+
+      if (ide_str_equal0 (config_id, id))
+        return config;
     }
 
   return NULL;
@@ -264,10 +289,6 @@ ide_configuration_manager_finalize (GObject *object)
       g_clear_object (&self->current);
     }
 
-  if (self->cancellable != NULL)
-    g_cancellable_cancel (self->cancellable);
-  g_clear_object (&self->cancellable);
-
   G_OBJECT_CLASS (ide_configuration_manager_parent_class)->finalize (object);
 }
 
@@ -396,31 +417,13 @@ list_model_iface_init (GListModelInterface *iface)
   iface->get_item = ide_configuration_manager_get_item;
 }
 
-static void
-ide_configuration_manager_track_buildconfig (PeasExtensionSet *set,
-                                             PeasPluginInfo   *plugin_info,
-                                             PeasExtension    *exten,
-                                             gpointer          user_data)
-{
-  IdeConfigurationProvider *provider = (IdeConfigurationProvider *)exten;
-  IdeConfiguration *config = user_data;
-
-  g_assert (PEAS_IS_EXTENSION_SET (set));
-  g_assert (plugin_info != NULL);
-  g_assert (IDE_IS_CONFIGURATION_PROVIDER (provider));
-
-  if (IDE_IS_BUILDCONFIG_CONFIGURATION_PROVIDER (provider) && config != NULL)
-    ide_buildconfig_configuration_provider_track_config ((IdeBuildconfigConfigurationProvider *)provider,
-                                                         (IdeBuildconfigConfiguration *)g_object_ref 
(config));
-}
-
 static void
 ide_configuration_manager_load_cb (GObject      *object,
                                    GAsyncResult *result,
                                    gpointer      user_data)
 {
   IdeConfigurationProvider *provider = (IdeConfigurationProvider *)object;
-  IdeConfigurationManager *self = user_data;
+  g_autoptr(IdeConfigurationManager) self = user_data;
   g_autoptr(GError) error = NULL;
 
   IDE_ENTRY;
@@ -430,41 +433,8 @@ ide_configuration_manager_load_cb (GObject      *object,
   g_assert (G_IS_TASK (result));
 
   if (!ide_configuration_provider_load_finish (provider, result, &error))
-    g_warning ("%s: %s", G_OBJECT_TYPE_NAME (provider), error->message);
-
-  self->providers_loading--;
-  if (self->providers_loading == 0)
-    {
-      IdeConfiguration *default_config;
-      gboolean restored_buildconfig = FALSE;
-
-      for (guint i = 0; i < self->configurations->len; i++)
-        {
-          IdeConfiguration *configuration = g_ptr_array_index (self->configurations, i);
-
-          if (IDE_IS_BUILDCONFIG_CONFIGURATION (configuration) &&
-              g_strcmp0 ("default", ide_configuration_get_id (configuration)) != 0)
-            restored_buildconfig = TRUE;
-        }
-
-      /*
-       * If the default config was added by the manager rather than the provider,
-       * let the provider know about it so changes are persisted to the disk.
-       */
-      default_config = ide_configuration_manager_get_configuration (self, "default");
-      if (!restored_buildconfig)
-        {
-          if (default_config == NULL)
-            {
-              ide_configuration_manager_add_default (self);
-              default_config = ide_configuration_manager_get_configuration (self, "default");
-            }
-
-          peas_extension_set_foreach (self->extensions,
-                                      ide_configuration_manager_track_buildconfig,
-                                      default_config);
-        }
-    }
+    g_warning ("%s failed to initialize: %s",
+               G_OBJECT_TYPE_NAME (provider), error->message);
 
   IDE_EXIT;
 }
@@ -482,12 +452,11 @@ ide_configuration_manager_extension_added (PeasExtensionSet *set,
   g_assert (plugin_info != NULL);
   g_assert (IDE_IS_CONFIGURATION_PROVIDER (provider));
 
-  self->providers_loading++;
   ide_configuration_provider_load_async (provider,
                                          self,
-                                         self->cancellable,
+                                         NULL,
                                          ide_configuration_manager_load_cb,
-                                         self);
+                                         g_object_ref (self));
 }
 
 static void
@@ -507,27 +476,66 @@ ide_configuration_manager_extension_removed (PeasExtensionSet *set,
 }
 
 static void
-ide_configuration_manager_init_worker (GTask        *task,
-                                       gpointer      source_object,
-                                       gpointer      task_data,
-                                       GCancellable *cancellable)
+ide_configuration_manager_init_load_cb (GObject      *object,
+                                        GAsyncResult *result,
+                                        gpointer      user_data)
 {
-  IdeConfigurationManager *self = source_object;
-  g_autoptr(GFile) settings_file = NULL;
+  IdeConfigurationProvider *provider = (IdeConfigurationProvider *)object;
+  IdeConfigurationManager *self;
   g_autoptr(GError) error = NULL;
-  IdeContext *context;
+  g_autoptr(GTask) task = user_data;
+  GPtrArray *providers;
+
+  IDE_ENTRY;
 
+  g_assert (IDE_IS_CONFIGURATION_PROVIDER (provider));
+  g_assert (G_IS_ASYNC_RESULT (result));
   g_assert (G_IS_TASK (task));
+
+  self = g_task_get_source_object (task);
   g_assert (IDE_IS_CONFIGURATION_MANAGER (self));
+
+  if (!ide_configuration_provider_load_finish (provider, result, &error))
+    g_warning ("%s failed to initialize: %s",
+               G_OBJECT_TYPE_NAME (provider), error->message);
+
+  providers = g_task_get_task_data (task);
+  g_assert (providers != NULL);
+  g_assert (providers->len > 0);
+
+  g_ptr_array_remove (providers, provider);
+
+  if (self->configurations->len == 0)
+    ide_configuration_manager_add_default (self);
+
+  if (providers->len == 0)
+    g_task_return_boolean (task, TRUE);
+
+  IDE_EXIT;
+}
+
+static void
+ide_configuration_manager_init_async (GAsyncInitable      *initable,
+                                      gint                 priority,
+                                      GCancellable        *cancellable,
+                                      GAsyncReadyCallback  callback,
+                                      gpointer             user_data)
+{
+  IdeConfigurationManager *self = (IdeConfigurationManager *)initable;
+  g_autoptr(GTask) task = NULL;
+  g_autoptr(GPtrArray) providers = NULL;
+  IdeContext *context;
+
+  g_assert (G_IS_ASYNC_INITABLE (self));
   g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
 
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, ide_configuration_manager_init_async);
+  g_task_set_priority (task, priority);
+
   context = ide_object_get_context (IDE_OBJECT (self));
   g_assert (IDE_IS_CONTEXT (context));
 
-  self->providers_loading = 0;
-
-  self->cancellable = g_cancellable_new ();
-
   self->extensions = peas_extension_set_new (peas_engine_get_default (),
                                              IDE_TYPE_CONFIGURATION_PROVIDER,
                                              NULL);
@@ -542,30 +550,30 @@ ide_configuration_manager_init_worker (GTask        *task,
                     G_CALLBACK (ide_configuration_manager_extension_removed),
                     self);
 
+  providers = g_ptr_array_new_with_free_func (g_object_unref);
   peas_extension_set_foreach (self->extensions,
-                              ide_configuration_manager_extension_added,
-                              self);
-
-  ide_configuration_manager_add_default (self);
-
-  g_task_return_boolean (task, TRUE);
-}
+                              ide_configuration_manager_collect_providers,
+                              providers);
+  g_task_set_task_data (task,
+                        g_ptr_array_ref (providers),
+                        (GDestroyNotify)g_ptr_array_unref);
 
-static void
-ide_configuration_manager_init_async (GAsyncInitable      *initable,
-                                      gint                 priority,
-                                      GCancellable        *cancellable,
-                                      GAsyncReadyCallback  callback,
-                                      gpointer             user_data)
-{
-  IdeConfigurationManager *self = (IdeConfigurationManager *)initable;
-  g_autoptr(GTask) task = NULL;
+  for (guint i = 0; i < providers->len; i++)
+    {
+      IdeConfigurationProvider *provider = g_ptr_array_index (providers, i);
 
-  g_assert (G_IS_ASYNC_INITABLE (self));
-  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+      ide_configuration_provider_load_async (provider,
+                                             self,
+                                             cancellable,
+                                             ide_configuration_manager_init_load_cb,
+                                             g_object_ref (task));
+    }
 
-  task = g_task_new (self, cancellable, callback, user_data);
-  g_task_run_in_thread (task, ide_configuration_manager_init_worker);
+  if (providers->len == 0)
+    {
+      ide_configuration_manager_add_default (self);
+      g_task_return_boolean (task, TRUE);
+    }
 }
 
 static gboolean
@@ -658,18 +666,35 @@ void
 ide_configuration_manager_add (IdeConfigurationManager *self,
                                IdeConfiguration        *configuration)
 {
+  const gchar *config_id;
   guint position;
 
   g_return_if_fail (IDE_IS_CONFIGURATION_MANAGER (self));
   g_return_if_fail (IDE_IS_CONFIGURATION (configuration));
 
+  for (guint i = 0; i < self->configurations->len; i++)
+    {
+      IdeConfiguration *ele = g_ptr_array_index (self->configurations, i);
+
+      /* Do nothing if we already have this. Unlikely to happen but might
+       * be if we got into a weird race with registering default configurations
+       * and receiving a default from a provider.
+       */
+      if (configuration == ele)
+        return;
+    }
+
+  config_id = ide_configuration_get_id (configuration);
+
   /* Allow the default config to be overridden by one from a provider */
-  if (g_strcmp0 ("default", ide_configuration_get_id (configuration)) == 0)
+  if (ide_str_equal0 ("default", config_id))
     {
-      IdeConfiguration *default_config;
-      default_config = ide_configuration_manager_get_configuration (self, "default");
-      if (default_config != NULL)
-        g_ptr_array_remove_fast (self->configurations, default_config);
+      IdeConfiguration *def = ide_configuration_manager_get_configuration (self, "default");
+
+      g_assert (def != configuration);
+
+      if (def != NULL)
+        g_ptr_array_remove_fast (self->configurations, def);
     }
 
   position = self->configurations->len;


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