@cryptotaxi247 / netdata-1 / commits / 740006874

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