[tracker/wip/carlosg/interface-race-condition: 2/2] libtracker-data: Add an usage reference early when getting an interface




commit 70ae8dcc5497cbd5478d1e5086c4b36d53d25b2e
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sun Feb 21 13:43:53 2021 +0100

    libtracker-data: Add an usage reference early when getting an interface
    
    Currently, there's a gap between a TrackerDBInterface being picked for
    execution, and a cursor increasing its usage counter. This opened the
    following race condition:
    
     - Random thread executes SPARQL select query, a TrackerDBInterface
       is picked.
     - TrackerSparqlConnection reaches a threshold/timeout and tries to
       release memory, performed by the update thread
     - All unused readonly connections are closed
     - The random thread proceeds to create a stmt/cursor, finds invalid
       memory in place of the TrackerDBInterface
     - Whoops
    
    To fix this, increase the usage counter when getting a readonly
    interface from the TrackerDBManager, while the connection pool is
    locked (thus mutually exclusive with the "release memory" operation)
    and decrease it after having created the statement/cursor (at which
    point it is additionally increased by the cursor).
    
    This will ensure that an interface is considered "in use" as soon
    as it gets out of the readonly connections pool, usage counter will
    always be greater than 1 until there are no cursors left.
    
    Fixes: https://gitlab.gnome.org/GNOME/tracker-miners/-/issues/154

 src/libtracker-data/tracker-db-manager.c | 2 ++
 src/libtracker-data/tracker-sparql.c     | 4 +++-
 2 files changed, 5 insertions(+), 1 deletion(-)
---
diff --git a/src/libtracker-data/tracker-db-manager.c b/src/libtracker-data/tracker-db-manager.c
index c9523d480..e3044819c 100644
--- a/src/libtracker-data/tracker-db-manager.c
+++ b/src/libtracker-data/tracker-db-manager.c
@@ -874,6 +874,8 @@ tracker_db_manager_get_db_interface (TrackerDBManager *db_manager)
                }
        }
 
+       tracker_db_interface_ref_use (interface);
+
        g_async_queue_push_unlocked (db_manager->interfaces, interface);
        g_async_queue_unlock (db_manager->interfaces);
 
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index 9b0f5701f..8fd51cc6e 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -9483,7 +9483,7 @@ tracker_sparql_execute_cursor (TrackerSparql  *sparql,
                                GError        **error)
 {
        TrackerDBStatement *stmt;
-       TrackerDBInterface *iface;
+       TrackerDBInterface *iface = NULL;
        TrackerDBCursor *cursor = NULL;
        TrackerPropertyType *types;
        const gchar * const *names;
@@ -9543,6 +9543,8 @@ tracker_sparql_execute_cursor (TrackerSparql  *sparql,
        g_object_unref (stmt);
 
 error:
+       if (iface)
+               tracker_db_interface_unref_use (iface);
        g_mutex_unlock (&sparql->mutex);
 
        return TRACKER_SPARQL_CURSOR (cursor);


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