mattn / mattn/go-sqlite3

misuse of sqlite3_interrupt

Open
#681 11 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C
Stars
9.2k
Forks
1.2k
Avg merge
19m
Merged PRs (30d)
4

Description

This library is not using sqlite3_interrupt correctly. When called, it interrupts all current and future active statements, until the active statement count reaches 0. (An active statement is any statement for which the last call to sqlite3_step returned SQLITE_ROW, and it has not been reset or finalized since.) Consequently, it is entirely possible for one operation getting canceled to result in other, unrelated operations being canceled.

Consider the following (contrived) example.

db, err := sql.Open("sqlite3", ":memory:")
if err != nil {
	panic(err)
}
defer db.Close()

if _, err := db.Exec(`
	CREATE TABLE Foo(FooID INTEGER NOT NULL PRIMARY KEY);
	INSERT INTO Foo VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
`); err != nil {
	panic(err)
}

tx, err := db.Begin()
if err != nil {
	panic(err)
}
defer tx.Rollback()

rows, err := tx.Query("SELECT * FROM Foo")
if err != nil {
	panic(err)
}
defer rows.Close()

for rows.Next() {
	// nested func so defer works properly
	func() {
		ctx, cancel := context.WithCancel(context.Background())
		defer cancel()

		r2, err := tx.QueryContext(ctx, "SELECT * FROM Foo")
		if err != nil {
			panic(err)
		}
		defer r2.Close()

		cancel()

		// sleep so the cancellation go routine has time to run
		time.Sleep(time.Second)
	}()
}

fmt.Println(rows.Err())

This example always outputs "interrupted", even though the outer query was not canceled.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue names QueryContext, context cancellation, and sqlite3_interrupt but no repository files or tests. Start by reproducing the nested-query example and tracing cancellation from QueryContext to sqlite3_interrupt. Done means canceling one statement no longer interrupts an unrelated active statement, with a regression test covering the example.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, sqlite
Domain
backend, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.