[tracker/wip/carlosg/timeouts-and-stuff: 2/2] libtracker-data: Protect tracker_sparql_execute_cursor() with a mutex



commit 7eb1ca0858841ddbf0680f95e542c5d29e869ab9
Author: Carlos Garnacho <carlosg gnome org>
Date:   Fri Jul 3 12:01:37 2020 +0200

    libtracker-data: Protect tracker_sparql_execute_cursor() with a mutex
    
    This function used to operate 100% on readonly data, so could be safely
    used from multiple threads. This is however no longer true since commit
    af97cede7ced, which might result in TrackerSparql churning again to
    re-parse the SPARQL into SQL.
    
    Moreover, as this was not an atomic operation (far from it), the same
    TrackerSparql could trigger independently this re-parsing, or surprise
    older users with data going down their feet. This could produce anything
    from wrong results, to invalid reads/writes, to crashes.
    
    Protect the whole thing with a mutex, so it is ensured it's only rebuilt
    in one thread, and other users don't get surprised by it.

 src/libtracker-data/tracker-sparql.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)
---
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index 937b475cb..8e87d9fb5 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -137,6 +137,8 @@ struct _TrackerSparql
        GPtrArray *named_graphs;
        gchar *base;
 
+       GMutex mutex;
+
        struct {
                TrackerContext *context;
                TrackerContext *select_context;
@@ -8795,6 +8797,7 @@ tracker_sparql_init (TrackerSparql *sparql)
        sparql->anon_graphs = g_ptr_array_new_with_free_func (g_free);
        sparql->named_graphs = g_ptr_array_new_with_free_func (g_free);
        sparql->cacheable = TRUE;
+       g_mutex_init (&sparql->mutex);
 }
 
 static gboolean
@@ -8967,11 +8970,13 @@ tracker_sparql_execute_cursor (TrackerSparql  *sparql,
 {
        TrackerDBStatement *stmt;
        TrackerDBInterface *iface;
-       TrackerDBCursor *cursor;
+       TrackerDBCursor *cursor = NULL;
        TrackerPropertyType *types;
        const gchar * const *names;
        guint n_types, n_names;
 
+       g_mutex_lock (&sparql->mutex);
+
 #ifdef G_ENABLE_DEBUG
        if (TRACKER_DEBUG_CHECK (SPARQL)) {
                gchar *query_to_print;
@@ -8985,14 +8990,14 @@ tracker_sparql_execute_cursor (TrackerSparql  *sparql,
 
        if (sparql->parser_error) {
                g_propagate_error (error, sparql->parser_error);
-               return NULL;
+               goto error;
        }
 
        if (tracker_sparql_needs_update (sparql)) {
                tracker_sparql_reset_state (sparql);
 
                if (!_call_rule_func (sparql, NAMED_RULE_Query, error))
-                       return NULL;
+                       goto error;
        }
 
        iface = tracker_data_manager_get_db_interface (sparql->data_manager);
@@ -9002,7 +9007,7 @@ tracker_sparql_execute_cursor (TrackerSparql  *sparql,
                              sparql->cacheable,
                              error);
        if (!stmt)
-               return NULL;
+               goto error;
 
        types = (TrackerPropertyType *) sparql->var_types->data;
        n_types = sparql->var_types->len;
@@ -9015,7 +9020,11 @@ tracker_sparql_execute_cursor (TrackerSparql  *sparql,
                                                           error);
        g_object_unref (stmt);
 
+error:
+       g_mutex_unlock (&sparql->mutex);
+
        return TRACKER_SPARQL_CURSOR (cursor);
+
 }
 
 TrackerSparql *


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]