Skip to content

Commit 70d5efc

Browse files
authored
fix: do not overwrite signal property of options (#2214)
Where we set a default abort signal for an operation, copy the incoming options object instead of overwriting the property as sometimes a user will reuse the options object they have passed in and be surprised when a signal that they didn't set aborts a subsequent operation.
1 parent fb8a6f1 commit 70d5efc

File tree

8 files changed

+63
-16
lines changed

8 files changed

+63
-16
lines changed

packages/kad-dht/src/query/manager.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,16 @@ export class QueryManager implements Startable {
113113

114114
if (options.signal == null) {
115115
// don't let queries run forever
116-
options.signal = AbortSignal.timeout(DEFAULT_QUERY_TIMEOUT)
116+
const signal = AbortSignal.timeout(DEFAULT_QUERY_TIMEOUT)
117117

118118
// this signal will get listened to for network requests, etc
119119
// so make sure we don't make a lot of noise in the logs
120-
setMaxListeners(Infinity, options.signal)
120+
setMaxListeners(Infinity, signal)
121+
122+
options = {
123+
...options,
124+
signal
125+
}
121126
}
122127

123128
const signal = anySignal([this.shutDownController.signal, options.signal])

packages/libp2p/src/connection/index.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,15 @@ export class ConnectionImpl implements Connection {
155155

156156
this.status = 'closing'
157157

158-
options.signal = options?.signal ?? AbortSignal.timeout(CLOSE_TIMEOUT)
159-
160-
setMaxListeners(Infinity, options.signal)
158+
if (options.signal == null) {
159+
const signal = AbortSignal.timeout(CLOSE_TIMEOUT)
160+
setMaxListeners(Infinity, signal)
161+
162+
options = {
163+
...options,
164+
signal
165+
}
166+
}
161167

162168
try {
163169
this.#log.trace('closing all streams')

packages/libp2p/src/identify/identify.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,15 @@ export class DefaultIdentifyService implements Startable, IdentifyService {
257257
async _identify (connection: Connection, options: AbortOptions = {}): Promise<Identify> {
258258
let stream: Stream | undefined
259259

260-
options.signal = options.signal ?? AbortSignal.timeout(this.timeout)
260+
if (options.signal == null) {
261+
const signal = AbortSignal.timeout(this.timeout)
262+
setMaxListeners(Infinity, signal)
263+
264+
options = {
265+
...options,
266+
signal
267+
}
268+
}
261269

262270
try {
263271
stream = await connection.newStream([this.identifyProtocolStr], {

packages/libp2p/src/ping/index.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,14 @@ class DefaultPingService implements Startable, PingService {
109109
let stream: Stream | undefined
110110
let onAbort = (): void => {}
111111

112-
options.signal = options.signal ?? AbortSignal.timeout(this.timeout)
112+
if (options.signal == null) {
113+
const signal = AbortSignal.timeout(this.timeout)
114+
115+
options = {
116+
...options,
117+
signal
118+
}
119+
}
113120

114121
try {
115122
stream = await connection.newStream(this.protocol, {
@@ -122,7 +129,7 @@ class DefaultPingService implements Startable, PingService {
122129
}
123130

124131
// make stream abortable
125-
options.signal.addEventListener('abort', onAbort, { once: true })
132+
options.signal?.addEventListener('abort', onAbort, { once: true })
126133

127134
const result = await pipe(
128135
[data],
@@ -150,7 +157,7 @@ class DefaultPingService implements Startable, PingService {
150157

151158
throw err
152159
} finally {
153-
options.signal.removeEventListener('abort', onAbort)
160+
options.signal?.removeEventListener('abort', onAbort)
154161
if (stream != null) {
155162
await stream.close()
156163
}

packages/libp2p/src/upgrader.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import type { ConnectionManager } from '@libp2p/interface-internal/connection-ma
2020
import type { Registrar } from '@libp2p/interface-internal/registrar'
2121
import type { Duplex, Source } from 'it-stream-types'
2222

23+
const DEFAULT_PROTOCOL_SELECT_TIMEOUT = 30000
24+
2325
interface CreateConnectionOptions {
2426
cryptoProtocol: string
2527
direction: 'inbound' | 'outbound'
@@ -439,9 +441,13 @@ export class DefaultUpgrader implements Upgrader {
439441
if (options.signal == null) {
440442
this.#log('No abort signal was passed while trying to negotiate protocols %s falling back to default timeout', protocols)
441443

442-
options.signal = AbortSignal.timeout(30000)
444+
const signal = AbortSignal.timeout(DEFAULT_PROTOCOL_SELECT_TIMEOUT)
445+
setMaxListeners(Infinity, signal)
443446

444-
setMaxListeners(Infinity, options.signal)
447+
options = {
448+
...options,
449+
signal
450+
}
445451
}
446452

447453
const { stream, protocol } = await mss.select(muxedStream, protocols, options)

packages/protocol-perf/src/perf-service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ export class PerfService implements Startable, PerfServiceInterface {
199199
log('performed %s to %p', this.protocol, connection.remotePeer)
200200
await stream.close()
201201
} catch (err: any) {
202-
log('error sending %s bytes to %p: %s', totalBytesSent, connection.remotePeer, err)
202+
log('error sending %d/%d bytes to %p: %s', totalBytesSent, sendBytes, connection.remotePeer, err)
203203
stream.abort(err)
204204
throw err
205205
}

packages/transport-tcp/src/socket-to-conn.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,14 @@ export const toMultiaddrConnection = (socket: Socket, options: ToConnectionOptio
126126
return
127127
}
128128

129-
options.signal = options.signal ?? AbortSignal.timeout(closeTimeout)
129+
if (options.signal == null) {
130+
const signal = AbortSignal.timeout(closeTimeout)
131+
132+
options = {
133+
...options,
134+
signal
135+
}
136+
}
130137

131138
try {
132139
log('%s closing socket', lOptsStr)

packages/transport-websockets/src/socket-to-conn.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,15 @@ export function socketToMaConn (stream: DuplexWebSocket, remoteAddr: Multiaddr,
4141

4242
async close (options: AbortOptions = {}) {
4343
const start = Date.now()
44-
options.signal = options.signal ?? AbortSignal.timeout(CLOSE_TIMEOUT)
44+
45+
if (options.signal == null) {
46+
const signal = AbortSignal.timeout(CLOSE_TIMEOUT)
47+
48+
options = {
49+
...options,
50+
signal
51+
}
52+
}
4553

4654
const listener = (): void => {
4755
const { host, port } = maConn.remoteAddr.toOptions()
@@ -51,15 +59,15 @@ export function socketToMaConn (stream: DuplexWebSocket, remoteAddr: Multiaddr,
5159
this.abort(new CodeError('Socket close timeout', 'ERR_SOCKET_CLOSE_TIMEOUT'))
5260
}
5361

54-
options.signal.addEventListener('abort', listener)
62+
options.signal?.addEventListener('abort', listener)
5563

5664
try {
5765
await stream.close()
5866
} catch (err: any) {
5967
log.error('error closing WebSocket gracefully', err)
6068
this.abort(err)
6169
} finally {
62-
options.signal.removeEventListener('abort', listener)
70+
options.signal?.removeEventListener('abort', listener)
6371
maConn.timeline.close = Date.now()
6472
}
6573
},

0 commit comments

Comments
 (0)