Add additional database checks during shutdown (#20731)
Do not attempt to release statements if we have closed the databases
Stelios Fragkakis committed
Jul 28, 2025 at 20:52 UTC
0819f17790f7362414db228076cae7c34e343fb9
1 file changed
+19
-5
src/database/sqlite/sqlite_functions.c
+19
-5
@@ -4,8 +4,8 @@
4
5
#define MAX_PREPARED_THREAD_STATEMENTS (32)
6
7
-SPINLOCK JudyL_thread_stmt_lock = SPINLOCK_INITIALIZER;
8
-Pvoid_t JudyL_thread_stmt_pool = NULL;
7
+static SPINLOCK JudyL_thread_stmt_lock = SPINLOCK_INITIALIZER;
8
+static Pvoid_t JudyL_thread_stmt_pool = NULL;
9
10
struct stmt_pool_s {
11
int count;
@@ -21,6 +21,7 @@ long long def_journal_size_limit = 16777216;
21
SPINLOCK sqlite_spinlock = SPINLOCK_INITIALIZER;
22
23
bool sqlite_library_initialized;
24
+bool sqlite_databases_closed;
25
26
SQLITE_API int sqlite3_exec_monitored(
27
sqlite3 *db, /* An open database */
@@ -189,6 +190,11 @@ static void finalize_and_free_stmt_list(struct stmt_pool_s *stmt_list)
190
// This must be called when the thread terminates
191
void finalize_self_prepared_sql_statements()
192
{
193
+ if (__atomic_load_n(&sqlite_databases_closed, __ATOMIC_ACQUIRE))
194
+ return;
195
+
196
+ spinlock_lock(&sqlite_spinlock);
197
+
198
spinlock_lock(&JudyL_thread_stmt_lock);
199
if (thread_stmt_pool) {
200
Word_t thread_id = thread_stmt_pool->thread_id;
@@ -197,6 +203,8 @@ void finalize_self_prepared_sql_statements()
203
(void)JudyLDel(&JudyL_thread_stmt_pool, thread_id, PJE0);
204
}
205
spinlock_unlock(&JudyL_thread_stmt_lock);
206
+
207
+ spinlock_unlock(&sqlite_spinlock);
208
}
209
210
void finalize_all_prepared_sql_statements()
@@ -245,6 +253,9 @@ static void init_thread_stmt_pool(void) {
253
254
int prepare_statement(sqlite3 *database, const char *query, sqlite3_stmt **statement)
255
{
256
+ if (__atomic_load_n(&sqlite_databases_closed, __ATOMIC_ACQUIRE))
257
+ return SQLITE_MISUSE;
258
+
259
int rc = sqlite3_prepare_v2(database, query, -1, statement, 0);
260
if (rc == SQLITE_OK) {
261
if (!thread_stmt_pool)
@@ -429,11 +440,13 @@ extern sqlite3 *db_context_meta;
440
441
void sqlite_close_databases(void)
442
{
432
- spinlock_lock(&sqlite_spinlock);
433
-
434
- // In case we have statements in the main thread
443
+ // In case we have statements in the main thread (we should not)
444
finalize_self_prepared_sql_statements();
445
446
+ __atomic_store_n(&sqlite_databases_closed, true, __ATOMIC_RELEASE);
447
+
448
+ spinlock_lock(&sqlite_spinlock);
449
+
450
// Finalize pending statements and report any thread that failed
451
// to do it properly
452
finalize_all_prepared_sql_statements();
@@ -484,6 +497,7 @@ int sqlite_library_init(void)
497
nd_log_daemon(
498
NDLP_INFO, "SQLITE: heap memory hard limit %s, soft limit %s", sqlite_hard_limit_mb, sqlite_soft_limit_mb);
499
}
500
+ __atomic_store_n(&sqlite_databases_closed, false, __ATOMIC_RELEASE);
501
sqlite_library_initialized = true;
502
spinlock_unlock(&sqlite_spinlock);
503