Skip to content
This repository has been archived by the owner on Aug 29, 2023. It is now read-only.

Commit

Permalink
fix: hanging close promise (#140)
Browse files Browse the repository at this point in the history
  • Loading branch information
wemeetagain committed Feb 3, 2021
1 parent 8661c09 commit 3813100
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/socket-to-conn.js
Expand Up @@ -78,7 +78,10 @@ module.exports = (socket, options) => {
resolve()
}, CLOSE_TIMEOUT)

socket.once('close', () => clearTimeout(timeout))
socket.once('close', () => {
clearTimeout(timeout)
resolve()
})
socket.end(err => {
maConn.timeline.close = Date.now()
if (err) return reject(err)
Expand Down
32 changes: 32 additions & 0 deletions test/connection.spec.js
Expand Up @@ -50,4 +50,36 @@ describe('valid localAddr and remoteAddr', () => {
expect(dialerConn.remoteAddr.toString())
.to.equal(listenerConn.localAddr.toString())
})

it('should handle multiple simultaneous closes', async () => {
// Create a Promise that resolves when a connection is handled
let handled
const handlerPromise = new Promise(resolve => { handled = resolve })

const handler = conn => handled(conn)

// Create a listener with the handler
const listener = tcp.createListener(handler)

// Listen on the multi-address
await listener.listen(ma)

const localAddrs = listener.getAddrs()
expect(localAddrs.length).to.equal(1)

// Dial to that address
const dialerConn = await tcp.dial(localAddrs[0])

// Wait for the incoming dial to be handled
await handlerPromise

// Close the listener with two simultaneous calls to `close`
await Promise.race([
new Promise((resolve, reject) => setTimeout(() => reject(new Error('Timed out waiting for connection close')), 500)),
await Promise.all([
dialerConn.close(),
dialerConn.close()
])
])
})
})

0 comments on commit 3813100

Please sign in to comment.