Skip to content

Commit 65df905

Browse files
committed
Destroy socket when there was an error on it
When error happens on socket, potentially dead socket is kept open indefinitely by calling "connection.end()". Similar issue is that it keeps socket open until long-running query is finished even though the connection was ended.
1 parent 8eca181 commit 65df905

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

packages/pg/lib/client.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ Client.prototype.query = function (config, values, callback) {
545545
Client.prototype.end = function (cb) {
546546
this._ending = true
547547

548-
if (this.activeQuery) {
548+
if (this.activeQuery || !this._queryable) {
549549
// if we have an active query we need to force a disconnect
550550
// on the socket - otherwise a hung query could block end forever
551551
this.connection.stream.destroy()

packages/pg/test/integration/connection-pool/error-tests.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict'
22
var helper = require('./test-helper')
33
const pg = helper.pg
4+
const native = helper.args.native
45

56
const suite = new helper.Suite()
67
suite.test('connecting to invalid port', (cb) => {
@@ -99,3 +100,31 @@ suite.test('connection-level errors cause future queries to fail', (cb) => {
99100
}))
100101
}))
101102
})
103+
104+
suite.test('handles socket error during pool.query and destroys it immediately', (cb) => {
105+
const pool = new pg.Pool({ max: 1 })
106+
107+
if (native) {
108+
pool.query('SELECT pg_sleep(10)', [], (err) => {
109+
assert.equal(err.message, 'canceling statement due to user request')
110+
cb()
111+
})
112+
113+
setTimeout(() => {
114+
pool._clients[0].native.cancel((err) => {
115+
assert.ifError(err)
116+
})
117+
}, 100)
118+
} else {
119+
pool.query('SELECT pg_sleep(10)', [], (err) => {
120+
assert.equal(err.message, 'network issue')
121+
assert.equal(stream.destroyed, true)
122+
cb()
123+
})
124+
125+
const stream = pool._clients[0].connection.stream
126+
setTimeout(() => {
127+
stream.emit('error', new Error('network issue'))
128+
}, 100)
129+
}
130+
})

0 commit comments

Comments
 (0)