Commit d4274572 authored by Richard Hughes's avatar Richard Hughes Committed by Kalev Lember

Add mutexes to protect access to PkClient and PkTask

This fixes the GUI hanging in an unresponsive state. The libpackagekit-glib
library isn't as thread safe as we'd like, and although we can fix PK to be
safer we can't depend on that very new version just yet.
parent d528ca6e
Pipeline #58448 passed with stage
in 4 minutes and 31 seconds
......@@ -18,12 +18,15 @@
struct GsPluginData {
PkTask *task;
GMutex task_mutex;
};
void
gs_plugin_initialize (GsPlugin *plugin)
{
GsPluginData *priv = gs_plugin_alloc_data (plugin, sizeof(GsPluginData));
g_mutex_init (&priv->task_mutex);
priv->task = pk_task_new ();
pk_client_set_background (PK_CLIENT (priv->task), FALSE);
}
......@@ -32,6 +35,7 @@ void
gs_plugin_destroy (GsPlugin *plugin)
{
GsPluginData *priv = gs_plugin_get_data (plugin);
g_mutex_clear (&priv->task_mutex);
g_object_unref (priv->task);
}
......@@ -51,6 +55,11 @@ gs_plugin_packagekit_refresh_guess_app_id (GsPlugin *plugin,
g_auto(GStrv) files = NULL;
g_autoptr(PkResults) results = NULL;
g_autoptr(GPtrArray) array = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
/* get file list so we can work out ID */
files = g_strsplit (filename, "\t", -1);
......@@ -128,6 +137,7 @@ gs_plugin_file_to_app (GsPlugin *plugin,
g_auto(GStrv) split = NULL;
g_autoptr(GPtrArray) array = NULL;
g_autoptr(GsApp) app = NULL;
g_autoptr(GMutexLocker) locker = NULL;
const gchar *mimetypes[] = {
"application/x-app-package",
"application/x-deb",
......@@ -143,6 +153,10 @@ gs_plugin_file_to_app (GsPlugin *plugin,
if (!g_strv_contains (mimetypes, content_type))
return TRUE;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
/* get details */
filename = g_file_get_path (file);
files = g_strsplit (filename, "\t", -1);
......
......@@ -24,12 +24,15 @@
struct GsPluginData {
PkClient *client;
GMutex client_mutex;
};
void
gs_plugin_initialize (GsPlugin *plugin)
{
GsPluginData *priv = gs_plugin_alloc_data (plugin, sizeof(GsPluginData));
g_mutex_init (&priv->client_mutex);
priv->client = pk_client_new ();
pk_client_set_background (priv->client, FALSE);
pk_client_set_cache_age (priv->client, G_MAXUINT);
......@@ -42,6 +45,7 @@ void
gs_plugin_destroy (GsPlugin *plugin)
{
GsPluginData *priv = gs_plugin_get_data (plugin);
g_mutex_clear (&priv->client_mutex);
g_object_unref (priv->client);
}
......@@ -57,6 +61,11 @@ gs_plugin_packagekit_refine_repo_from_filename (GsPlugin *plugin,
g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
g_autoptr(PkResults) results = NULL;
g_autoptr(GPtrArray) packages = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->client_mutex);
g_assert (locker != NULL);
to_array[0] = filename;
gs_packagekit_helper_add_app (helper, app);
......
......@@ -27,6 +27,7 @@
struct GsPluginData {
PkControl *control;
PkClient *client;
GMutex client_mutex;
};
static void
......@@ -45,6 +46,8 @@ void
gs_plugin_initialize (GsPlugin *plugin)
{
GsPluginData *priv = gs_plugin_alloc_data (plugin, sizeof(GsPluginData));
g_mutex_init (&priv->client_mutex);
priv->client = pk_client_new ();
priv->control = pk_control_new ();
g_signal_connect (priv->control, "updates-changed",
......@@ -63,6 +66,7 @@ void
gs_plugin_destroy (GsPlugin *plugin)
{
GsPluginData *priv = gs_plugin_get_data (plugin);
g_mutex_clear (&priv->client_mutex);
g_object_unref (priv->client);
g_object_unref (priv->control);
}
......@@ -95,6 +99,7 @@ gs_plugin_packagekit_resolve_packages_with_filter (GsPlugin *plugin,
g_autoptr(PkResults) results = NULL;
g_autoptr(GPtrArray) package_ids = NULL;
g_autoptr(GPtrArray) packages = NULL;
g_autoptr(GMutexLocker) locker = NULL;
package_ids = g_ptr_array_new_with_free_func (g_free);
for (i = 0; i < gs_app_list_length (list); i++) {
......@@ -115,6 +120,10 @@ gs_plugin_packagekit_resolve_packages_with_filter (GsPlugin *plugin,
return TRUE;
g_ptr_array_add (package_ids, NULL);
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->client_mutex);
g_assert (locker != NULL);
/* resolve them all at once */
results = pk_client_resolve (priv->client,
filter,
......@@ -202,6 +211,11 @@ gs_plugin_packagekit_refine_from_desktop (GsPlugin *plugin,
g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
g_autoptr(PkResults) results = NULL;
g_autoptr(GPtrArray) packages = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->client_mutex);
g_assert (locker != NULL);
to_array[0] = filename;
gs_packagekit_helper_add_app (helper, app);
......@@ -272,6 +286,7 @@ gs_plugin_packagekit_refine_updatedetails (GsPlugin *plugin,
g_autofree const gchar **package_ids = NULL;
g_autoptr(PkResults) results = NULL;
g_autoptr(GPtrArray) array = NULL;
g_autoptr(GMutexLocker) locker = NULL;
package_ids = g_new0 (const gchar *, gs_app_list_length (list) + 1);
for (guint i = 0; i < gs_app_list_length (list); i++) {
......@@ -285,6 +300,10 @@ gs_plugin_packagekit_refine_updatedetails (GsPlugin *plugin,
if (cnt == 0)
return TRUE;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->client_mutex);
g_assert (locker != NULL);
/* get any update details */
results = pk_client_get_update_detail (priv->client,
(gchar **) package_ids,
......@@ -334,6 +353,7 @@ gs_plugin_packagekit_refine_details2 (GsPlugin *plugin,
g_autoptr(GPtrArray) array = NULL;
g_autoptr(GPtrArray) package_ids = NULL;
g_autoptr(PkResults) results = NULL;
g_autoptr(GMutexLocker) locker = NULL;
package_ids = g_ptr_array_new_with_free_func (g_free);
for (i = 0; i < gs_app_list_length (list); i++) {
......@@ -348,6 +368,10 @@ gs_plugin_packagekit_refine_details2 (GsPlugin *plugin,
return TRUE;
g_ptr_array_add (package_ids, NULL);
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->client_mutex);
g_assert (locker != NULL);
/* get any details */
results = pk_client_get_details (priv->client,
(gchar **) package_ids->pdata,
......@@ -385,11 +409,16 @@ gs_plugin_packagekit_refine_update_urgency (GsPlugin *plugin,
g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
g_autoptr(PkPackageSack) sack = NULL;
g_autoptr(PkResults) results = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* not required */
if ((flags & GS_PLUGIN_REFINE_FLAGS_REQUIRE_UPDATE_SEVERITY) == 0)
return TRUE;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->client_mutex);
g_assert (locker != NULL);
/* get the list of updates */
filter = pk_bitfield_value (PK_FILTER_ENUM_NONE);
results = pk_client_get_updates (priv->client,
......@@ -564,11 +593,16 @@ gs_plugin_packagekit_refine_distro_upgrade (GsPlugin *plugin,
GsPluginData *priv = gs_plugin_get_data (plugin);
guint i;
GsApp *app2;
g_autoptr(GMutexLocker) locker = NULL;
g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
g_autoptr(PkResults) results = NULL;
g_autoptr(GsAppList) list = NULL;
guint cache_age_save;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->client_mutex);
g_assert (locker != NULL);
/* ask PK to simulate upgrading the system */
cache_age_save = pk_client_get_cache_age (priv->client);
pk_client_set_cache_age (priv->client, 60 * 60 * 24 * 7); /* once per week */
......
......@@ -22,12 +22,15 @@
struct GsPluginData {
PkTask *task;
GMutex task_mutex;
};
void
gs_plugin_initialize (GsPlugin *plugin)
{
GsPluginData *priv = gs_plugin_alloc_data (plugin, sizeof(GsPluginData));
g_mutex_init (&priv->task_mutex);
priv->task = pk_task_new ();
pk_task_set_only_download (priv->task, TRUE);
pk_client_set_background (PK_CLIENT (priv->task), TRUE);
......@@ -40,6 +43,7 @@ void
gs_plugin_destroy (GsPlugin *plugin)
{
GsPluginData *priv = gs_plugin_get_data (plugin);
g_mutex_clear (&priv->task_mutex);
g_object_unref (priv->task);
}
......@@ -53,6 +57,11 @@ _download_only (GsPlugin *plugin, GsAppList *list,
g_autoptr(PkPackageSack) sack = NULL;
g_autoptr(PkResults) results2 = NULL;
g_autoptr(PkResults) results = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
/* never refresh the metadata here as this can surprise the frontend if
* we end up downloading a different set of packages than what was
......@@ -134,6 +143,11 @@ gs_plugin_refresh (GsPlugin *plugin,
g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
g_autoptr(GsApp) app_dl = gs_app_new (gs_plugin_get_name (plugin));
g_autoptr(PkResults) results = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
/* cache age of 1 is user-initiated */
pk_client_set_background (PK_CLIENT (priv->task), cache_age > 1);
......
......@@ -17,12 +17,15 @@
struct GsPluginData {
PkTask *task;
GMutex task_mutex;
};
void
gs_plugin_initialize (GsPlugin *plugin)
{
GsPluginData *priv = gs_plugin_alloc_data (plugin, sizeof(GsPluginData));
g_mutex_init (&priv->task_mutex);
priv->task = pk_task_new ();
pk_task_set_only_download (priv->task, TRUE);
pk_client_set_background (PK_CLIENT (priv->task), TRUE);
......@@ -33,6 +36,7 @@ void
gs_plugin_destroy (GsPlugin *plugin)
{
GsPluginData *priv = gs_plugin_get_data (plugin);
g_mutex_clear (&priv->task_mutex);
g_object_unref (priv->task);
}
......@@ -52,6 +56,7 @@ gs_plugin_app_upgrade_download (GsPlugin *plugin,
GsPluginData *priv = gs_plugin_get_data (plugin);
g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
g_autoptr(PkResults) results = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* only process this app if was created by this plugin */
if (g_strcmp0 (gs_app_get_management_plugin (app), "packagekit") != 0)
......@@ -61,6 +66,10 @@ gs_plugin_app_upgrade_download (GsPlugin *plugin,
if (gs_app_get_kind (app) != AS_APP_KIND_OS_UPGRADE)
return TRUE;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
/* ask PK to download enough packages to upgrade the system */
gs_app_set_state (app, AS_APP_STATE_INSTALLING);
gs_packagekit_helper_add_app (helper, app);
......
......@@ -15,12 +15,15 @@
struct GsPluginData {
PkClient *client;
GMutex client_mutex;
};
void
gs_plugin_initialize (GsPlugin *plugin)
{
GsPluginData *priv = gs_plugin_alloc_data (plugin, sizeof(GsPluginData));
g_mutex_init (&priv->client_mutex);
priv->client = pk_client_new ();
pk_client_set_background (priv->client, FALSE);
......@@ -31,6 +34,7 @@ void
gs_plugin_destroy (GsPlugin *plugin)
{
GsPluginData *priv = gs_plugin_get_data (plugin);
g_mutex_clear (&priv->client_mutex);
g_object_unref (priv->client);
}
......@@ -53,6 +57,7 @@ gs_plugin_url_to_app (GsPlugin *plugin,
g_autoptr(GsOsRelease) os_release = NULL;
g_autoptr(GPtrArray) packages = NULL;
g_autoptr(GPtrArray) details = NULL;
g_autoptr(GMutexLocker) locker = NULL;
g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
path = gs_utils_get_url_path (url);
......@@ -79,9 +84,12 @@ gs_plugin_url_to_app (GsPlugin *plugin,
gs_app_set_kind (app, AS_APP_KIND_GENERIC);
gs_app_set_bundle_kind (app, AS_BUNDLE_KIND_PACKAGE);
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->client_mutex);
g_assert (locker != NULL);
package_ids = g_new0 (gchar *, 2);
package_ids[0] = g_strdup (path);
results = pk_client_resolve (priv->client,
pk_bitfield_from_enums (PK_FILTER_ENUM_NEWEST, PK_FILTER_ENUM_ARCH, -1),
package_ids,
......
......@@ -26,12 +26,15 @@
struct GsPluginData {
PkTask *task;
GMutex task_mutex;
};
void
gs_plugin_initialize (GsPlugin *plugin)
{
GsPluginData *priv = gs_plugin_alloc_data (plugin, sizeof(GsPluginData));
g_mutex_init (&priv->task_mutex);
priv->task = pk_task_new ();
pk_client_set_background (PK_CLIENT (priv->task), FALSE);
pk_client_set_cache_age (PK_CLIENT (priv->task), G_MAXUINT);
......@@ -41,6 +44,7 @@ void
gs_plugin_destroy (GsPlugin *plugin)
{
GsPluginData *priv = gs_plugin_get_data (plugin);
g_mutex_clear (&priv->task_mutex);
g_object_unref (priv->task);
}
......@@ -60,6 +64,11 @@ gs_plugin_add_sources_related (GsPlugin *plugin,
gboolean ret = TRUE;
g_autoptr(GsAppList) installed = gs_app_list_new ();
g_autoptr(PkResults) results = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
filter = pk_bitfield_from_enums (PK_FILTER_ENUM_INSTALLED,
PK_FILTER_ENUM_NEWEST,
......@@ -121,6 +130,11 @@ gs_plugin_add_sources (GsPlugin *plugin,
g_autoptr(GHashTable) hash = NULL;
g_autoptr(PkResults) results = NULL;
g_autoptr(GPtrArray) array = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
/* ask PK for the repo details */
filter = pk_bitfield_from_enums (PK_FILTER_ENUM_NOT_SOURCE,
......@@ -173,6 +187,11 @@ gs_plugin_app_origin_repo_enable (GsPlugin *plugin,
GsPluginData *priv = gs_plugin_get_data (plugin);
g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
g_autoptr(PkResults) results = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
/* do sync call */
gs_plugin_status_update (plugin, app, GS_PLUGIN_STATUS_WAITING);
......@@ -203,6 +222,11 @@ gs_plugin_repo_enable (GsPlugin *plugin,
GsPluginData *priv = gs_plugin_get_data (plugin);
g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
g_autoptr(PkResults) results = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
/* do sync call */
gs_plugin_status_update (plugin, app, GS_PLUGIN_STATUS_WAITING);
......@@ -242,6 +266,7 @@ gs_plugin_app_install (GsPlugin *plugin,
g_auto(GStrv) package_ids = NULL;
g_autoptr(GPtrArray) array_package_ids = NULL;
g_autoptr(PkResults) results = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* only process this app if was created by this plugin */
if (g_strcmp0 (gs_app_get_management_plugin (app),
......@@ -282,6 +307,10 @@ gs_plugin_app_install (GsPlugin *plugin,
* is probably some kind of hard-to-debug race in the daemon. */
g_usleep (G_USEC_PER_SEC * 3);
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
/* actually install the package */
gs_packagekit_helper_add_app (helper, app);
results = pk_task_install_packages_sync (priv->task,
......@@ -350,6 +379,11 @@ gs_plugin_app_install (GsPlugin *plugin,
"no packages to install");
return FALSE;
}
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
gs_app_set_state (app, AS_APP_STATE_INSTALLING);
addons = gs_app_get_addons (app);
for (i = 0; i < gs_app_list_length (addons); i++) {
......@@ -382,6 +416,11 @@ gs_plugin_app_install (GsPlugin *plugin,
}
local_filename = g_file_get_path (gs_app_get_local_file (app));
package_ids = g_strsplit (local_filename, "\t", -1);
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
gs_app_set_state (app, AS_APP_STATE_INSTALLING);
gs_packagekit_helper_add_app (helper, app);
results = pk_task_install_files_sync (priv->task,
......@@ -426,6 +465,11 @@ gs_plugin_repo_disable (GsPlugin *plugin,
GsPluginData *priv = gs_plugin_get_data (plugin);
g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
g_autoptr(PkResults) results = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
/* do sync call */
gs_plugin_status_update (plugin, app, GS_PLUGIN_STATUS_WAITING);
......@@ -463,6 +507,7 @@ gs_plugin_app_remove (GsPlugin *plugin,
guint cnt = 0;
g_autoptr(PkResults) results = NULL;
g_auto(GStrv) package_ids = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* only process this app if was created by this plugin */
if (g_strcmp0 (gs_app_get_management_plugin (app),
......@@ -497,6 +542,10 @@ gs_plugin_app_remove (GsPlugin *plugin,
return FALSE;
}
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
/* do the action */
gs_app_set_state (app, AS_APP_STATE_REMOVING);
gs_packagekit_helper_add_app (helper, app);
......@@ -556,6 +605,11 @@ gs_plugin_add_updates (GsPlugin *plugin,
g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
g_autoptr(PkResults) results = NULL;
g_autoptr(GPtrArray) array = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
/* do sync call */
gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_WAITING);
......@@ -589,6 +643,11 @@ gs_plugin_add_search_files (GsPlugin *plugin,
PkBitfield filter;
g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
g_autoptr(PkResults) results = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
/* do sync call */
gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_WAITING);
......@@ -619,6 +678,11 @@ gs_plugin_add_search_what_provides (GsPlugin *plugin,
PkBitfield filter;
g_autoptr(GsPackagekitHelper) helper = gs_packagekit_helper_new (plugin);
g_autoptr(PkResults) results = NULL;
g_autoptr(GMutexLocker) locker = NULL;
/* packagekit-glib is not threadsafe */
locker = g_mutex_locker_new (&priv->task_mutex);
g_assert (locker != NULL);
/* do sync call */
gs_plugin_status_update (plugin, NULL, GS_PLUGIN_STATUS_WAITING);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment