Skip to content

Commit

Permalink
fix: don't leak socket if client is destroyed will connecting
Browse files Browse the repository at this point in the history
  • Loading branch information
ronag committed Apr 12, 2023
1 parent b20405e commit 7948b87
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 3 deletions.
25 changes: 23 additions & 2 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ const {
const FastBuffer = Buffer[Symbol.species]

const kClosedResolve = Symbol('kClosedResolve')
const kSignal = Symbol('kSignal')
const kAbortController = Symbol('kAbortController')

const channels = {}

Expand Down Expand Up @@ -240,6 +242,9 @@ class Client extends DispatcherBase {
this[kClosedResolve] = null
this[kMaxResponseSize] = maxResponseSize > -1 ? maxResponseSize : -1

this[kAbortController] = new AbortController()
this[kSignal] = this[kAbortController].signal

// kQueue is built up of 3 sections separated by
// the kRunningIdx and kPendingIdx indices.
// | complete | running | pending |
Expand Down Expand Up @@ -343,6 +348,8 @@ class Client extends DispatcherBase {
resolve()
}

this[kAbortController].abort()

if (!this[kSocket]) {
queueMicrotask(callback)
} else {
Expand Down Expand Up @@ -1064,15 +1071,17 @@ async function connect (client) {
})
}

let socket
try {
const socket = await new Promise((resolve, reject) => {
socket = await new Promise((resolve, reject) => {
client[kConnector]({
host,
hostname,
protocol,
port,
servername: client[kServerName],
localAddress: client[kLocalAddress]
localAddress: client[kLocalAddress],
signal: client[kSignal]
}, (err, socket) => {
if (err) {
reject(err)
Expand All @@ -1082,6 +1091,8 @@ async function connect (client) {
})
})

util.throwIfAborted(this[kSignal])

if (!llhttpInstance) {
llhttpInstance = await llhttpPromise
llhttpPromise = null
Expand Down Expand Up @@ -1124,6 +1135,11 @@ async function connect (client) {
}
client.emit('connect', client[kUrl], [client])
} catch (err) {
if (socket) {
socket.on('error', () => {}).destroy(err)
socket = null
}

client[kConnecting] = false

if (channels.connectError.hasSubscribers) {
Expand All @@ -1141,6 +1157,11 @@ async function connect (client) {
})
}

if (err.name === 'AbortError') {
assert(client.destroyed)
return
}

if (err.code === 'ERR_TLS_CERT_ALTNAME_INVALID') {
assert(client[kRunning] === 0)
while (client[kPending] > 0 && client[kQueue][client[kPendingIdx]].servername === client[kServerName]) {
Expand Down
3 changes: 2 additions & 1 deletion types/connector.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ declare namespace buildConnector {
port: string
servername?: string
localAddress?: string | null
httpSocket?: Socket
httpSocket?: Socket,
signal?: AbortSignal,
}

export type Callback = (...args: CallbackArgs) => void
Expand Down

0 comments on commit 7948b87

Please sign in to comment.