[gnome-software: 8/14] gs-application: Use asynchronous setup for the plugin loader




commit 5c6f856da9c55dddc732f365dbac43c05231c9d6
Author: Philip Withnall <pwithnall endlessos org>
Date:   Tue Mar 1 14:35:12 2022 +0000

    gs-application: Use asynchronous setup for the plugin loader
    
    This ensures that file monitors and other long-lived objects which
    reference the thread-default `GMainContext` at their time of
    construction, end up referencing the *correct* thread-default
    `GMainContext`.
    
    See the previous commit message for more details.
    
    Signed-off-by: Philip Withnall <pwithnall endlessos org>
    
    Fixes: #1661

 src/gs-application.c | 41 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 36 insertions(+), 5 deletions(-)
---
diff --git a/src/gs-application.c b/src/gs-application.c
index 04f100362..477cce9b9 100644
--- a/src/gs-application.c
+++ b/src/gs-application.c
@@ -159,6 +159,19 @@ gs_application_init (GsApplication *application)
        g_application_add_main_option_entries (G_APPLICATION (application), options);
 }
 
+static void
+async_result_cb (GObject      *source_object,
+                 GAsyncResult *result,
+                 gpointer      user_data)
+{
+       GAsyncResult **result_out = user_data;
+
+       g_assert (*result_out == NULL);
+       *result_out = g_object_ref (result);
+
+       g_main_context_wakeup (g_main_context_get_thread_default ());
+}
+
 static void
 gs_application_initialize_plugins (GsApplication *app)
 {
@@ -167,6 +180,7 @@ gs_application_initialize_plugins (GsApplication *app)
        g_auto(GStrv) plugin_allowlist = NULL;
        g_autoptr(GError) error = NULL;
        const gchar *tmp;
+       g_autoptr(GAsyncResult) setup_result = NULL;
 
        if (initialized)
                return;
@@ -184,11 +198,28 @@ gs_application_initialize_plugins (GsApplication *app)
        app->plugin_loader = gs_plugin_loader_new ();
        if (g_file_test (LOCALPLUGINDIR, G_FILE_TEST_EXISTS))
                gs_plugin_loader_add_location (app->plugin_loader, LOCALPLUGINDIR);
-       if (!gs_plugin_loader_setup (app->plugin_loader,
-                                    plugin_allowlist,
-                                    plugin_blocklist,
-                                    NULL,
-                                    &error)) {
+
+       /* Set up the plugins. Manually iterate the thread-default #GMainContext
+        * at this point to save refactoring all this code to be async (FIXME:
+        * we should do that in future).
+        *
+        * We can’t use gs_plugin_loader_setup() from gs-plugin-loader-sync.c
+        * here because that uses a custom #GMainContext, which means that a lot
+        * of objects in plugins are initialised with the wrong #GMainContext
+        * for subsequent callbacks. */
+       gs_plugin_loader_setup_async (app->plugin_loader,
+                                     (const gchar * const *) plugin_allowlist,
+                                     (const gchar * const *) plugin_blocklist,
+                                     NULL,
+                                     async_result_cb,
+                                     &setup_result);
+
+       while (setup_result == NULL)
+               g_main_context_iteration (g_main_context_get_thread_default (), TRUE);
+
+       if (!gs_plugin_loader_setup_finish (app->plugin_loader,
+                                           setup_result,
+                                           &error)) {
                g_warning ("Failed to setup plugins: %s", error->message);
                exit (1);
        }


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