[tracker/wip/carlosg/bus-statements] libtracker-data: Fix race condition
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [tracker/wip/carlosg/bus-statements] libtracker-data: Fix race condition
- Date: Mon, 2 Mar 2020 13:32:38 +0000 (UTC)
commit ed204139a1af9a2b539b0b07429bb7df6096eab7
Author: Carlos Garnacho <carlosg gnome org>
Date: Mon Mar 2 14:17:50 2020 +0100
libtracker-data: Fix race condition
For some reason ever unseen (by me?) till CI happened to trip on this
branch. The underlying TrackerDBStatements have a brief window between
them being looked up in the stmt LRU and them being used for query
execution that they might end up in use by two threads at the same time.
Add a new TrackerDBStatement flag to indicate that the statement is owned,
set it early when fetching the TrackerDBStatement and make the LRU checks
check for it before considering using a temporary stmt. The lifetime of
this flag matches the time the TrackerDBStatement is in use by a given
user.
The flag is released altogether on _release(), as it works for indicating
the statement is being made available to other users.
src/libtracker-data/tracker-db-interface-sqlite.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
---
diff --git a/src/libtracker-data/tracker-db-interface-sqlite.c
b/src/libtracker-data/tracker-db-interface-sqlite.c
index 074bf40f1..3dbfcc233 100644
--- a/src/libtracker-data/tracker-db-interface-sqlite.c
+++ b/src/libtracker-data/tracker-db-interface-sqlite.c
@@ -131,7 +131,8 @@ struct TrackerDBStatement {
GInitiallyUnowned parent_instance;
TrackerDBInterface *db_interface;
sqlite3_stmt *stmt;
- gboolean stmt_is_used;
+ guint stmt_is_used : 1;
+ guint stmt_is_owned : 1;
TrackerDBStatement *next;
TrackerDBStatement *prev;
};
@@ -2572,9 +2573,9 @@ tracker_db_interface_lru_lookup (TrackerDBInterface *db_interface,
/* a) Cached */
- if (stmt && stmt->stmt_is_used) {
+ if (stmt && stmt->stmt_is_owned) {
/* c) Forced non-cached
- * prepared statement is still in use, create new uncached one
+ * prepared statement is owned somewhere else, create new uncached one
*/
stmt = NULL;
/* Make sure to set cache_type here, to avoid replacing
@@ -2741,6 +2742,7 @@ tracker_db_interface_create_statement (TrackerDBInterface *db_interfac
stmt);
}
+ stmt->stmt_is_owned = TRUE;
g_free (full_query);
tracker_db_interface_unlock (db_interface);
@@ -2929,6 +2931,7 @@ static TrackerDBStatement *
tracker_db_statement_sqlite_grab (TrackerDBStatement *stmt)
{
g_assert (!stmt->stmt_is_used);
+ g_assert (stmt->stmt_is_owned);
stmt->stmt_is_used = TRUE;
g_object_ref (stmt->db_interface);
return g_object_ref (stmt);
@@ -2939,8 +2942,9 @@ tracker_db_statement_sqlite_release (TrackerDBStatement *stmt)
{
TrackerDBInterface *iface = stmt->db_interface;
- g_assert (stmt->stmt_is_used);
+ g_assert (stmt->stmt_is_owned);
stmt->stmt_is_used = FALSE;
+ stmt->stmt_is_owned = FALSE;
tracker_db_statement_sqlite_reset (stmt);
g_object_unref (stmt);
g_object_unref (iface);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]