Skip to content

Data race between mysqlConn watcher and okHandler during context cancellation#1559

@bobvawter

Description

@bobvawter

Issue description

I have one goroutine running database transactions in a loop and another goroutine cancels the context being used. This leads to the data race shown below.

Example code

Execute with go test -v -race . -test.count 1000 -test.failfast -test.run 'TestRace'

funcTestRace(t*testing.T){r:=require.New(t) driver:= mysql.MySQLDriver{} connector, err:=driver.OpenConnector("root:SoupOrSecret@/mysql") r.NoError(err) db:=sql.OpenDB(connector) ctx, cancel:=context.WithTimeout(context.Background(), 5*time.Second) defercancel() triggerCancel:=make(chanstruct{}) done:=make(chanstruct{}) gofunc(){deferclose(done) didTrigger:=falseforctx.Err() ==nil{tx, err:=db.BeginTx(ctx, nil) iferrors.Is(err, context.Canceled){return } r.NoError(err) varoneinterr=tx.QueryRowContext(ctx, "SELECT 1").Scan(&one) iferrors.Is(err, context.Canceled){return } r.NoError(err) _=tx.Rollback() if!didTrigger{didTrigger=trueclose(triggerCancel) } } }() <-triggerCanceltime.Sleep(10*time.Millisecond) cancel() <-done }

Error log

WARNING: DATA RACE Write at 0x00c000392458 by goroutine 28578: github.com/go-sql-driver/mysql.(*mysqlConn).clearResult() /home/runner/go/pkg/mod/github.com/go-sql-driver/[email protected]/packets.go:630 +0x1c4 github.com/go-sql-driver/mysql.(*mysqlConn).cleanup() /home/runner/go/pkg/mod/github.com/go-sql-driver/[email protected]/connection.go:156 +0x1a4 github.com/go-sql-driver/mysql.(*mysqlConn).cancel() /home/runner/go/pkg/mod/github.com/go-sql-driver/[email protected]/connection.go:441 +0x84 github.com/go-sql-driver/mysql.(*mysqlConn).startWatcher.func1() /home/runner/go/pkg/mod/github.com/go-sql-driver/[email protected]/connection.go:628 +0x234 Previous read at 0x00c000392458 by goroutine 30352: github.com/go-sql-driver/mysql.(*okHandler).handleOkPacket() /home/runner/go/pkg/mod/github.com/go-sql-driver/[email protected]/packets.go:650 +0xfd github.com/go-sql-driver/mysql.(*okHandler).readResultSetHeaderPacket() /home/runner/go/pkg/mod/github.com/go-sql-driver/[email protected]/packets.go:536 +0x36f github.com/go-sql-driver/mysql.(*mysqlConn).exec() /home/runner/go/pkg/mod/github.com/go-sql-driver/[email protected]/connection.go:336 +0x18d github.com/go-sql-driver/mysql.(*mysqlConn).begin() /home/runner/go/pkg/mod/github.com/go-sql-driver/[email protected]/connection.go:121 +0x8a github.com/go-sql-driver/mysql.(*mysqlConn).BeginTx() /home/runner/go/pkg/mod/github.com/go-sql-driver/[email protected]/connection.go:498 +0x156 database/sql.ctxDriverBegin() /opt/hostedtoolcache/go/1.20.14/x64/src/database/sql/ctxutil.go:104 +0x105 database/sql.(*DB).beginDC.func1() /opt/hostedtoolcache/go/1.20.14/x64/src/database/sql/sql.go:1868 +0x156 database/sql.withLock() /opt/hostedtoolcache/go/1.20.14/x64/src/database/sql/sql.go:3405 +0xa2 database/sql.(*DB).beginDC() /opt/hostedtoolcache/go/1.20.14/x64/src/database/sql/sql.go:1864 +0x113 database/sql.(*DB).begin() /opt/hostedtoolcache/go/1.20.14/x64/src/database/sql/sql.go:1857 +0x104 database/sql.(*DB).BeginTx.func1() 

Configuration

Driver version (or git SHA): 1.8.0

Go version: 1.20.7 & 1.22.1

Server version: mysql-v8 & mariadb-v10

Server OS: Ubuntu 22.04 (an ubuntu-latest GitHub actions runner)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions