summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2021-02-21 13:43:53 +0100
committerCarlos Garnacho <carlosg@gnome.org>2021-04-02 18:06:24 +0200
commitdd04b1f3aec0acaa79db20c140e72cbdb3561f98 (patch)
treefd8d86e5b00c51c9dfd68c97e9309383a9b73430
parent4084e90c91feec5064e644aeaf44650f8926f484 (diff)
downloadtracker-dd04b1f3aec0acaa79db20c140e72cbdb3561f98.tar.gz
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
-rw-r--r--src/libtracker-data/tracker-db-manager.c2
-rw-r--r--src/libtracker-data/tracker-sparql.c4
2 files changed, 5 insertions, 1 deletions
diff --git a/src/libtracker-data/tracker-db-manager.c b/src/libtracker-data/tracker-db-manager.c
index 4eec98e11..75a562133 100644
--- a/src/libtracker-data/tracker-db-manager.c
+++ b/src/libtracker-data/tracker-db-manager.c
@@ -862,6 +862,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 6dea87b7a..e6680ea06 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -9465,7 +9465,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;
@@ -9524,6 +9524,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);