Skip to content

Commit

Permalink
cleanup transaction hooks on close
Browse files Browse the repository at this point in the history
  • Loading branch information
stevensJourney committed Jan 27, 2025
1 parent 70340d5 commit 60b42b6
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 12 deletions.
6 changes: 3 additions & 3 deletions cpp/ConnectionPool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ ConnectionPool::ConnectionPool(std::string dbName, std::string docPath,

onContextCallback = nullptr;
isConcurrencyEnabled = maxReads > 0;
isClosed = false;

readConnections = new ConnectionState *[maxReads];
// Open the read connections
Expand Down Expand Up @@ -169,9 +170,8 @@ void ConnectionPool::closeContext(ConnectionLockId contextId) {
}

void ConnectionPool::closeAll() {
// Prevent this pointer from being used if closed
rollbackPayload.dbName = NULL;
commitPayload.dbName = NULL;
isClosed = true;
// Stop any callbacks
sqlite3_commit_hook(writeConnection.connection,
NULL, NULL);
sqlite3_rollback_hook(writeConnection.connection,
Expand Down
6 changes: 4 additions & 2 deletions cpp/ConnectionPool.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,17 @@ class ConnectionPool {
std::vector<ConnectionLockId> writeQueue;

// Cached constant payloads for c style commit/rollback callbacks
TransactionCallbackPayload commitPayload;
TransactionCallbackPayload rollbackPayload;
const TransactionCallbackPayload commitPayload;
const TransactionCallbackPayload rollbackPayload;

void (*onContextCallback)(std::string, ConnectionLockId);
void (*onCommitCallback)(const TransactionCallbackPayload *);

bool isConcurrencyEnabled;

public:
bool isClosed;

ConnectionPool(std::string dbName, std::string docPath,
unsigned int numReadConnections);
~ConnectionPool();
Expand Down
1 change: 0 additions & 1 deletion cpp/ConnectionState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ std::future<void> ConnectionState::refreshSchema() {

void ConnectionState::close() {
{
// Now signal the thread to stop and notify it
std::unique_lock<std::mutex> g(workQueueMutex);
// prevent any new work from being queued
isClosed = true;
Expand Down
18 changes: 12 additions & 6 deletions cpp/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,25 @@ void transactionFinalizerHandler(const TransactionCallbackPayload *payload) {
* This function triggers an async invocation to call watch callbacks,
* avoiding holding SQLite up.
*/
invoker->invokeAsync([payload] {

// Make a copy of the payload data, this avoids a potential race condition
// where the async invocation might occur after closing a connection
auto dbName = std::make_shared<std::string>(*payload->dbName);
int event = payload->event;
invoker->invokeAsync([dbName, event] {
try {
// Prevent trying to create a JSI string for a potentially closed DB
if (payload == NULL || payload->dbName == NULL) {

ConnectionPool* connection = getConnection(*dbName);
if (connection == nullptr || connection->isClosed) {
return;
}

auto global = runtime->global();
jsi::Function handlerFunction = global.getPropertyAsFunction(
*runtime, "triggerTransactionFinalizerHook");

auto jsiDbName = jsi::String::createFromAscii(*runtime, *payload->dbName);
auto jsiEventType = jsi::Value((int)payload->event);
auto jsiDbName = jsi::String::createFromAscii(*runtime, *dbName);
auto jsiEventType = jsi::Value(event);
handlerFunction.call(*runtime, move(jsiDbName), move(jsiEventType));

Check warning on line 99 in cpp/bindings.cpp

View workflow job for this annotation

GitHub Actions / Test iOS (Only build)

unqualified call to 'std::move' [-Wunqualified-std-cast-call]
} catch (jsi::JSINativeException e) {
std::cout << e.what() << std::endl;
Expand Down
10 changes: 10 additions & 0 deletions cpp/sqliteBridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ SQLiteOPResult generateNotOpenResult(std::string const &dbName) {
};
}

ConnectionPool *getConnection(std::string const dbName) {
if (dbMap.count(dbName) == 0) {
// Connection is already closed
return nullptr;
}

return dbMap[dbName];
}


/**
* Opens SQL database with default settings
*/
Expand Down
2 changes: 2 additions & 0 deletions cpp/sqliteBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ SQLiteOPResult sqliteCloseDb(string const dbName);

void sqliteCloseAll();

ConnectionPool *getConnection(std::string const dbName);

SQLiteOPResult sqliteRemoveDb(string const dbName, string const docPath);

/**
Expand Down

0 comments on commit 60b42b6

Please sign in to comment.