From d0c514609098e0fe68c4ca01093fe94fc996ac75 Mon Sep 17 00:00:00 2001 From: Efe Karasakal Date: Tue, 7 Jul 2026 19:39:38 +0200 Subject: [PATCH 1/4] doc: discourage AbortSignal cleanup for long-lived resources Signed-off-by: Efe Karasakal --- doc/api/child_process.md | 16 ++++++++++ doc/api/deprecations.md | 67 ++++++++++++++++++++++++++++++++++++++++ doc/api/net.md | 4 +++ doc/api/stream.md | 4 +++ 4 files changed, 91 insertions(+) diff --git a/doc/api/child_process.md b/doc/api/child_process.md index 68f4d7ef14a9..c88ead4f83dd 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -242,6 +242,10 @@ can be used to specify the character encoding used to decode the stdout and stderr output. If `encoding` is `'buffer'`, or an unrecognized character encoding, `Buffer` objects will be passed to the callback instead. +> Stability: 0 - Deprecated. Using the `signal` option to destroy long-lived +> child process resources is documentation-only deprecated. See +> [DEP0209](deprecations.md#dep0209-using-abortsignal-to-dispose-of-resources). + ```cjs const { exec } = require('node:child_process'); exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => { @@ -390,6 +394,10 @@ except that it does not spawn a shell by default. Rather, the specified executable `file` is spawned directly as a new process making it slightly more efficient than [`child_process.exec()`][]. +> Stability: 0 - Deprecated. Using the `signal` option to destroy long-lived +> child process resources is documentation-only deprecated. See +> [DEP0209](deprecations.md#dep0209-using-abortsignal-to-dispose-of-resources). + The same options as [`child_process.exec()`][] are supported. Since a shell is not spawned, behaviors such as I/O redirection and file globbing are not supported. @@ -585,6 +593,10 @@ current process. The `shell` option available in [`child_process.spawn()`][] is not supported by `child_process.fork()` and will be ignored if set. +> Stability: 0 - Deprecated. Using the `signal` option to destroy long-lived +> child process resources is documentation-only deprecated. See +> [DEP0209](deprecations.md#dep0209-using-abortsignal-to-dispose-of-resources). + If the `signal` option is enabled, calling `.abort()` on the corresponding `AbortController` is similar to calling `.kill()` on the child process except the error passed to the callback will be an `AbortError`: @@ -735,6 +747,10 @@ process, the default is [`process.env`][]. `undefined` values in `env` will be ignored. +> Stability: 0 - Deprecated. Using the `signal` option to destroy long-lived +> child process resources is documentation-only deprecated. See +> [DEP0209](deprecations.md#dep0209-using-abortsignal-to-dispose-of-resources). + Example of running `ls -lh /usr`, capturing `stdout`, `stderr`, and the exit code: diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index ee2c3ef3e1b6..fe7e5fc670cb 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -4718,6 +4718,73 @@ replacing it keeps being called by [`server.listen()`][], and it will be removed in a future version of Node.js. Use [`server.listen()`][] instead of calling or overriding `_listen2`. +### DEP0209: Using `AbortSignal` to dispose of resources + + + +Type: Documentation-only + +Using `AbortSignal` to destroy long-lived resources is deprecated. Prefer +`using` for resource cleanup. + +`AbortSignal` is still a good fit for canceling actions, propagating +cancellation from the outside, and timeouts. + +```js +// Deprecated +const ac = new AbortController(); +const server = http.createServer(handler); +server.listen({ port: 3000, signal: ac.signal }); + +await doWork(); +ac.abort(); +``` + +```js +// Use this instead +await using server = http.createServer(handler); +server.listen(3000); + +await doWork(); +``` + +```js +// Deprecated +const ac = new AbortController(); +const stream = addAbortSignal(ac.signal, fs.createReadStream(file)); + +await consume(stream); +ac.abort(); +``` + +```js +// Use this instead +await using stream = fs.createReadStream(file); + +await consume(stream); +``` + +```js +// Deprecated +const ac = new AbortController(); +const child = spawn(command, args, { signal: ac.signal }); + +await doWork(); +ac.abort(); +``` + +```js +// Use this instead +using child = spawn(command, args); + +await doWork(); +``` + [DEP0142]: #dep0142-repl_builtinlibs [DEP0156]: #dep0156-aborted-property-and-abort-aborted-event-in-http [NIST SP 800-38D]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf diff --git a/doc/api/net.md b/doc/api/net.md index 348f0e75992c..7e90f261d4a7 100644 --- a/doc/api/net.md +++ b/doc/api/net.md @@ -785,6 +785,10 @@ Otherwise, if `path` is specified, it behaves the same as [`server.listen(path[, backlog][, callback])`][`server.listen(path)`]. If none of them is specified, an error will be thrown. +> Stability: 0 - Deprecated. Using the `signal` option to destroy long-lived +> server resources is documentation-only deprecated. See +> [DEP0209](deprecations.md#dep0209-using-abortsignal-to-dispose-of-resources). + If `exclusive` is `false` (default), then cluster workers will use the same underlying handle, allowing connection handling duties to be shared. When `exclusive` is `true`, the handle is not shared, and attempted port sharing diff --git a/doc/api/stream.md b/doc/api/stream.md index 3b2308851f0d..fea60dcc2026 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -3570,6 +3570,10 @@ changes: Attaches an AbortSignal to a readable or writable stream. This lets code control stream destruction using an `AbortController`. +> Stability: 0 - Deprecated. Using [`stream.addAbortSignal()`][] to destroy +> long-lived stream resources is documentation-only deprecated. See +> [DEP0209](deprecations.md#dep0209-using-abortsignal-to-dispose-of-resources). + Calling `abort` on the `AbortController` corresponding to the passed `AbortSignal` will behave the same way as calling `.destroy(new AbortError())` on the stream, and `controller.error(new AbortError())` for webstreams. From d694ab073e9a81ce3d16ec64b3d831a453d1d104 Mon Sep 17 00:00:00 2001 From: Efe Karasakal Date: Tue, 7 Jul 2026 19:53:07 +0200 Subject: [PATCH 2/4] doc: wrap in async fns to please the linter Signed-off-by: Efe Karasakal --- doc/api/deprecations.md | 52 +++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index fe7e5fc670cb..0390e32ad003 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -4737,52 +4737,64 @@ cancellation from the outside, and timeouts. ```js // Deprecated -const ac = new AbortController(); -const server = http.createServer(handler); -server.listen({ port: 3000, signal: ac.signal }); +async function example() { + const ac = new AbortController(); + const server = http.createServer(handler); + server.listen({ port: 3000, signal: ac.signal }); -await doWork(); -ac.abort(); + await doWork(); + ac.abort(); +} ``` ```js // Use this instead -await using server = http.createServer(handler); -server.listen(3000); +async function example() { + await using server = http.createServer(handler); + server.listen(3000); -await doWork(); + await doWork(); +} ``` ```js // Deprecated -const ac = new AbortController(); -const stream = addAbortSignal(ac.signal, fs.createReadStream(file)); +async function example() { + const ac = new AbortController(); + const stream = addAbortSignal(ac.signal, fs.createReadStream(file)); -await consume(stream); -ac.abort(); + await consume(stream); + ac.abort(); +} ``` ```js // Use this instead -await using stream = fs.createReadStream(file); +async function example() { + await using stream = fs.createReadStream(file); -await consume(stream); + await consume(stream); +} ``` ```js // Deprecated -const ac = new AbortController(); -const child = spawn(command, args, { signal: ac.signal }); +async function example() { + const ac = new AbortController(); + const child = spawn(command, args, { signal: ac.signal }); -await doWork(); -ac.abort(); + await doWork(); + ac.abort(); +} ``` ```js // Use this instead -using child = spawn(command, args); +async function example() { + using child = spawn(command, args); -await doWork(); + await doWork(); +} ``` [DEP0142]: #dep0142-repl_builtinlibs From d878b94bd568940f533c663ecd52e0bb1dc8f8ff Mon Sep 17 00:00:00 2001 From: Efe Karasakal Date: Thu, 16 Jul 2026 20:11:21 +0200 Subject: [PATCH 3/4] doc: adjust pr link --- doc/api/deprecations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index 0390e32ad003..3abfd75ce8de 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -4723,7 +4723,7 @@ calling or overriding `_listen2`. From b5931a784bfb85bc48341167252ec655e1bb6fab Mon Sep 17 00:00:00 2001 From: Efe Karasakal Date: Sun, 23 Aug 2026 21:12:26 +0200 Subject: [PATCH 4/4] doc: apply review comment --- doc/api/child_process.md | 20 ++++++++++++-------- doc/api/net.md | 5 +++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/doc/api/child_process.md b/doc/api/child_process.md index c88ead4f83dd..ef238fbe013c 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -242,8 +242,9 @@ can be used to specify the character encoding used to decode the stdout and stderr output. If `encoding` is `'buffer'`, or an unrecognized character encoding, `Buffer` objects will be passed to the callback instead. -> Stability: 0 - Deprecated. Using the `signal` option to destroy long-lived -> child process resources is documentation-only deprecated. See +> Using the `signal` option to destroy a long-lived child process as a resource +> cleanup mechanism is deprecated. The `signal` option remains appropriate for +> cancellation, externally propagated aborts, and timeouts. See > [DEP0209](deprecations.md#dep0209-using-abortsignal-to-dispose-of-resources). ```cjs @@ -394,8 +395,9 @@ except that it does not spawn a shell by default. Rather, the specified executable `file` is spawned directly as a new process making it slightly more efficient than [`child_process.exec()`][]. -> Stability: 0 - Deprecated. Using the `signal` option to destroy long-lived -> child process resources is documentation-only deprecated. See +> Using the `signal` option to destroy a long-lived child process as a resource +> cleanup mechanism is deprecated. The `signal` option remains appropriate for +> cancellation, externally propagated aborts, and timeouts. See > [DEP0209](deprecations.md#dep0209-using-abortsignal-to-dispose-of-resources). The same options as [`child_process.exec()`][] are supported. Since a shell is @@ -593,8 +595,9 @@ current process. The `shell` option available in [`child_process.spawn()`][] is not supported by `child_process.fork()` and will be ignored if set. -> Stability: 0 - Deprecated. Using the `signal` option to destroy long-lived -> child process resources is documentation-only deprecated. See +> Using the `signal` option to destroy a long-lived child process as a resource +> cleanup mechanism is deprecated. The `signal` option remains appropriate for +> cancellation, externally propagated aborts, and timeouts. See > [DEP0209](deprecations.md#dep0209-using-abortsignal-to-dispose-of-resources). If the `signal` option is enabled, calling `.abort()` on the corresponding @@ -747,8 +750,9 @@ process, the default is [`process.env`][]. `undefined` values in `env` will be ignored. -> Stability: 0 - Deprecated. Using the `signal` option to destroy long-lived -> child process resources is documentation-only deprecated. See +> Using the `signal` option to destroy a long-lived child process as a resource +> cleanup mechanism is deprecated. The `signal` option remains appropriate for +> cancellation, externally propagated aborts, and timeouts. See > [DEP0209](deprecations.md#dep0209-using-abortsignal-to-dispose-of-resources). Example of running `ls -lh /usr`, capturing `stdout`, `stderr`, and the diff --git a/doc/api/net.md b/doc/api/net.md index 7e90f261d4a7..ab569a7b9c6f 100644 --- a/doc/api/net.md +++ b/doc/api/net.md @@ -785,8 +785,9 @@ Otherwise, if `path` is specified, it behaves the same as [`server.listen(path[, backlog][, callback])`][`server.listen(path)`]. If none of them is specified, an error will be thrown. -> Stability: 0 - Deprecated. Using the `signal` option to destroy long-lived -> server resources is documentation-only deprecated. See +> Using the `signal` option to destroy a long-lived server as a resource cleanup +> mechanism is deprecated. The `signal` option remains appropriate for +> cancellation, externally propagated aborts, and timeouts. See > [DEP0209](deprecations.md#dep0209-using-abortsignal-to-dispose-of-resources). If `exclusive` is `false` (default), then cluster workers will use the same