Skip to content

fix(sqlite): reject work after shutdown close#4903

Closed
NathanFlurry wants to merge 1 commit intographite-base/4903from
driver-test-complaints/close-sqlite-on-shutdown
Closed

fix(sqlite): reject work after shutdown close#4903
NathanFlurry wants to merge 1 commit intographite-base/4903from
driver-test-complaints/close-sqlite-on-shutdown

Conversation

@NathanFlurry
Copy link
Copy Markdown
Member

Description

Please include a summary of the changes and the related issue. Please also include relevant motivation and context.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes.

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Copy link
Copy Markdown
Member Author

NathanFlurry commented May 3, 2026

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 3, 2026

Review: fix(sqlite): reject work after shutdown close

Adds a shutdown_closed: Arc<AtomicBool> guard to SqliteDb so any operation attempted after cleanup() returns SqliteRuntimeError::Closed instead of racing against a partially-closed connection.

Correctness

The three critical cases in open() (local-native path) are all covered:

  1. Shutdown before open_lockensure_not_shutdown_closed() fires before the lock is acquired; error returned immediately.
  2. Shutdown while waiting for open_lockcleanup() sets the flag before blocking on open_lock, so once open() acquires the lock the re-check inside catches it.
  3. Shutdown races open_database_from_envoy() — the post-open check closes the freshly-opened handle and returns Closed before storing it into self.db.

The cleanup() ordering (set flag → acquire open_lock → flush → close) correctly prevents a newly-opened handle from being left behind.

The Arc wrapping on AtomicBool is justified because SqliteDb: Clone — clones must share the same shutdown state.

Minor suggestions

1. Ordering: SeqCst can be relaxed to Acquire/Release

A Release store in cleanup() paired with Acquire loads in ensure_not_shutdown_closed() and the post-open check provides the same happens-before guarantee as SeqCst, at lower cost on ARM. Not a blocker.

2. cleanup() #[cfg] split is slightly awkward

The open_lock guard is declared in one #[cfg(feature = "sqlite-local")] attribute and the body in a second block. Combining them makes the drop scope explicit. Correctness is unaffected; readability nit only.

pub(crate) async fn cleanup(&self) -> Result<()> {
    self.shutdown_closed.store(true, Ordering::SeqCst);
    #[cfg(feature = "sqlite-local")]
    {
        let _open_guard = self.open_lock.lock().await;
        self.stop_preload_hint_flush_task();
        self.flush_preload_hints_before_close().await;
    }
    self.close().await
}

Coverage of public API

All async write paths (get_pages, commit, open, exec, query, run, execute, execute_write) have the guard added. The pub(crate) helpers (query_rows_cbor, exec_rows_cbor, run_cbor, execute_rows_cbor) delegate to the guarded public methods so they are covered transitively. close() is intentionally unguarded (idempotent, called by cleanup() itself). No gaps found.

Verdict

The fix is correct and well-scoped. The two nits above (memory ordering, #[cfg] style) are minor. LGTM.

@NathanFlurry NathanFlurry force-pushed the driver-test-complaints/close-sqlite-on-shutdown branch from 6aed029 to 9bf8eb7 Compare May 3, 2026 07:12
@NathanFlurry NathanFlurry force-pushed the driver-test-complaints/fix-shutdown-drain branch from 2f3266d to 977011c Compare May 3, 2026 07:12
@NathanFlurry NathanFlurry marked this pull request as draft May 3, 2026 07:19
@NathanFlurry NathanFlurry force-pushed the driver-test-complaints/close-sqlite-on-shutdown branch from 9bf8eb7 to c4e495b Compare May 3, 2026 07:34
@NathanFlurry NathanFlurry force-pushed the driver-test-complaints/fix-shutdown-drain branch from 977011c to 8ce7fbe Compare May 3, 2026 07:34
@NathanFlurry NathanFlurry changed the base branch from driver-test-complaints/fix-shutdown-drain to graphite-base/4903 May 3, 2026 21:03
This was referenced May 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant