From d4fbd569cb3f659a67ce85c6df159d8fbdce2821 Mon Sep 17 00:00:00 2001 From: Matthias Klumpp Date: Sat, 14 Sep 2024 18:28:43 +0200 Subject: [PATCH] Avoid a race condition when loading GResource data --- compose/asc-compose.c | 3 --- compose/asc-globals.c | 20 ++++++++++++++- src/as-utils-private.h | 2 -- src/as-utils.c | 55 +++++++++++++++++++----------------------- 4 files changed, 44 insertions(+), 36 deletions(-) diff --git a/compose/asc-compose.c b/compose/asc-compose.c index 0b746ad9..f9c5dfdd 100644 --- a/compose/asc-compose.c +++ b/compose/asc-compose.c @@ -2232,9 +2232,6 @@ asc_compose_run (AscCompose *compose, GCancellable *cancellable, GError **error) temp_dir_created = TRUE; } - /* sanity check to ensure resources can be loaded */ - as_utils_ensure_resources (); - tasks = g_ptr_array_new_with_free_func ((GDestroyNotify) asc_compose_task_free); for (guint i = 0; i < priv->units->len; i++) { diff --git a/compose/asc-globals.c b/compose/asc-globals.c index a77f3946..4a8dcb29 100644 --- a/compose/asc-globals.c +++ b/compose/asc-globals.c @@ -57,6 +57,24 @@ G_DEFINE_TYPE_WITH_PRIVATE (AscGlobals, asc_globals, G_TYPE_OBJECT) static AscGlobals *g_globals = NULL; static GMutex g_globals_mutex; +/** + * asc_get_resource_safe: + * + * A threadsafe variant to obtain the buit-in #GResource. + */ +static GResource * +asc_get_resource_safe (void) +{ + static GResource *resource = NULL; + + if (g_once_init_enter (&resource)) { + GResource *res = asc_get_resource (); + g_once_init_leave (&resource, res); + } + + return resource; +} + /** * asc_compose_error_quark: * @@ -306,7 +324,7 @@ asc_globals_get_pangrams_for (const gchar *lang) return priv->pangrams_en; /* load array from resources */ - data = g_resource_lookup_data (asc_get_resource (), + data = g_resource_lookup_data (asc_get_resource_safe (), "/org/freedesktop/appstream-compose/pangrams/en.txt", G_RESOURCE_LOOKUP_FLAGS_NONE, NULL); diff --git a/src/as-utils-private.h b/src/as-utils-private.h index a1e56daf..b0f9f837 100644 --- a/src/as-utils-private.h +++ b/src/as-utils-private.h @@ -143,8 +143,6 @@ gchar *as_utils_find_stock_icon_filename_full (const gchar *root_dir, guint icon_size, guint icon_scale, GError **error); -AS_INTERNAL_VISIBLE -void as_utils_ensure_resources (void); gchar *as_make_usertag_key (const gchar *ns, const gchar *tag); diff --git a/src/as-utils.c b/src/as-utils.c index 5e83411c..51c09e30 100644 --- a/src/as-utils.c +++ b/src/as-utils.c @@ -67,6 +67,25 @@ **/ G_DEFINE_QUARK (as-utils-error-quark, as_utils_error) +/** + * as_get_resource_safe: + * + * A threadsafe variant to obtain our GResource. + */ +static GResource * +as_get_resource_safe (void) +{ + static GResource *resource = NULL; + + if (g_once_init_enter (&resource)) { + GResource *res = as_get_resource (); + g_once_init_leave (&resource, res); + } + + g_assert (resource != NULL); + return resource; +} + /** * as_markup_strsplit_words: * @text: the text to split. @@ -1259,24 +1278,6 @@ as_utils_search_token_valid (const gchar *token) return TRUE; } -/** - * as_utils_ensure_resources: - * - * Perform a sanity check to ensure GResource can be loaded. - */ -void -as_utils_ensure_resources (void) -{ - static GMutex mutex; - GResource *resource = NULL; - - g_mutex_lock (&mutex); - resource = as_get_resource (); - if (resource == NULL) - g_error ("Failed to load internal resources: as_get_resource() returned NULL!"); - g_mutex_unlock (&mutex); -} - /** * as_utils_is_category_name: * @category_name: a XDG category name, e.g. "ProjectManagement" @@ -1294,8 +1295,7 @@ as_utils_is_category_name (const gchar *category_name) { g_autoptr(GBytes) data = NULL; g_autofree gchar *key = NULL; - GResource *resource = as_get_resource (); - g_assert (resource != NULL); + GResource *resource = as_get_resource_safe (); /* custom spec-extensions are generally valid if prefixed correctly */ if (g_str_has_prefix (category_name, "X-")) @@ -1382,8 +1382,7 @@ as_utils_is_tld (const gchar *tld) { g_autoptr(GBytes) data = NULL; g_autofree gchar *key = NULL; - GResource *resource = as_get_resource (); - g_assert (resource != NULL); + GResource *resource = as_get_resource_safe (); /* safeguard against accidentally matching comments */ if (as_is_empty (tld) || g_str_has_prefix (tld, "#")) @@ -1532,8 +1531,7 @@ as_utils_is_platform_triplet_arch (const gchar *arch) if (g_str_has_prefix (arch, "#")) return FALSE; - resource = as_get_resource (); - g_assert (resource != NULL); + resource = as_get_resource_safe (); /* load the readonly data section */ data = g_resource_lookup_data (resource, @@ -1575,8 +1573,7 @@ as_utils_is_platform_triplet_oskernel (const gchar *os) if (g_str_has_prefix (os, "#")) return FALSE; - resource = as_get_resource (); - g_assert (resource != NULL); + resource = as_get_resource_safe (); /* load the readonly data section */ data = g_resource_lookup_data (resource, @@ -1618,8 +1615,7 @@ as_utils_is_platform_triplet_osenv (const gchar *env) if (g_str_has_prefix (env, "#")) return FALSE; - resource = as_get_resource (); - g_assert (resource != NULL); + resource = as_get_resource_safe (); /* load the readonly data section */ data = g_resource_lookup_data (resource, @@ -1688,8 +1684,7 @@ as_utils_is_reference_registry (const gchar *regname) if (g_str_has_prefix (regname, "#")) return FALSE; - resource = as_get_resource (); - g_assert (resource != NULL); + resource = as_get_resource_safe (); /* load the readonly data section */ data = g_resource_lookup_data (resource,