stray query cancellation

This has been tracked down from a production issue.

I'll lead with the reproducer. Run with -race.

require modernc.org/sqlite v1.42.1

package main

import (
	"context"
	"database/sql"
	"fmt"
	"strings"

	_ "modernc.org/sqlite"
)

func main() {
	db, err := sql.Open("sqlite", ":memory:")
	if err != nil {
		panic(err)
	}

	db.SetMaxOpenConns(1)
	db.SetMaxIdleConns(1)

	conn, err := db.Conn(context.Background())
	if err != nil {
		panic(err)
	}

	for i := 0; ; i++ {
		ctx, cancel := context.WithCancel(context.Background())
		go cancel()                       // cancel "very soon" but not immediately
		conn.ExecContext(ctx, "SELECT 1") // might be interrupted, don't care

		// This query should never be interrupted, because it uses a non-cancellable context.
		_, err := conn.ExecContext(context.Background(), "SELECT 1")
		if err != nil && strings.Contains(err.Error(), "interrupted") {
			panic(err)
		}

		if i%1_00_000 == 0 {
			fmt.Printf("iteration %d\n", i)
		}
	}
}

It can take a very long time to fail on an idle machine, but running many instances concurrently triggers failures very quickly.

Sample local run:

$ go build -race .
$ ./sqlite-interrupt-bug  # can run for a long time, but eventually fails
iteration 0
^C
$ stress ./sqlite-interrupt-bug  # fails very quickly

/var/folders/vm/htvrhp4177v2dfhdjlvl0pqh0000gn/T/go-stress-20251227T162220-643681232
iteration 0
panic: interrupted (9)
^C

Again, this is happening to us semi-regularly in prod right now, so this is not just theoretical.

Edited by Josh Bleecher Snyder