Improve statement preparation (#21608)
Wrap statement preperation with spinlock to avoid crashes during shutdown
Stelios Fragkakis committed
Jan 22, 2026 at 18:21 UTC
74000687429be113894854890c6201fda945613f
2 files changed
+20
-2
src/database/sqlite/sqlite_functions.c
+18
-1
@@ -251,10 +251,26 @@ static void init_thread_stmt_pool(void) {
251
spinlock_unlock(&JudyL_thread_stmt_lock);
252
}
253
254
+int simple_prepare_statement(sqlite3 *database, const char *query, sqlite3_stmt **statement)
255
+{
256
+ spinlock_lock(&sqlite_spinlock);
257
+ if (__atomic_load_n(&sqlite_databases_closed, __ATOMIC_ACQUIRE)) {
258
+ spinlock_unlock(&sqlite_spinlock);
259
+ return SQLITE_MISUSE;
260
+ }
261
+
262
+ int rc = sqlite3_prepare_v2(database, query, -1, statement, 0);
263
+ spinlock_unlock(&sqlite_spinlock);
264
+ return rc;
265
+}
266
+
267
int prepare_statement(sqlite3 *database, const char *query, sqlite3_stmt **statement)
268
{
256
- if (__atomic_load_n(&sqlite_databases_closed, __ATOMIC_ACQUIRE))
269
+ spinlock_lock(&sqlite_spinlock);
270
+ if (__atomic_load_n(&sqlite_databases_closed, __ATOMIC_ACQUIRE)) {
271
+ spinlock_unlock(&sqlite_spinlock);
272
return SQLITE_MISUSE;
273
+ }
274
275
int rc = sqlite3_prepare_v2(database, query, -1, statement, 0);
276
if (rc == SQLITE_OK) {
@@ -264,6 +280,7 @@ int prepare_statement(sqlite3 *database, const char *query, sqlite3_stmt **state
280
if (stmt_key < MAX_PREPARED_THREAD_STATEMENTS)
281
thread_stmt_pool->stmt[stmt_key] = *statement;
282
}
283
+ spinlock_unlock(&sqlite_spinlock);
284
return rc;
285
}
286
src/database/sqlite/sqlite_functions.h
+2
-1
@@ -77,7 +77,7 @@ extern bool sqlite_databases_closed;
77
78
#define PREPARE_STATEMENT(db, sql, stmt_ptr) \
79
({ \
80
- int _rc = sqlite3_prepare_v2((db), (sql), -1, stmt_ptr, 0); \
80
+ int _rc = simple_prepare_statement((db), (sql), stmt_ptr); \
81
if (_rc != SQLITE_OK) { \
82
internal_error(true, "Failed to prepare statement \"%s\", rc=%d in %s", (sql), _rc, __FUNCTION__); \
83
nd_log(NDLS_DAEMON, NDLP_ERR, "Failed to prepare statement, rc=%d in %s", _rc, __FUNCTION__); \
@@ -105,6 +105,7 @@ int configure_sqlite_database(sqlite3 *database, int target_version, const char
105
// Helpers
106
int bind_text_null(sqlite3_stmt *res, int position, const char *text, bool can_be_null);
107
int prepare_statement(sqlite3 *database, const char *query, sqlite3_stmt **statement);
108
+int simple_prepare_statement(sqlite3 *database, const char *query, sqlite3_stmt **statement);
109
void finalize_self_prepared_sql_statements();
110
void finalize_all_prepared_sql_statements();
111