[gnome-software] appstream plugin: Fix crashes due to concurrent appstream store access



commit 8b66892c433a82c00ec3ee93d919773474a71c3d
Author: Kalev Lember <kalevlember gmail com>
Date:   Sat Jun 6 21:01:46 2015 +0200

    appstream plugin: Fix crashes due to concurrent appstream store access
    
    Use a mutex to serialize access to priv->store to make sure that we
    don't have one thread modifying the store and another thread trying to
    read from it at the same time. This could happen for instance when the
    AsStore file monitors detect that the data has changed and reload and
    the plugin is accessing the AsStore at the same time.
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1226585
    https://bugzilla.redhat.com/show_bug.cgi?id=1210989
    https://bugzilla.redhat.com/show_bug.cgi?id=1183772
    https://bugzilla.redhat.com/show_bug.cgi?id=1177618
    https://bugzilla.redhat.com/show_bug.cgi?id=1177235
    https://bugzilla.redhat.com/show_bug.cgi?id=1176343
    https://bugzilla.redhat.com/show_bug.cgi?id=1176298
    https://bugzilla.redhat.com/show_bug.cgi?id=1164179
    https://bugzilla.redhat.com/show_bug.cgi?id=1155344

 src/plugins/gs-plugin-appstream.c |   24 ++++++++++++++++++++++--
 1 files changed, 22 insertions(+), 2 deletions(-)
---
diff --git a/src/plugins/gs-plugin-appstream.c b/src/plugins/gs-plugin-appstream.c
index cb5cebe..441d3dd 100644
--- a/src/plugins/gs-plugin-appstream.c
+++ b/src/plugins/gs-plugin-appstream.c
@@ -32,6 +32,7 @@
 
 struct GsPluginPrivate {
        AsStore                 *store;
+       GMutex                   store_mutex;
        gchar                   *locale;
        gsize                    done_init;
        gboolean                 has_hi_dpi_support;
@@ -88,6 +89,7 @@ void
 gs_plugin_initialize (GsPlugin *plugin)
 {
        plugin->priv = GS_PLUGIN_GET_PRIVATE (GsPluginPrivate);
+       g_mutex_init (&plugin->priv->store_mutex);
        plugin->priv->store = as_store_new ();
        g_signal_connect (plugin->priv->store, "changed",
                          G_CALLBACK (gs_plugin_appstream_store_changed_cb),
@@ -120,6 +122,7 @@ gs_plugin_destroy (GsPlugin *plugin)
 {
        g_free (plugin->priv->locale);
        g_object_unref (plugin->priv->store);
+       g_mutex_clear (&plugin->priv->store_mutex);
 }
 
 /**
@@ -666,6 +669,8 @@ gs_plugin_refine_from_id (GsPlugin *plugin,
        gboolean ret = TRUE;
        AsApp *item = NULL;
 
+       g_mutex_lock (&plugin->priv->store_mutex);
+
        /* find anything that matches the ID */
        id = gs_app_get_id (app);
        if (id == NULL)
@@ -679,6 +684,7 @@ gs_plugin_refine_from_id (GsPlugin *plugin,
        if (!ret)
                goto out;
 out:
+       g_mutex_unlock (&plugin->priv->store_mutex);
        *found = (item != NULL);
        return ret;
 }
@@ -693,9 +699,12 @@ gs_plugin_refine_from_pkgname (GsPlugin *plugin,
 {
        AsApp *item = NULL;
        GPtrArray *sources;
+       gboolean ret = TRUE;
        const gchar *pkgname;
        guint i;
 
+       g_mutex_lock (&plugin->priv->store_mutex);
+
        /* find anything that matches the ID */
        sources = gs_app_get_sources (app);
        for (i = 0; i < sources->len && item == NULL; i++) {
@@ -708,10 +717,13 @@ gs_plugin_refine_from_pkgname (GsPlugin *plugin,
 
        /* nothing found */
        if (item == NULL)
-               return TRUE;
+               goto out;
 
        /* set new properties */
-       return gs_plugin_refine_item (plugin, app, item, error);
+       ret = gs_plugin_refine_item (plugin, app, item, error);
+out:
+       g_mutex_unlock (&plugin->priv->store_mutex);
+       return ret;
 }
 
 /**
@@ -785,6 +797,7 @@ gs_plugin_add_category_apps (GsPlugin *plugin,
 
        /* get the two search terms */
        gs_profile_start (plugin->profile, "appstream::add-category-apps");
+       g_mutex_lock (&plugin->priv->store_mutex);
        search_id1 = gs_category_get_id (category);
        parent = gs_category_get_parent (category);
        if (parent != NULL)
@@ -816,6 +829,7 @@ gs_plugin_add_category_apps (GsPlugin *plugin,
                gs_plugin_add_app (list, app);
        }
 out:
+       g_mutex_unlock (&plugin->priv->store_mutex);
        gs_profile_stop (plugin->profile, "appstream::add-category-apps");
        return ret;
 }
@@ -919,6 +933,7 @@ gs_plugin_add_search (GsPlugin *plugin,
 
        /* search categories for the search term */
        gs_profile_start (plugin->profile, "appstream::search");
+       g_mutex_lock (&plugin->priv->store_mutex);
        array = as_store_get_apps (plugin->priv->store);
        for (i = 0; i < array->len; i++) {
                if (g_cancellable_set_error_if_cancelled (cancellable, error))
@@ -930,6 +945,7 @@ gs_plugin_add_search (GsPlugin *plugin,
                        goto out;
        }
 out:
+       g_mutex_unlock (&plugin->priv->store_mutex);
        gs_profile_stop (plugin->profile, "appstream::search");
        return ret;
 }
@@ -958,6 +974,7 @@ gs_plugin_add_installed (GsPlugin *plugin,
 
        /* search categories for the search term */
        gs_profile_start (plugin->profile, "appstream::add_installed");
+       g_mutex_lock (&plugin->priv->store_mutex);
        array = as_store_get_apps (plugin->priv->store);
        for (i = 0; i < array->len; i++) {
                item = g_ptr_array_index (array, i);
@@ -971,6 +988,7 @@ gs_plugin_add_installed (GsPlugin *plugin,
                }
        }
 out:
+       g_mutex_unlock (&plugin->priv->store_mutex);
        gs_profile_stop (plugin->profile, "appstream::add_installed");
        return ret;
 }
@@ -1044,6 +1062,7 @@ gs_plugin_add_categories (GsPlugin *plugin,
 
        /* find out how many packages are in each category */
        gs_profile_start (plugin->profile, "appstream::add-categories");
+       g_mutex_lock (&plugin->priv->store_mutex);
        array = as_store_get_apps (plugin->priv->store);
        for (i = 0; i < array->len; i++) {
                app = g_ptr_array_index (array, i);
@@ -1053,6 +1072,7 @@ gs_plugin_add_categories (GsPlugin *plugin,
                        continue;
                gs_plugin_add_categories_for_app (*list, app);
        }
+       g_mutex_unlock (&plugin->priv->store_mutex);
        gs_profile_stop (plugin->profile, "appstream::add-categories");
        return ret;
 }


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