Skip to content

Commit 91f10e4

Browse files
authored
Merge pull request #618 from ainar-g/master
Avoid goroutine leak on error in query with context
2 parents 2704adc + 8540d8a commit 91f10e4

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

conn_go18.go

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ func (cn *conn) QueryContext(ctx context.Context, query string, args []driver.Na
1919
finish := cn.watchCancel(ctx)
2020
r, err := cn.query(query, list)
2121
if err != nil {
22+
if finish != nil {
23+
finish()
24+
}
2225
return nil, err
2326
}
2427
r.finish = finish

go18_test.go

+31
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package pq
55
import (
66
"context"
77
"database/sql"
8+
"runtime"
89
"testing"
910
"time"
1011
)
@@ -155,6 +156,36 @@ func TestContextCancelQuery(t *testing.T) {
155156
}
156157
}
157158

159+
// TestIssue617 tests that a failed query in QueryContext doesn't lead to a
160+
// goroutine leak.
161+
func TestIssue617(t *testing.T) {
162+
db := openTestConn(t)
163+
defer db.Close()
164+
165+
const N = 10
166+
167+
numGoroutineStart := runtime.NumGoroutine()
168+
for i := 0; i < N; i++ {
169+
func() {
170+
ctx, cancel := context.WithCancel(context.Background())
171+
defer cancel()
172+
_, err := db.QueryContext(ctx, `SELECT * FROM DOESNOTEXIST`)
173+
pqErr, _ := err.(*Error)
174+
// Expecting "pq: relation \"doesnotexist\" does not exist" error.
175+
if err == nil || pqErr == nil || pqErr.Code != "42P01" {
176+
t.Fatalf("expected undefined table error, got %v", err)
177+
}
178+
}()
179+
}
180+
numGoroutineFinish := runtime.NumGoroutine()
181+
182+
// We use N/2 and not N because the GC and other actors may increase or
183+
// decrease the number of goroutines.
184+
if numGoroutineFinish-numGoroutineStart >= N/2 {
185+
t.Errorf("goroutine leak detected, was %d, now %d", numGoroutineStart, numGoroutineFinish)
186+
}
187+
}
188+
158189
func TestContextCancelBegin(t *testing.T) {
159190
db := openTestConn(t)
160191
defer db.Close()

0 commit comments

Comments
 (0)