• Daniel Theophanes's avatar
    database/sql: fix race when canceling queries immediately · 2b283ced
    Daniel Theophanes authored
    Previously the following could happen, though in practice it would
    be rare.
    
    Goroutine 1:
    	(*Tx).QueryContext begins a query, passing in userContext
    
    Goroutine 2:
    	(*Tx).awaitDone starts to wait on the context derived from the passed in context
    
    Goroutine 1:
    	(*Tx).grabConn returns a valid (*driverConn)
    	The (*driverConn) passes to (*DB).queryConn
    
    Goroutine 3:
    	userContext is canceled
    
    Goroutine 2:
    	(*Tx).awaitDone unblocks and calls (*Tx).rollback
    	(*driverConn).finalClose obtains dc.Mutex
    	(*driverConn).finalClose sets dc.ci = nil
    
    Goroutine 1:
    	(*DB).queryConn obtains dc.Mutex in withLock
    	ctxDriverPrepare accepts dc.ci which is now nil
    	ctxCriverPrepare panics on the nil ci
    
    The fix for this is to guard the Tx methods with a RWLock
    holding it exclusivly when closing the Tx and holding a read lock
    when executing a query.
    
    Fixes #18719
    
    Change-Id: I37aa02c37083c9793dabd28f7f934a1c5cbc05ea
    Reviewed-on: https://go-review.googlesource.com/35550
    Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
    2b283ced
sql_test.go 67.2 KB