wallet: store m_additional_flags in SQLiteDatabase to fix reopen path

SQLiteDatabase::Open() (the public override) always reopens the database
with no additional flags. If SQLiteBatch::Close() triggers the
force_conn_refresh path (TxnAbort failed), it calls Open() which drops
the original additional_flags, causing in-memory databases to be reopened
as on-disk instead.

Store additional_flags as a member and use it in Open() so the reconnect
preserves the original flags. For in-memory databases, connection recovery
makes no sense as all data would be lost; both the force_conn_refresh path
and the public Open() now throw instead.

Co-authored-by: Sjors Provoost <sjors@sprovoost.nl>
This commit is contained in:
Pablo Martin
2026-07-04 15:30:13 -03:00
parent 1835f2fcbf
commit ee43743f12
2 changed files with 13 additions and 3 deletions

View File

@@ -116,7 +116,7 @@ SQLiteDatabase::SQLiteDatabase(const fs::path& dir_path, const fs::path& file_pa
{}
SQLiteDatabase::SQLiteDatabase(const fs::path& dir_path, const fs::path& file_path, const DatabaseOptions& options, int additional_flags)
: WalletDatabase(), m_dir_path(dir_path), m_file_path(fs::PathToString(file_path)), m_write_semaphore(1), m_use_unsafe_sync(options.use_unsafe_sync)
: WalletDatabase(), m_dir_path(dir_path), m_file_path(fs::PathToString(file_path)), m_additional_flags(additional_flags), m_write_semaphore(1), m_use_unsafe_sync(options.use_unsafe_sync)
{
{
LOCK(g_sqlite_mutex);
@@ -139,7 +139,7 @@ SQLiteDatabase::SQLiteDatabase(const fs::path& dir_path, const fs::path& file_pa
}
try {
Open(additional_flags);
Open(m_additional_flags);
} catch (const std::runtime_error&) {
// If open fails, cleanup this object and rethrow the exception
Cleanup();
@@ -247,7 +247,10 @@ bool SQLiteDatabase::Verify(bilingual_str& error)
void SQLiteDatabase::Open()
{
Open(/*additional_flags*/0);
if (m_additional_flags & SQLITE_OPEN_MEMORY) {
throw std::runtime_error("SQLiteDatabase: Cannot reopen an in-memory database");
}
Open(m_additional_flags);
}
void SQLiteDatabase::Open(int additional_flags)
@@ -448,6 +451,9 @@ void SQLiteBatch::Close()
}
if (force_conn_refresh) {
if (m_database.m_additional_flags & SQLITE_OPEN_MEMORY) {
throw std::runtime_error("SQLiteDatabase: Cannot recover in-memory database connection");
}
m_database.Close();
try {
m_database.Open();

View File

@@ -103,10 +103,14 @@ public:
class SQLiteDatabase : public WalletDatabase
{
private:
friend class SQLiteBatch;
const fs::path m_dir_path;
const std::string m_file_path;
const int m_additional_flags;
/**
* This mutex protects SQLite initialization and shutdown.
* sqlite3_config() and sqlite3_shutdown() are not thread-safe (sqlite3_initialize() is).