diff options
author | Richard Hughes <richard@hughsie.com> | 2015-02-04 09:23:52 +0000 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2015-02-04 09:23:54 +0000 |
commit | ba68a8a3788a7f3ff3945abd03459a1af909ab46 (patch) | |
tree | 113db1a2fa04fb5a803536b101fac40c216db290 /libappstream-builder | |
parent | eb7992290c39efed28179efa9b3a607f9d3637ed (diff) | |
download | appstream-glib-ba68a8a3788a7f3ff3945abd03459a1af909ab46.tar.gz |
Fix a crash when more than one thread tries to ensure the same package
This can happen when a package is itself an extra package of another, at the
same time being a valid application itself. This is probably a packaging bug,
but crashing isn't nice either.
Diffstat (limited to 'libappstream-builder')
-rw-r--r-- | libappstream-builder/asb-package.c | 22 | ||||
-rw-r--r-- | libappstream-builder/asb-self-test.c | 23 |
2 files changed, 41 insertions, 4 deletions
diff --git a/libappstream-builder/asb-package.c b/libappstream-builder/asb-package.c index d0e9d4f..7ca89c4 100644 --- a/libappstream-builder/asb-package.c +++ b/libappstream-builder/asb-package.c @@ -42,7 +42,9 @@ struct _AsbPackagePrivate gboolean enabled; gboolean is_open; gchar **filelist; + guint filelist_refcount; GPtrArray *deps; + guint deps_refcount; gchar *filename; gchar *basename; gchar *name; @@ -966,6 +968,12 @@ asb_package_ensure (AsbPackage *pkg, return FALSE; } + /* this is recounted */ + if (flags & ASB_PACKAGE_ENSURE_DEPS) + priv->deps_refcount++; + if (flags & ASB_PACKAGE_ENSURE_FILES) + priv->filelist_refcount++; + /* clear flags */ if (priv->name != NULL) flags &= ~ASB_PACKAGE_ENSURE_NEVRA; @@ -1007,11 +1015,17 @@ void asb_package_clear (AsbPackage *pkg, AsbPackageEnsureFlags flags) { AsbPackagePrivate *priv = GET_PRIVATE (pkg); - if (flags & ASB_PACKAGE_ENSURE_DEPS) - g_ptr_array_set_size (priv->deps, 0); + + /* this is recounted */ + if (flags & ASB_PACKAGE_ENSURE_DEPS) { + if (priv->deps_refcount > 0 && --priv->deps_refcount == 0) + g_ptr_array_set_size (priv->deps, 0); + } if (flags & ASB_PACKAGE_ENSURE_FILES) { - g_strfreev (priv->filelist); - priv->filelist = NULL; + if (priv->filelist_refcount > 0 && --priv->filelist_refcount == 0) { + g_strfreev (priv->filelist); + priv->filelist = NULL; + } } } diff --git a/libappstream-builder/asb-self-test.c b/libappstream-builder/asb-self-test.c index b196cba..687bb21 100644 --- a/libappstream-builder/asb-self-test.c +++ b/libappstream-builder/asb-self-test.c @@ -155,6 +155,29 @@ asb_test_package_rpm_func (void) asb_package_set_config (pkg, "test", "dave2"); g_assert_cmpstr (asb_package_get_config (pkg, "test"), ==, "dave2"); + /* clear */ + asb_package_clear (pkg, + ASB_PACKAGE_ENSURE_DEPS | + ASB_PACKAGE_ENSURE_FILES); + g_assert (asb_package_get_filelist (pkg) == NULL); + g_assert_cmpint (asb_package_get_deps(pkg)->len, ==, 0); + + /* clear, ensure, ensure, clear, check, clear */ + asb_package_clear (pkg, ASB_PACKAGE_ENSURE_DEPS); + g_assert_cmpint (asb_package_get_deps(pkg)->len, ==, 0); + ret = asb_package_ensure (pkg, ASB_PACKAGE_ENSURE_DEPS, &error); + g_assert_no_error (error); + g_assert (ret); + g_assert_cmpint (asb_package_get_deps(pkg)->len, ==, 3); + ret = asb_package_ensure (pkg, ASB_PACKAGE_ENSURE_DEPS, &error); + g_assert_no_error (error); + g_assert (ret); + g_assert_cmpint (asb_package_get_deps(pkg)->len, ==, 3); + asb_package_clear (pkg, ASB_PACKAGE_ENSURE_DEPS); + g_assert_cmpint (asb_package_get_deps(pkg)->len, ==, 3); + asb_package_clear (pkg, ASB_PACKAGE_ENSURE_DEPS); + g_assert_cmpint (asb_package_get_deps(pkg)->len, ==, 0); + /* compare */ g_assert_cmpint (asb_package_compare (pkg, pkg), ==, 0); |