data race on `Close` and `interrupt`
When running the race detector on some unit tests there appears to be a data race on Close
and interrupt
:
WARNING: DATA RACE
Write at 0x00c00034e308 by goroutine 14:
modernc.org/sqlite.(*conn).Close()
/home/runner/go/pkg/mod/modernc.org/sqlite@v1.11.2/sqlite.go:1212 +0xbe
database/sql.(*driverConn).finalClose.func2()
/opt/hostedtoolcache/go/1.16.5/x64/src/database/sql/sql.go:592 +0x8b
database/sql.withLock()
/opt/hostedtoolcache/go/1.16.5/x64/src/database/sql/sql.go:3294 +0x7e
database/sql.(*driverConn).finalClose()
/opt/hostedtoolcache/go/1.16.5/x64/src/database/sql/sql.go:590 +0x189
database/sql.finalCloser.finalClose-fm()
/opt/hostedtoolcache/go/1.16.5/x64/src/database/sql/sql.go:636 +0x4f
database/sql.(*DB).Close()
/opt/hostedtoolcache/go/1.16.5/x64/src/database/sql/sql.go:847 +0x3f9
github.com/pomerium/pomerium-console/internal/testutil.WithTestSQLite.func2()
/home/runner/work/pomerium-console/pomerium-console/internal/testutil/db.go:179 +0x4b
github.com/pomerium/pomerium-console/internal/testutil.WithTestSQLite()
/home/runner/work/pomerium-console/pomerium-console/internal/testutil/db.go:181 +0x40d
github.com/pomerium/pomerium-console/pkg/db.TestDB_Migrate000027.func5()
/home/runner/work/pomerium-console/pomerium-console/pkg/db/db_migrate_000027_test.go:107 +0x5d
testing.tRunner()
/opt/hostedtoolcache/go/1.16.5/x64/src/testing/testing.go:1193 +0x202
Previous read at 0x00c00034e308 by goroutine 31:
modernc.org/sqlite.(*conn).interrupt()
/home/runner/go/pkg/mod/modernc.org/sqlite@v1.11.2/sqlite.go:1111 +0x18d
modernc.org/sqlite.(*stmt).query.func1()
/home/runner/go/pkg/mod/modernc.org/sqlite@v1.11.2/sqlite.go:580 +0x126
I believe the cause here is:
if c.tls != nil {
c.tls.Close()
c.tls = nil
}
And the access:
func (c *conn) interrupt(pdb uintptr) (err error) {
sqlite3.Xsqlite3_interrupt(c.tls, pdb)
return nil
}
Because interrupt
happens if a context is closed in a separate goroutine, it's possible for these two pieces of code to happen simultaneously.
A workaround would be to always close the context before closing the database.