libsql-sqlite3: Make libsql_stmt_interrupt() abort an in-flight step#2248
Merged
Conversation
libsql_stmt_interrupt() set a per-statement isInterrupted flag, but the VDBE execution loop only ever checked the connection-wide db->u1.isInterrupted. A statement already executing inside sqlite3_step() therefore ran to completion regardless of the request; the flag was only observed at the next step() entry. Check p->isInterrupted alongside db->u1.isInterrupted at both VDBE interrupt-check sites so an interrupt requested mid-execution aborts the running statement promptly with SQLITE_INTERRUPT, without touching the connection-wide interrupt state (other statements keep running). Set and clear the flag atomically, mirroring sqlite3_interrupt(), since the request may come from another thread. Tests: - test/interruptstmt.test: deterministic regression via a new sqlite_stmt_interrupt_count test hook, covering the in-loop check and the connection-flag-stays-clear property. - test/interrupttest.c: standalone multi-threaded test of the real cross-thread case (interrupt a step() in flight) and statement-level granularity. Build and run with `make interrupttest`.
The 0.10.0-pre.3 version bump (61d629a) updated the workspace Cargo.toml versions but not Cargo.lock, which stayed at 0.10.0-pre.2. Any cargo invocation (including the c-bundle-validate CI job's 'cargo xtask build-bundled') rewrites the lockfile to match, leaving an uncommitted Cargo.lock change that fails the job's 'git diff --quiet' check. Regenerate the lockfile so it matches the committed Cargo.toml.
penberg
added a commit
to tursodatabase/libsql-js
that referenced
this pull request
Jun 2, 2026
Query timeouts previously relied on a per-connection execution lock that serialized every operation so the timer wheel's connection.interrupt() would unambiguously hit the timed-out operation. This serialized all concurrent work on a connection and added a mutex acquisition to every call. Use libsql_stmt_interrupt() instead: the timer wheel now interrupts the specific statement that timed out (via a new Interruptible trait, so the wheel can target either a statement or a connection), leaving other concurrent operations on the same connection untouched. This removes execution_lock entirely, along with acquire_execution_lock and the deadline/remaining plumbing it required. Depends on: tursodatabase/libsql#2248
penberg
added a commit
to tursodatabase/libsql-js
that referenced
this pull request
Jun 2, 2026
Query timeouts previously relied on a per-connection execution lock that serialized every operation so the timer wheel's connection.interrupt() would unambiguously hit the timed-out operation. This serialized all concurrent work on a connection and added a mutex acquisition to every call. Use libsql_stmt_interrupt() instead: the timer wheel now interrupts the specific statement that timed out (via a new Interruptible trait, so the wheel can target either a statement or a connection), leaving other concurrent operations on the same connection untouched. This removes execution_lock entirely, along with acquire_execution_lock and the deadline/remaining plumbing it required. Depends on: tursodatabase/libsql#2248
penberg
added a commit
to tursodatabase/libsql-js
that referenced
this pull request
Jun 2, 2026
…#226) Query timeouts previously relied on a per-connection execution lock that serialized every operation so the timer wheel's connection.interrupt() would unambiguously hit the timed-out operation. This serialized all concurrent work on a connection and added a mutex acquisition to every call. Use libsql_stmt_interrupt() instead: the timer wheel now interrupts the specific statement that timed out (via a new Interruptible trait, so the wheel can target either a statement or a connection), leaving other concurrent operations on the same connection untouched. This removes execution_lock entirely, along with acquire_execution_lock and the deadline/remaining plumbing it required. Depends on: tursodatabase/libsql#2248
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
libsql_stmt_interrupt() set a per-statement isInterrupted flag, but the
VDBE execution loop only ever checked the connection-wide
db->u1.isInterrupted. A statement already executing inside sqlite3_step()
therefore ran to completion regardless of the request; the flag was only
observed at the next step() entry.
Check p->isInterrupted alongside db->u1.isInterrupted at both VDBE
interrupt-check sites so an interrupt requested mid-execution aborts the
running statement promptly with SQLITE_INTERRUPT, without touching the
connection-wide interrupt state (other statements keep running). Set and
clear the flag atomically, mirroring sqlite3_interrupt(), since the
request may come from another thread.
Tests:
sqlite_stmt_interrupt_count test hook, covering the in-loop check and
the connection-flag-stays-clear property.
cross-thread case (interrupt a step() in flight) and statement-level
granularity. Build and run with
make interrupttest.