Destroy socket when there was an error on it (#1975)

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.
This commit is contained in:
Michal Brašna 2020-02-14 17:23:41 +01:00 committed by GitHub
parent e404dd517e
commit 823153138f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 1 deletions

View File

@ -545,7 +545,7 @@ Client.prototype.query = function (config, values, callback) {
Client.prototype.end = function (cb) {
this._ending = true
if (this.activeQuery) {
if (this.activeQuery || !this._queryable) {
// if we have an active query we need to force a disconnect
// on the socket - otherwise a hung query could block end forever
this.connection.stream.destroy()

View File

@ -1,6 +1,7 @@
'use strict'
var helper = require('./test-helper')
const pg = helper.pg
const native = helper.args.native
const suite = new helper.Suite()
suite.test('connecting to invalid port', (cb) => {
@ -99,3 +100,31 @@ suite.test('connection-level errors cause future queries to fail', (cb) => {
}))
}))
})
suite.test('handles socket error during pool.query and destroys it immediately', (cb) => {
const pool = new pg.Pool({ max: 1 })
if (native) {
pool.query('SELECT pg_sleep(10)', [], (err) => {
assert.equal(err.message, 'canceling statement due to user request')
cb()
})
setTimeout(() => {
pool._clients[0].native.cancel((err) => {
assert.ifError(err)
})
}, 100)
} else {
pool.query('SELECT pg_sleep(10)', [], (err) => {
assert.equal(err.message, 'network issue')
assert.equal(stream.destroyed, true)
cb()
})
const stream = pool._clients[0].connection.stream
setTimeout(() => {
stream.emit('error', new Error('network issue'))
}, 100)
}
})