From 68160a29bd8dfe97c74ab9a74000977da7783d6f Mon Sep 17 00:00:00 2001 From: Peter Rust Date: Mon, 20 Jun 2022 06:25:12 -0700 Subject: [PATCH] Fix #2556 by keeping callback errors from interfering with cleanup (#2753) * Fix #2556 (handleRowDescription of null) by keeping callback errors from interfering with cleanup * Added regression test for #2556 --- packages/pg/lib/query.js | 9 ++++- .../test/integration/gh-issues/2556-tests.js | 40 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 packages/pg/test/integration/gh-issues/2556-tests.js diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index c0dfedd1..6655a0e6 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -135,7 +135,14 @@ class Query extends EventEmitter { return this.handleError(this._canceledDueToError, con) } if (this.callback) { - this.callback(null, this._results) + try { + this.callback(null, this._results) + } + catch(err) { + process.nextTick(() => { + throw err + }) + } } this.emit('end', this._results) } diff --git a/packages/pg/test/integration/gh-issues/2556-tests.js b/packages/pg/test/integration/gh-issues/2556-tests.js new file mode 100644 index 00000000..13fdf80e --- /dev/null +++ b/packages/pg/test/integration/gh-issues/2556-tests.js @@ -0,0 +1,40 @@ +'use strict' +var helper = require('./../test-helper') +var assert = require('assert') + +var callbackError = new Error('TEST: Throw in callback') + +const suite = new helper.Suite() + +suite.test('it should cleanup client even if an error is thrown in a callback', (done) => { + // temporarily replace the test framework's uncaughtException handlers + // with a custom one that ignores the callbackError + let original_handlers = process.listeners('uncaughtException') + process.removeAllListeners('uncaughtException') + process.on('uncaughtException', (err) => { + if (err != callbackError) { + original_handlers[0](err) + } + }) + + // throw an error in a callback and verify that a subsequent query works without error + var client = helper.client() + client.query('SELECT NOW()', (err) => { + assert(!err) + setTimeout(reuseClient, 50) + throw callbackError + }) + + function reuseClient() { + client.query('SELECT NOW()', (err) => { + assert(!err) + + // restore the test framework's uncaughtException handlers + for (let handler of original_handlers) { + process.on('uncaughtException', handler) + } + + client.end(done) + }) + } +})