aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/database/sql/sql_test.go
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@golang.org>2012-03-10 10:00:02 -0800
committerBrad Fitzpatrick <bradfitz@golang.org>2012-03-10 10:00:02 -0800
commit3297fc63d6226f6ed47a4fdb5962c78c55c5339c (patch)
treeb7460a8eaf8670853407fb434f35ed56a2158a5c /src/pkg/database/sql/sql_test.go
parent81a38fbb771d1282e5092dfc831ff225b60e2f13 (diff)
downloadgo-3297fc63d6226f6ed47a4fdb5962c78c55c5339c.tar.xz
database/sql: fix double connection free on Stmt.Query error
In a transaction, on a Stmt.Query error, it was possible for a connection to be added to a db's freelist twice. Should use the local releaseConn function instead. Thanks to Gwenael Treguier for the failing test. Also in this CL: propagate driver errors through releaseConn into *DB.putConn, which conditionally ignores the freelist addition if the driver signaled ErrBadConn, introduced in a previous CL. R=golang-dev, gary.burd CC=golang-dev https://golang.org/cl/5798049
Diffstat (limited to 'src/pkg/database/sql/sql_test.go')
-rw-r--r--src/pkg/database/sql/sql_test.go43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/pkg/database/sql/sql_test.go b/src/pkg/database/sql/sql_test.go
index 02ab20cd7c..90a40efa28 100644
--- a/src/pkg/database/sql/sql_test.go
+++ b/src/pkg/database/sql/sql_test.go
@@ -5,13 +5,35 @@
package sql
import (
+ "database/sql/driver"
"fmt"
"reflect"
+ "runtime"
"strings"
"testing"
"time"
)
+func init() {
+ type dbConn struct {
+ db *DB
+ c driver.Conn
+ }
+ freedFrom := make(map[dbConn]string)
+ putConnHook = func(db *DB, c driver.Conn) {
+ for _, oc := range db.freeConn {
+ if oc == c {
+ // print before panic, as panic may get lost due to conflicting panic
+ // (all goroutines asleep) elsewhere, since we might not unlock
+ // the mutex in freeConn here.
+ println("double free of conn. conflicts are:\nA) " + freedFrom[dbConn{db, c}] + "\n\nand\nB) " + stack())
+ panic("double free of conn.")
+ }
+ }
+ freedFrom[dbConn{db, c}] = stack()
+ }
+}
+
const fakeDBName = "foo"
var chrisBirthday = time.Unix(123456789, 0)
@@ -358,6 +380,22 @@ func TestTxQuery(t *testing.T) {
}
}
+func TestTxQueryInvalid(t *testing.T) {
+ db := newTestDB(t, "")
+ defer closeDB(t, db)
+
+ tx, err := db.Begin()
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer tx.Rollback()
+
+ _, err = tx.Query("SELECT|t1|name|")
+ if err == nil {
+ t.Fatal("Error expected")
+ }
+}
+
// Tests fix for issue 2542, that we release a lock when querying on
// a closed connection.
func TestIssue2542Deadlock(t *testing.T) {
@@ -562,3 +600,8 @@ func nullTestRun(t *testing.T, spec nullTestSpec) {
}
}
}
+
+func stack() string {
+ buf := make([]byte, 1024)
+ return string(buf[:runtime.Stack(buf, false)])
+}