Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,16 @@ function Connection(options, queues = {}, { onopen = noop, onend = noop, onclose
}

function nextWrite(fn) {
if (!socket) {
// closed() nulls the socket and reconnect() only recreates it on a later
// timer. write() is also reached from the 'data' handler, so a throw here
// has no query to reject and escapes as an uncaughtException. Settle the
// pending queries rather than dropping the write, or the caller hangs.
nextWriteTimer !== null && clearImmediate(nextWriteTimer)
chunk = nextWriteTimer = null
error(Errors.connection('CONNECTION_CLOSED', options, socket))
return false
}
const x = socket.write(chunk, fn)
nextWriteTimer !== null && clearImmediate(nextWriteTimer)
chunk = nextWriteTimer = null
Expand Down
26 changes: 26 additions & 0 deletions tests/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2707,6 +2707,32 @@ t('Ensure reserve on query throws proper error', async() => {
]
})

t('Writing to a closed reserved connection rejects instead of crashing', async() => {
let downstream
const proxy = net.createServer(x => {
downstream = x
const upstream = net.connect(5432, '127.0.0.1')
x.pipe(upstream).pipe(x)
x.on('error', () => upstream.destroy())
upstream.on('error', () => x.destroy())
})

await new Promise(r => proxy.listen(0, r))

const sql = postgres({ ...options, host: '127.0.0.1', port: proxy.address().port, max: 1 })
, reserved = await sql.reserve()

await reserved`select 1`
downstream.end()
await delay(50)

const code = await reserved`select 1`.catch(e => e.code)
reserved.release()
proxy.close()

return ['CONNECTION_CLOSED', code]
})

t('query during copy error', async() => {
const sql = postgres(options) // eslint-disable-line
await sql`create table test (id serial primary key, name text)`
Expand Down