diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2020-11-24 13:58:25 +0100 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2020-11-24 13:58:25 +0100 |
commit | 721c46273c48d0b5a7ce949fcbd0b5c65bd3456a (patch) | |
tree | 3ef455225998bce83d832e3cc1b7ca217076e536 /src/libtracker-data/tracker-namespace.c | |
parent | cf3fac9e5f70adcd404b24db8987815125b748be (diff) | |
download | tracker-721c46273c48d0b5a7ce949fcbd0b5c65bd3456a.tar.gz |
libtracker-data: Protect ontology objects with a mutex
In the case of readonly connections, we use the ontology gvdb as a
fast path to regenerate the ontology, and fetch the actual data on
demand.
However, we use the ontology bits from the query machinery, so
fetching this data on the fly may collide with other threads
performing queries that require the same ontology resources. This
may cause from leaks (because two threads get the same data, but
one is lost) to crashes (because one thread frees data that the
other is accessing).
Make all gvdb extraction at a single point for those objects, and
protect the operation with a mutex. As we can do this once, optimize
the case that data has been already extracted (not needing a mutex
lock/unlock then). But obviously, also handle the case that 2 or more
threads contend on gvdb synchronization.
Fixes: https://gitlab.gnome.org/GNOME/tracker/-/issues/272
Diffstat (limited to 'src/libtracker-data/tracker-namespace.c')
-rw-r--r-- | src/libtracker-data/tracker-namespace.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/src/libtracker-data/tracker-namespace.c b/src/libtracker-data/tracker-namespace.c index bb6496e06..6cbb1085e 100644 --- a/src/libtracker-data/tracker-namespace.c +++ b/src/libtracker-data/tracker-namespace.c @@ -32,6 +32,7 @@ typedef struct _TrackerNamespacePrivate TrackerNamespacePrivate; struct _TrackerNamespacePrivate { gchar *uri; + GMutex mutex; guint use_gvdb : 1; guint is_new : 1; @@ -54,6 +55,10 @@ tracker_namespace_class_init (TrackerNamespaceClass *klass) static void tracker_namespace_init (TrackerNamespace *service) { + TrackerNamespacePrivate *priv; + + priv = tracker_namespace_get_instance_private (service); + g_mutex_init (&priv->mutex); } static void @@ -85,6 +90,29 @@ tracker_namespace_new (gboolean use_gvdb) return namespace; } +static void +tracker_namespace_maybe_sync_from_gvdb (TrackerNamespace *namespace) +{ + TrackerNamespacePrivate *priv; + + priv = tracker_namespace_get_instance_private (namespace); + + if (!priv->use_gvdb) + return; + + g_mutex_lock (&priv->mutex); + + /* In case the lock was contended, make the second lose */ + if (!priv->use_gvdb) + goto out; + + priv->prefix = g_strdup (tracker_ontologies_get_namespace_string_gvdb (priv->ontologies, priv->uri, "prefix")); + + priv->use_gvdb = FALSE; +out: + g_mutex_unlock (&priv->mutex); +} + const gchar * tracker_namespace_get_uri (TrackerNamespace *namespace) { @@ -106,9 +134,7 @@ tracker_namespace_get_prefix (TrackerNamespace *namespace) priv = tracker_namespace_get_instance_private (namespace); - if (!priv->prefix && priv->use_gvdb) { - priv->prefix = g_strdup (tracker_ontologies_get_namespace_string_gvdb (priv->ontologies, priv->uri, "prefix")); - } + tracker_namespace_maybe_sync_from_gvdb (namespace); return priv->prefix; } |