1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-11-23 17:30:17 +01:00

Bug2700: intermittent failure to open project database... (#799)

... Logging data from the wild shows that the SELECT query in
ProjectFileIO::CheckVersion() returned SQLITE_BUSY sometimes.

A plausible explanation is that the concurrently starting checkpoint thread
was sometimes creating a new connection simultaneously.

Instead, serialize the creation of the two connections in the main thread and
pass the second one ready made into the checkpoint thread.
This commit is contained in:
Paul Licameli
2021-04-08 14:56:06 -04:00
committed by GitHub
parent cceaf0d162
commit 40d3a36296
2 changed files with 25 additions and 18 deletions

View File

@@ -155,7 +155,20 @@ int DBConnection::Open(const FilePath fileName)
mCheckpointStop = false;
mCheckpointPending = false;
mCheckpointActive = false;
mCheckpointThread = std::thread([this]{ CheckpointThread(); });
// Open another connection to the DB to prevent blocking the main thread.
//
// If it fails, then we won't checkpoint until the main thread closes
// the associated DB.
sqlite3 *db = nullptr;
const auto name = sqlite3_db_filename(mDB, nullptr);
if (sqlite3_open(name, &db) == SQLITE_OK &&
// Configure it to be safe
ModeConfig(db, "main", SafeConfig) ) {
mCheckpointThread = std::thread([this, db]{ CheckpointThread(db); });
}
else
sqlite3_close(db);
// Install our checkpoint hook
sqlite3_wal_hook(mDB, CheckpointHook, this);
@@ -213,7 +226,8 @@ bool DBConnection::Close()
}
// And wait for it to do so
mCheckpointThread.join();
if (mCheckpointThread.joinable())
mCheckpointThread.join();
// We're done with the prepared statements
{
@@ -373,22 +387,14 @@ sqlite3_stmt *DBConnection::Prepare(enum StatementID id, const char *sql)
return stmt;
}
void DBConnection::CheckpointThread()
void DBConnection::CheckpointThread(sqlite3 *db)
{
// Open another connection to the DB to prevent blocking the main thread.
//
// If it fails, then we won't checkpoint until the main thread closes
// the associated DB.
sqlite3 *db = nullptr;
const auto name = sqlite3_db_filename(mDB, nullptr);
int rc = SQLITE_OK;
bool giveUp = false;
auto rc = sqlite3_open(name, &db);
if (rc == SQLITE_OK)
const char *name = nullptr;
if (db)
{
// Configure it to be safe
ModeConfig(db, "main", SafeConfig);
name = sqlite3_db_filename(db, nullptr);
while (true)
{
{
@@ -484,8 +490,9 @@ void DBConnection::CheckpointThread()
}
// All done (always close)
rc = sqlite3_close(db);
if (rc != SQLITE_OK)
if (db)
rc = sqlite3_close(db);
if (rc != SQLITE_OK && name)
{
wxLogMessage("Checkpoint thread failed to close %s\n"
"\tErrCode: %d\n"

View File

@@ -98,7 +98,7 @@ public:
private:
bool ModeConfig(sqlite3 *db, const char *schema, const char *config);
void CheckpointThread();
void CheckpointThread(sqlite3 *db);
static int CheckpointHook(void *data, sqlite3 *db, const char *schema, int pages);
private: