Compare commits

..

9 commits

Author SHA1 Message Date
Milan Crha
4891bb80d5 Update to 47.5 2025-03-14 09:51:03 +01:00
Milan Crha
9b97c98178 Update to 47.4 2025-01-14 18:54:52 +01:00
Milan Crha
ee9cb23a37 Update to 47.3 2025-01-07 08:59:45 +01:00
Milan Crha
87cb53a57a Resolves: #2272232 (Crash under gs_appstream_gather_merge_data()) 2024-12-09 11:00:18 +01:00
Milan Crha
3603a80e6c Update to 47.2 2024-11-25 14:37:30 +01:00
Milan Crha
3f8b665d79 Update to 47.1 2024-10-10 15:03:49 +02:00
Milan Crha
e2f28fc62c Resolves: #2312882 (dkms: Fix callback user data in a reload() function) 2024-09-19 13:02:38 +02:00
Milan Crha
9d793c2bdf Update to 47.0 2024-09-13 09:55:38 +02:00
Milan Crha
75782b9e8c Update to 47.rc 2024-08-30 11:33:20 +02:00
8 changed files with 2475 additions and 7550 deletions

1
.gitignore vendored
View file

@ -1,2 +1 @@
/gnome-software-*.tar.xz
/gnome-software-*-build

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,686 +0,0 @@
From 0c79d9fb08a348a45a18f15427c945a63b44982e Mon Sep 17 00:00:00 2001
Date: Mon, 24 Nov 2025 16:06:51 +0100
Subject: [PATCH 1/3] flatpak: Fix XbSilo lifetime in
gs_flatpak_refine_wildcard()
The function uses pre-cached data in the hash tables, consisting of XbNode-s
from an XbSilo. The nodes are referenced, but the silos the node belongs to
is not referenced (by the XbNode).
This change keeps the XbSilo alive as long as it's needed for the nodes
in the pre-cached data. It also does not call gs_flatpak_ref_silo() multiple
times for the same GsFlatpak instance, which could invalidate the XbNode-s
in the pre-cached data when a change in the silo or in the installation
had been received while the function was still processing the apps.
Related downstream bug https://bugzilla.redhat.com/show_bug.cgi?id=2416542
Closes https://gitlab.gnome.org/GNOME/gnome-software/-/issues/2900
---
plugins/flatpak/gs-flatpak.c | 18 ++++++++---
plugins/flatpak/gs-flatpak.h | 4 +++
plugins/flatpak/gs-plugin-flatpak.c | 49 ++++++++++++++++++++---------
3 files changed, 51 insertions(+), 20 deletions(-)
diff --git a/plugins/flatpak/gs-flatpak.c b/plugins/flatpak/gs-flatpak.c
index b409475c7..a40ab54fb 100644
--- a/plugins/flatpak/gs-flatpak.c
+++ b/plugins/flatpak/gs-flatpak.c
@@ -3748,16 +3748,19 @@ gboolean
gs_flatpak_refine_wildcard (GsFlatpak *self, GsApp *app,
GsAppList *list, GsPluginRefineRequireFlags require_flags,
gboolean interactive,
+ XbSilo **inout_silo,
+ gchar **inout_silo_filename,
+ GHashTable **inout_installed_by_desktopid,
GHashTable **inout_components_by_id,
GHashTable **inout_components_by_bundle,
GCancellable *cancellable, GError **error)
{
const gchar *id;
GPtrArray* components = NULL;
+ XbSilo *silo;
+ GHashTable *silo_installed_by_desktopid;
+ const gchar *silo_filename;
g_autoptr(GError) error_local = NULL;
- g_autoptr(XbSilo) silo = NULL;
- g_autoptr(GHashTable) silo_installed_by_desktopid = NULL;
- g_autofree gchar *silo_filename = NULL;
GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcard, "Flatpak (refine wildcard)", NULL);
@@ -3766,10 +3769,15 @@ gs_flatpak_refine_wildcard (GsFlatpak *self, GsApp *app,
if (id == NULL)
return TRUE;
- silo = gs_flatpak_ref_silo (self, interactive, &silo_filename, &silo_installed_by_desktopid, cancellable, error);
- if (silo == NULL)
+ if (*inout_silo == NULL)
+ *inout_silo = gs_flatpak_ref_silo (self, interactive, inout_silo_filename, inout_installed_by_desktopid, cancellable, error);
+ if (*inout_silo == NULL)
return FALSE;
+ silo = *inout_silo;
+ silo_filename = *inout_silo_filename;
+ silo_installed_by_desktopid = *inout_installed_by_desktopid;
+
GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardQuerySilo, "Flatpak (query silo)", NULL);
if (*inout_components_by_id != NULL) {
diff --git a/plugins/flatpak/gs-flatpak.h b/plugins/flatpak/gs-flatpak.h
index 66ff59967..34e1416b5 100644
--- a/plugins/flatpak/gs-flatpak.h
+++ b/plugins/flatpak/gs-flatpak.h
@@ -11,6 +11,7 @@
#include <gnome-software.h>
#include <flatpak.h>
+#include <xmlb.h>
G_BEGIN_DECLS
@@ -108,6 +109,9 @@ gboolean gs_flatpak_refine_wildcard (GsFlatpak *self,
GsAppList *list,
GsPluginRefineRequireFlags require_flags,
gboolean interactive,
+ XbSilo **inout_silo,
+ gchar **inout_silo_filename,
+ GHashTable **inout_installed_by_desktopid,
GHashTable **inout_components_by_id,
GHashTable **inout_components_by_bundle,
GCancellable *cancellable,
diff --git a/plugins/flatpak/gs-plugin-flatpak.c b/plugins/flatpak/gs-plugin-flatpak.c
index 3d0503d46..f5d4a1d67 100644
--- a/plugins/flatpak/gs-plugin-flatpak.c
+++ b/plugins/flatpak/gs-plugin-flatpak.c
@@ -667,12 +667,29 @@ gs_plugin_flatpak_refine_app (GsPluginFlatpak *self,
return gs_flatpak_refine_app (flatpak, app, require_flags, interactive, FALSE, event_callback, event_user_data, cancellable, error);
}
+typedef struct {
+ XbSilo *silo;
+ gchar *silo_filename;
+ GHashTable *installed_by_desktopid;
+ GHashTable *components_by_id;
+ GHashTable *components_by_bundle;
+} RefineInstallationData;
+
static void
-unref_nonnull_hash_table (gpointer ptr)
+refine_installation_data_free (gpointer ptr)
{
- GHashTable *hash_table = ptr;
- if (hash_table != NULL)
- g_hash_table_unref (hash_table);
+ RefineInstallationData *data = ptr;
+
+ if (data == NULL)
+ return;
+
+ g_clear_pointer (&data->silo_filename, g_free);
+ g_clear_pointer (&data->installed_by_desktopid, g_hash_table_unref);
+ g_clear_pointer (&data->components_by_id, g_hash_table_unref);
+ g_clear_pointer (&data->components_by_bundle, g_hash_table_unref);
+ /* free the silo as the last, just in case, because the data from it is in the above hash tables */
+ g_clear_object (&data->silo);
+ g_free (data);
}
static gboolean
@@ -761,8 +778,7 @@ refine_thread_cb (GTask *task,
gboolean interactive = (data->job_flags & GS_PLUGIN_REFINE_FLAGS_INTERACTIVE) != 0;
GsPluginEventCallback event_callback = data->event_callback;
void *event_user_data = data->event_user_data;
- g_autoptr(GPtrArray) array_components_by_id = NULL; /* (element-type GHashTable) */
- g_autoptr(GPtrArray) array_components_by_bundle = NULL; /* (element-type GHashTable) */
+ g_autoptr(GPtrArray) installation_data = NULL; /* (element-type RefineInstallationData) */
g_autoptr(GsAppList) app_list = NULL;
g_autoptr(GError) local_error = NULL;
@@ -783,10 +799,9 @@ refine_thread_cb (GTask *task,
* (e.g. inserting an app in the list on every call results in
* an infinite loop) */
app_list = gs_app_list_copy (list);
- array_components_by_id = g_ptr_array_new_full (self->installations->len, unref_nonnull_hash_table);
- g_ptr_array_set_size (array_components_by_id, self->installations->len);
- array_components_by_bundle = g_ptr_array_new_full (self->installations->len, unref_nonnull_hash_table);
- g_ptr_array_set_size (array_components_by_bundle, self->installations->len);
+
+ installation_data = g_ptr_array_new_full (self->installations->len, refine_installation_data_free);
+ g_ptr_array_set_size (installation_data, self->installations->len);
for (guint j = 0; j < gs_app_list_length (app_list); j++) {
GsApp *app = gs_app_list_index (app_list, j);
@@ -796,16 +811,20 @@ refine_thread_cb (GTask *task,
for (guint i = 0; i < self->installations->len; i++) {
GsFlatpak *flatpak = g_ptr_array_index (self->installations, i);
- GHashTable *components_by_id = array_components_by_id->pdata[i];
- GHashTable *components_by_bundle = array_components_by_bundle->pdata[i];
+ RefineInstallationData *inst_data = g_ptr_array_index (installation_data, i);
+
+ if (inst_data == NULL) {
+ inst_data = g_new0 (RefineInstallationData, 1);
+ installation_data->pdata[i] = inst_data;
+ }
- if (!gs_flatpak_refine_wildcard (flatpak, app, list, require_flags, interactive, &components_by_id, &components_by_bundle,
+ if (!gs_flatpak_refine_wildcard (flatpak, app, list, require_flags, interactive, &inst_data->silo,
+ &inst_data->silo_filename, &inst_data->installed_by_desktopid,
+ &inst_data->components_by_id, &inst_data->components_by_bundle,
cancellable, &local_error)) {
g_task_return_error (task, g_steal_pointer (&local_error));
return;
}
- array_components_by_id->pdata[i] = components_by_id;
- array_components_by_bundle->pdata[i] = components_by_bundle;
}
}
--
GitLab
From 546c6ee17b5959d2a696a6cb346a1f8b94aba303 Mon Sep 17 00:00:00 2001
Date: Wed, 7 Jan 2026 18:37:52 +0100
Subject: [PATCH 2/3] flatpak: Simplify wildcard app lookup function
By flipping the order of traversing app and installation the code
can be simplified to not have too many in/out arguments.
Suggested by Philip Withnall
---
plugins/flatpak/gs-flatpak.c | 251 ++++++++++++++--------------
plugins/flatpak/gs-flatpak.h | 9 +-
plugins/flatpak/gs-plugin-flatpak.c | 61 +------
3 files changed, 130 insertions(+), 191 deletions(-)
diff --git a/plugins/flatpak/gs-flatpak.c b/plugins/flatpak/gs-flatpak.c
index a40ab54fb..782b0bb48 100644
--- a/plugins/flatpak/gs-flatpak.c
+++ b/plugins/flatpak/gs-flatpak.c
@@ -3745,167 +3745,158 @@ gs_flatpak_refine_app (GsFlatpak *self,
}
gboolean
-gs_flatpak_refine_wildcard (GsFlatpak *self, GsApp *app,
- GsAppList *list, GsPluginRefineRequireFlags require_flags,
- gboolean interactive,
- XbSilo **inout_silo,
- gchar **inout_silo_filename,
- GHashTable **inout_installed_by_desktopid,
- GHashTable **inout_components_by_id,
- GHashTable **inout_components_by_bundle,
- GCancellable *cancellable, GError **error)
+gs_flatpak_refine_wildcards (GsFlatpak *self,
+ GPtrArray *wildcard_apps,
+ GsAppList *list,
+ GsPluginRefineRequireFlags require_flags,
+ gboolean interactive,
+ GCancellable *cancellable,
+ GError **error)
{
- const gchar *id;
- GPtrArray* components = NULL;
- XbSilo *silo;
- GHashTable *silo_installed_by_desktopid;
- const gchar *silo_filename;
g_autoptr(GError) error_local = NULL;
+ g_autoptr(XbSilo) silo = NULL;
+ g_autoptr(GHashTable) silo_installed_by_desktopid = NULL;
+ g_autoptr(GHashTable) components_by_id = NULL;
+ g_autoptr(GHashTable) components_by_bundle = NULL;
+ g_autoptr(GPtrArray) components_with_id = NULL;
+ g_autoptr(GPtrArray) bundles = NULL;
+ g_autofree gchar *silo_filename = NULL;
GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcard, "Flatpak (refine wildcard)", NULL);
- /* not enough info to find */
- id = gs_app_get_id (app);
- if (id == NULL)
- return TRUE;
-
- if (*inout_silo == NULL)
- *inout_silo = gs_flatpak_ref_silo (self, interactive, inout_silo_filename, inout_installed_by_desktopid, cancellable, error);
- if (*inout_silo == NULL)
+ silo = gs_flatpak_ref_silo (self, interactive, &silo_filename, &silo_installed_by_desktopid, cancellable, error);
+ if (silo == NULL)
return FALSE;
- silo = *inout_silo;
- silo_filename = *inout_silo_filename;
- silo_installed_by_desktopid = *inout_installed_by_desktopid;
-
GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardQuerySilo, "Flatpak (query silo)", NULL);
- if (*inout_components_by_id != NULL) {
- components = g_hash_table_lookup (*inout_components_by_id, gs_app_get_id (app));
- } else {
- g_autoptr(GPtrArray) components_with_id = NULL;
- *inout_components_by_id = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_ptr_array_unref);
- components_with_id = xb_silo_query (silo, "components/component/id", 0, &error_local);
- if (components_with_id == NULL) {
- if (g_error_matches (error_local, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
- return TRUE;
- g_propagate_error (error, g_steal_pointer (&error_local));
- return FALSE;
+ components_by_id = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_ptr_array_unref);
+ components_with_id = xb_silo_query (silo, "components/component/id", 0, &error_local);
+ if (components_with_id == NULL) {
+ if (g_error_matches (error_local, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
+ return TRUE;
+ g_propagate_error (error, g_steal_pointer (&error_local));
+ return FALSE;
+ }
+
+ for (guint i = 0; i < components_with_id->len; i++) {
+ XbNode *node = g_ptr_array_index (components_with_id, i);
+ XbNode *comp_node = xb_node_get_parent (node);
+ const gchar *comp_id = xb_node_get_text (node);
+ GPtrArray *comps = g_hash_table_lookup (components_by_id, comp_id);
+ if (comps == NULL) {
+ comps = g_ptr_array_new_with_free_func (g_object_unref);
+ g_hash_table_insert (components_by_id, g_strdup (comp_id), comps);
}
- for (guint i = 0; i < components_with_id->len; i++) {
- XbNode *node = g_ptr_array_index (components_with_id, i);
- XbNode *comp_node = xb_node_get_parent (node);
- const gchar *comp_id = xb_node_get_text (node);
- GPtrArray *comps = g_hash_table_lookup (*inout_components_by_id, comp_id);
- if (comps == NULL) {
- comps = g_ptr_array_new_with_free_func (g_object_unref);
- g_hash_table_insert (*inout_components_by_id, g_strdup (comp_id), comps);
+ g_ptr_array_add (comps, comp_node);
+ }
+
+ components_by_bundle = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
+ bundles = xb_silo_query (silo, "/components/component/bundle[@type='flatpak']", 0, NULL);
+ for (guint b = 0; bundles != NULL && b < bundles->len; b++) {
+ XbNode *bundle_node = g_ptr_array_index (bundles, b);
+ g_autoptr(XbNode) component_node = xb_node_get_parent (bundle_node);
+ g_autoptr(XbNode) components_node = xb_node_get_parent (component_node);
+ const gchar *origin = xb_node_get_attr (components_node, "origin");
+ if (origin != NULL) {
+ const gchar *bundle = xb_node_get_text (bundle_node);
+ if (bundle != NULL) {
+ g_autofree gchar *key = g_strconcat (origin, "\n", bundle, NULL);
+ g_hash_table_insert (components_by_bundle, g_steal_pointer (&key), g_steal_pointer (&component_node));
}
- g_ptr_array_add (comps, comp_node);
- if (components == NULL && g_strcmp0 (id, comp_id) == 0)
- components = comps;
}
}
GS_PROFILER_END_SCOPED (FlatpakRefineWildcardQuerySilo);
- if (components == NULL)
- return TRUE;
-
gs_flatpak_ensure_remote_title (self, interactive, cancellable);
- if (*inout_components_by_bundle == NULL) {
- g_autoptr(GPtrArray) bundles = NULL;
-
- *inout_components_by_bundle = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
- bundles = xb_silo_query (silo, "/components/component/bundle[@type='flatpak']", 0, NULL);
- for (guint b = 0; bundles != NULL && b < bundles->len; b++) {
- XbNode *bundle_node = g_ptr_array_index (bundles, b);
- g_autoptr(XbNode) component_node = xb_node_get_parent (bundle_node);
- g_autoptr(XbNode) components_node = xb_node_get_parent (component_node);
- const gchar *origin = xb_node_get_attr (components_node, "origin");
- if (origin != NULL) {
- const gchar *bundle = xb_node_get_text (bundle_node);
- if (bundle != NULL) {
- g_autofree gchar *key = g_strconcat (origin, "\n", bundle, NULL);
- g_hash_table_insert (*inout_components_by_bundle, g_steal_pointer (&key), g_steal_pointer (&component_node));
- }
- }
- }
- }
+ for (guint j = 0; j < wildcard_apps->len; j++) {
+ GsApp *app = g_ptr_array_index (wildcard_apps, j);
+ GPtrArray *components = NULL;
+ const gchar *id;
+ /* not enough info to find */
+ id = gs_app_get_id (app);
+ if (id == NULL)
+ continue;
- GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardGenerateApps, "Flatpak (create app)", NULL);
- for (guint i = 0; i < components->len; i++) {
- XbNode *component = g_ptr_array_index (components, i);
- g_autoptr(GsApp) new = NULL;
+ components = g_hash_table_lookup (components_by_id, id);
+ if (components == NULL)
+ continue;
- GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardCreateAppstreamApp, "Flatpak (create Appstream app)", NULL);
- new = gs_appstream_create_app (self->plugin, silo, component, silo_filename ? silo_filename : "",
- self->scope, error);
- GS_PROFILER_END_SCOPED (FlatpakRefineWildcardCreateAppstreamApp);
+ GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardGenerateApps, "Flatpak (create app)", NULL);
+ for (guint i = 0; i < components->len; i++) {
+ XbNode *component = g_ptr_array_index (components, i);
+ g_autoptr(GsApp) new = NULL;
- if (new == NULL)
- return FALSE;
+ GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardCreateAppstreamApp, "Flatpak (create Appstream app)", NULL);
+ new = gs_appstream_create_app (self->plugin, silo, component, silo_filename ? silo_filename : "",
+ self->scope, error);
+ GS_PROFILER_END_SCOPED (FlatpakRefineWildcardCreateAppstreamApp);
- gs_flatpak_claim_app (self, new);
-
- /* The appstream plugin did not find the component in the plugin's cache,
- thus read the required info from the 'bundle' element. */
- if (gs_flatpak_app_get_ref_name (new) == NULL ||
- gs_flatpak_app_get_ref_arch (new) == NULL) {
- const gchar *xref_str = NULL;
- g_autoptr(XbNode) child = NULL;
- g_autoptr(XbNode) next = NULL;
- for (child = xb_node_get_child (component); child != NULL && xref_str == NULL;
- g_object_unref (child), child = g_steal_pointer (&next)) {
- next = xb_node_get_next (child);
- if (g_strcmp0 (xb_node_get_element (child), "bundle") == 0 &&
- g_strcmp0 (xb_node_get_attr (child, "type"), "flatpak") == 0) {
- xref_str = xb_node_get_text (child);
- break;
+ if (new == NULL)
+ return FALSE;
+
+ gs_flatpak_claim_app (self, new);
+
+ /* The appstream plugin did not find the component in the plugin's cache,
+ thus read the required info from the 'bundle' element. */
+ if (gs_flatpak_app_get_ref_name (new) == NULL ||
+ gs_flatpak_app_get_ref_arch (new) == NULL) {
+ const gchar *xref_str = NULL;
+ g_autoptr(XbNode) child = NULL;
+ g_autoptr(XbNode) next = NULL;
+ for (child = xb_node_get_child (component); child != NULL && xref_str == NULL;
+ g_object_unref (child), child = g_steal_pointer (&next)) {
+ next = xb_node_get_next (child);
+ if (g_strcmp0 (xb_node_get_element (child), "bundle") == 0 &&
+ g_strcmp0 (xb_node_get_attr (child, "type"), "flatpak") == 0) {
+ xref_str = xb_node_get_text (child);
+ break;
+ }
}
- }
- if (xref_str != NULL) {
- g_auto(GStrv) split = NULL;
-
- /* get the kind/name/arch/branch */
- split = g_strsplit (xref_str, "/", -1);
- if (g_strv_length (split) == 4) {
- const gchar *comp_type = xb_node_get_attr (component, "type");
- AsComponentKind kind = as_component_kind_from_string (comp_type);
- if (kind != AS_COMPONENT_KIND_UNKNOWN)
- gs_app_set_kind (new, kind);
- else if (g_ascii_strcasecmp (split[0], "app") == 0)
- gs_app_set_kind (new, AS_COMPONENT_KIND_DESKTOP_APP);
- else if (g_ascii_strcasecmp (split[0], "runtime") == 0)
- gs_flatpak_set_runtime_kind_from_id (new);
- gs_flatpak_app_set_ref_name (new, split[1]);
- gs_flatpak_app_set_ref_arch (new, split[2]);
- gs_app_set_branch (new, split[3]);
- gs_app_set_metadata (new, "GnomeSoftware::packagename-value", xref_str);
+ if (xref_str != NULL) {
+ g_auto(GStrv) split = NULL;
+
+ /* get the kind/name/arch/branch */
+ split = g_strsplit (xref_str, "/", -1);
+ if (g_strv_length (split) == 4) {
+ const gchar *comp_type = xb_node_get_attr (component, "type");
+ AsComponentKind kind = as_component_kind_from_string (comp_type);
+ if (kind != AS_COMPONENT_KIND_UNKNOWN)
+ gs_app_set_kind (new, kind);
+ else if (g_ascii_strcasecmp (split[0], "app") == 0)
+ gs_app_set_kind (new, AS_COMPONENT_KIND_DESKTOP_APP);
+ else if (g_ascii_strcasecmp (split[0], "runtime") == 0)
+ gs_flatpak_set_runtime_kind_from_id (new);
+ gs_flatpak_app_set_ref_name (new, split[1]);
+ gs_flatpak_app_set_ref_arch (new, split[2]);
+ gs_app_set_branch (new, split[3]);
+ gs_app_set_metadata (new, "GnomeSoftware::packagename-value", xref_str);
+ }
}
}
- }
- if (gs_flatpak_app_get_ref_name (new) == NULL ||
- gs_flatpak_app_get_ref_arch (new) == NULL) {
- g_debug ("Failed to get ref info for '%s' from wildcard '%s', skipping it...", gs_app_get_id (new), id);
- } else {
- GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardRefineNewApp, "Flatpak (refine new app)", NULL);
- if (!gs_flatpak_refine_app_internal (self, new, require_flags, interactive, FALSE, *inout_components_by_bundle,
- silo, silo_filename, silo_installed_by_desktopid, cancellable, error))
- return FALSE;
- GS_PROFILER_END_SCOPED (FlatpakRefineWildcardRefineNewApp);
+ if (gs_flatpak_app_get_ref_name (new) == NULL ||
+ gs_flatpak_app_get_ref_arch (new) == NULL) {
+ g_debug ("Failed to get ref info for '%s' from wildcard '%s', skipping it...", gs_app_get_id (new), id);
+ } else {
+ GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardRefineNewApp, "Flatpak (refine new app)", NULL);
+ if (!gs_flatpak_refine_app_internal (self, new, require_flags, interactive, FALSE, components_by_bundle,
+ silo, silo_filename, silo_installed_by_desktopid, cancellable, error))
+ return FALSE;
+ GS_PROFILER_END_SCOPED (FlatpakRefineWildcardRefineNewApp);
- GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardSubsumeMetadata, "Flatpak (subsume metadata)", NULL);
- gs_app_subsume_metadata (new, app);
- GS_PROFILER_END_SCOPED (FlatpakRefineWildcardSubsumeMetadata);
+ GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcardSubsumeMetadata, "Flatpak (subsume metadata)", NULL);
+ gs_app_subsume_metadata (new, app);
+ GS_PROFILER_END_SCOPED (FlatpakRefineWildcardSubsumeMetadata);
- gs_app_list_add (list, new);
+ gs_app_list_add (list, new);
+ }
}
+ GS_PROFILER_END_SCOPED (FlatpakRefineWildcardGenerateApps);
}
- GS_PROFILER_END_SCOPED (FlatpakRefineWildcardGenerateApps);
GS_PROFILER_END_SCOPED (FlatpakRefineWildcard);
diff --git a/plugins/flatpak/gs-flatpak.h b/plugins/flatpak/gs-flatpak.h
index 34e1416b5..1f7d35a8f 100644
--- a/plugins/flatpak/gs-flatpak.h
+++ b/plugins/flatpak/gs-flatpak.h
@@ -104,16 +104,11 @@ gboolean gs_flatpak_refine_app_state (GsFlatpak *self,
void *event_user_data,
GCancellable *cancellable,
GError **error);
-gboolean gs_flatpak_refine_wildcard (GsFlatpak *self,
- GsApp *app,
+gboolean gs_flatpak_refine_wildcards (GsFlatpak *self,
+ GPtrArray *wildcard_apps,
GsAppList *list,
GsPluginRefineRequireFlags require_flags,
gboolean interactive,
- XbSilo **inout_silo,
- gchar **inout_silo_filename,
- GHashTable **inout_installed_by_desktopid,
- GHashTable **inout_components_by_id,
- GHashTable **inout_components_by_bundle,
GCancellable *cancellable,
GError **error);
gboolean gs_flatpak_launch (GsFlatpak *self,
diff --git a/plugins/flatpak/gs-plugin-flatpak.c b/plugins/flatpak/gs-plugin-flatpak.c
index f5d4a1d67..c06b1fb5f 100644
--- a/plugins/flatpak/gs-plugin-flatpak.c
+++ b/plugins/flatpak/gs-plugin-flatpak.c
@@ -667,31 +667,6 @@ gs_plugin_flatpak_refine_app (GsPluginFlatpak *self,
return gs_flatpak_refine_app (flatpak, app, require_flags, interactive, FALSE, event_callback, event_user_data, cancellable, error);
}
-typedef struct {
- XbSilo *silo;
- gchar *silo_filename;
- GHashTable *installed_by_desktopid;
- GHashTable *components_by_id;
- GHashTable *components_by_bundle;
-} RefineInstallationData;
-
-static void
-refine_installation_data_free (gpointer ptr)
-{
- RefineInstallationData *data = ptr;
-
- if (data == NULL)
- return;
-
- g_clear_pointer (&data->silo_filename, g_free);
- g_clear_pointer (&data->installed_by_desktopid, g_hash_table_unref);
- g_clear_pointer (&data->components_by_id, g_hash_table_unref);
- g_clear_pointer (&data->components_by_bundle, g_hash_table_unref);
- /* free the silo as the last, just in case, because the data from it is in the above hash tables */
- g_clear_object (&data->silo);
- g_free (data);
-}
-
static gboolean
refine_app (GsPluginFlatpak *self,
GsApp *app,
@@ -778,8 +753,7 @@ refine_thread_cb (GTask *task,
gboolean interactive = (data->job_flags & GS_PLUGIN_REFINE_FLAGS_INTERACTIVE) != 0;
GsPluginEventCallback event_callback = data->event_callback;
void *event_user_data = data->event_user_data;
- g_autoptr(GPtrArray) installation_data = NULL; /* (element-type RefineInstallationData) */
- g_autoptr(GsAppList) app_list = NULL;
+ g_autoptr(GPtrArray) wildcard_apps = g_ptr_array_new_with_free_func (g_object_unref); /* (element-type GsApp) (owned) */
g_autoptr(GError) local_error = NULL;
assert_in_worker (self);
@@ -790,38 +764,17 @@ refine_thread_cb (GTask *task,
g_task_return_error (task, g_steal_pointer (&local_error));
return;
}
- }
-
- /* Refine wildcards.
- *
- * Use a copy of the list for the loop because a function called
- * on the plugin may affect the list which can lead to problems
- * (e.g. inserting an app in the list on every call results in
- * an infinite loop) */
- app_list = gs_app_list_copy (list);
-
- installation_data = g_ptr_array_new_full (self->installations->len, refine_installation_data_free);
- g_ptr_array_set_size (installation_data, self->installations->len);
-
- for (guint j = 0; j < gs_app_list_length (app_list); j++) {
- GsApp *app = gs_app_list_index (app_list, j);
- if (!gs_app_has_quirk (app, GS_APP_QUIRK_IS_WILDCARD))
- continue;
+ if (gs_app_has_quirk (app, GS_APP_QUIRK_IS_WILDCARD) && gs_app_get_id (app) != NULL)
+ g_ptr_array_add (wildcard_apps, g_object_ref (app));
+ }
+ /* Refine wildcards. */
+ if (wildcard_apps->len > 0) {
for (guint i = 0; i < self->installations->len; i++) {
GsFlatpak *flatpak = g_ptr_array_index (self->installations, i);
- RefineInstallationData *inst_data = g_ptr_array_index (installation_data, i);
-
- if (inst_data == NULL) {
- inst_data = g_new0 (RefineInstallationData, 1);
- installation_data->pdata[i] = inst_data;
- }
- if (!gs_flatpak_refine_wildcard (flatpak, app, list, require_flags, interactive, &inst_data->silo,
- &inst_data->silo_filename, &inst_data->installed_by_desktopid,
- &inst_data->components_by_id, &inst_data->components_by_bundle,
- cancellable, &local_error)) {
+ if (!gs_flatpak_refine_wildcards (flatpak, wildcard_apps, list, require_flags, interactive, cancellable, &local_error)) {
g_task_return_error (task, g_steal_pointer (&local_error));
return;
}
--
GitLab
From 8472d717356a801e6c0171156738ea48480fa695 Mon Sep 17 00:00:00 2001
Date: Wed, 7 Jan 2026 18:45:47 +0100
Subject: [PATCH 3/3] flatpak: Hold silo lock when refining wildcard apps
The refine can take a long time, thus hold the silo lock to not have
it invalidated from another thread. Object reference is not enough
for the XbSilo, it breaks as soon as the underlying file changes.
---
plugins/flatpak/gs-flatpak.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/plugins/flatpak/gs-flatpak.c b/plugins/flatpak/gs-flatpak.c
index 782b0bb48..c5437125d 100644
--- a/plugins/flatpak/gs-flatpak.c
+++ b/plugins/flatpak/gs-flatpak.c
@@ -59,7 +59,7 @@ struct _GsFlatpak {
AsComponentScope scope;
GsPlugin *plugin;
XbSilo *silo;
- GMutex silo_lock;
+ GRecMutex silo_lock;
gchar *silo_filename;
GHashTable *silo_installed_by_desktopid;
gint silo_change_stamp;
@@ -1187,11 +1187,11 @@ gs_flatpak_ref_silo (GsFlatpak *self,
g_autoptr(GFile) file = NULL;
g_autoptr(GPtrArray) xremotes = NULL;
g_autoptr(GPtrArray) desktop_paths = NULL;
- g_autoptr(GMutexLocker) locker = NULL;
+ g_autoptr(GRecMutexLocker) locker = NULL;
g_autoptr(XbBuilder) builder = NULL;
g_autoptr(GMainContext) old_thread_default = NULL;
- locker = g_mutex_locker_new (&self->silo_lock);
+ locker = g_rec_mutex_locker_new (&self->silo_lock);
/* everything is okay */
if (self->silo != NULL && xb_silo_is_valid (self->silo) &&
g_atomic_int_get (&self->silo_change_stamp_current) == g_atomic_int_get (&self->silo_change_stamp)) {
@@ -3754,6 +3754,7 @@ gs_flatpak_refine_wildcards (GsFlatpak *self,
GError **error)
{
g_autoptr(GError) error_local = NULL;
+ g_autoptr(GRecMutexLocker) silo_locker = NULL;
g_autoptr(XbSilo) silo = NULL;
g_autoptr(GHashTable) silo_installed_by_desktopid = NULL;
g_autoptr(GHashTable) components_by_id = NULL;
@@ -3764,6 +3765,11 @@ gs_flatpak_refine_wildcards (GsFlatpak *self,
GS_PROFILER_BEGIN_SCOPED (FlatpakRefineWildcard, "Flatpak (refine wildcard)", NULL);
+ /* the refine can take a long time, thus hold the silo lock to not have
+ it invalidated from another thread; object reference is not enough
+ for the XbSilo, it breaks as soon as the underlying file changes */
+ silo_locker = g_rec_mutex_locker_new (&self->silo_lock);
+
silo = gs_flatpak_ref_silo (self, interactive, &silo_filename, &silo_installed_by_desktopid, cancellable, error);
if (silo == NULL)
return FALSE;
@@ -4810,7 +4816,7 @@ gs_flatpak_finalize (GObject *object)
g_object_unref (self->plugin);
g_hash_table_unref (self->broken_remotes);
g_mutex_clear (&self->broken_remotes_mutex);
- g_mutex_clear (&self->silo_lock);
+ g_rec_mutex_clear (&self->silo_lock);
g_hash_table_unref (self->app_silos);
g_mutex_clear (&self->app_silos_mutex);
g_clear_pointer (&self->remote_title, g_hash_table_unref);
@@ -4831,7 +4837,7 @@ gs_flatpak_init (GsFlatpak *self)
{
/* XbSilo needs external locking as we destroy the silo and build a new
* one when something changes */
- g_mutex_init (&self->silo_lock);
+ g_rec_mutex_init (&self->silo_lock);
g_mutex_init (&self->installed_refs_mutex);
self->installed_refs = NULL;
--
GitLab

View file

@ -1 +0,0 @@
checkout-gs-dnf5

View file

@ -1,35 +0,0 @@
#!/bin/bash
if [ ! -d checkout-gs-dnf5 ]; then
git clone --branch main https://gitlab.gnome.org/mcrha/gnome-software.git checkout-gs-dnf5 && \
cd checkout-gs-dnf5 && \
git checkout -b wip/dnf5daemon origin/wip/dnf5daemon && \
cd - >/dev/null
if [ "$?" != "0" ]; then
echo "Failed to clone dnf5-plugin repository" 1>&2
exit 1;
fi
fi
PATCH_PATH=../0001-dnf5-plugin.patch
cd checkout-gs-dnf5 && \
echo "Updating gs-dnf5 git 'main' repository" && \
git checkout main && \
git pull --rebase && \
echo "Updating gs-dnf5 git 'dnf5-pugin' repository" && \
git checkout wip/dnf5daemon && \
git pull --rebase && \
echo -n "at " >../${PATCH_PATH} && \
git log HEAD | head -n 5 | grep -E "commit|Date" >>../${PATCH_PATH} && \
echo "" >>../${PATCH_PATH} && \
git diff main >>../${PATCH_PATH} && \
cd - >/dev/null
if [ "$?" = "0" ]; then
echo "Patch '${PATCH_PATH}' updated"
else
echo "Failed to update patch '${PATCH_PATH}'" 1>&2
exit 1
fi

File diff suppressed because it is too large Load diff

View file

@ -1 +1 @@
SHA512 (gnome-software-49.3.tar.xz) = 0414ea55ad3b83bcd50514985e3d2026207801c040934805bb26d162e88f0619a9d70aa6ba324a29acfab02573490b928c83594b54f57ec2a8ad00e6c127f657
SHA512 (gnome-software-47.5.tar.xz) = d179f8b28d8a110424a1df35a736ca3b8a5e20b82a902f7c5ffb4343da55b139583da347ad055e3e1dd29bb5cded2e73b86709ea70db583311049d58e4861778