Fix leaks when database is closed while in sync iteration #156
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Most SQLite libraries use
sqlite3_close_v2to close connections. That function is designed for garbage-collected languages where the database and prepared statements might not be freed in the correct order. So if a statement exists as the timesqlite3_close_v2is called, the database is transitioned into a "zombie" state and resources are only fully released once prepared statements are closed as well.The Rust sync client prepares statements to manage subscriptions and caches those statements across multiple
powersync_controlcalls for efficiency. This causes issues if a database connection is closed while a sync iteration is active, since the database is transitioned into a zombie and we don't have an opportunity to free those statements. This might seem like a hypothetical scenario since all our SDKs would disconnect before closing connections, but our Dart sync tests are running into this and it's just not a good practice - closing the database should free everything.As a workaround, this uses the
xDisconnectcallback SQLite runs insqlite3_close_v2(pretty much specifically for this type of issue) in one of our vtabs as a hook to drop the sync client when it runs. Because our virtual tables are scoped to the database schema, we can use this to detect that the database is about to be closed and free resources.