diff options
| author | Chris Hines <chris.cs.guy@gmail.com> | 2015-09-14 03:44:56 -0400 |
|---|---|---|
| committer | Brad Fitzpatrick <bradfitz@golang.org> | 2015-10-16 15:17:03 +0000 |
| commit | 6de40099c88048c95df40c873e89b0e31f70ac24 (patch) | |
| tree | d5fde34e8e15ef68a5aaea1320f49265275e3cbf /src/database/sql/fakedb_test.go | |
| parent | 19aa4209aebce5deaf485268e210ed3fc29cacd5 (diff) | |
| download | go-6de40099c88048c95df40c873e89b0e31f70ac24.tar.xz | |
database/sql: avoid deadlock waiting for connections
Previously with db.maxOpen > 0, db.maxOpen+n failed connection attempts
started concurrently could result in a deadlock. DB.conn and
DB.openNewConnection did not trigger the DB.connectionOpener go routine
after a failed connection attempt. This omission could leave go routines
waiting for DB.connectionOpener forever.
In addition the logic to track the state of the pool was inconsistent.
db.numOpen was sometimes incremented optimistically and sometimes not.
This change harmonizes the logic and eliminates the db.pendingOpens
variable, making the logic easier to understand and maintain.
Fixes #10886
Change-Id: I983c4921a3dacfbd531c3d7f8d2da8a592e9922a
Reviewed-on: https://go-review.googlesource.com/14547
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'src/database/sql/fakedb_test.go')
| -rw-r--r-- | src/database/sql/fakedb_test.go | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/src/database/sql/fakedb_test.go b/src/database/sql/fakedb_test.go index 112f280ec5..f1e8f6cb6e 100644 --- a/src/database/sql/fakedb_test.go +++ b/src/database/sql/fakedb_test.go @@ -153,12 +153,32 @@ func TestDrivers(t *testing.T) { } } +// hook to simulate connection failures +var hookOpenErr struct { + sync.Mutex + fn func() error +} + +func setHookOpenErr(fn func() error) { + hookOpenErr.Lock() + defer hookOpenErr.Unlock() + hookOpenErr.fn = fn +} + // Supports dsn forms: // <dbname> // <dbname>;<opts> (only currently supported option is `badConn`, // which causes driver.ErrBadConn to be returned on // every other conn.Begin()) func (d *fakeDriver) Open(dsn string) (driver.Conn, error) { + hookOpenErr.Lock() + fn := hookOpenErr.fn + hookOpenErr.Unlock() + if fn != nil { + if err := fn(); err != nil { + return nil, err + } + } parts := strings.Split(dsn, ";") if len(parts) < 1 { return nil, errors.New("fakedb: no database name") |
