diff --git a/doc/api/child_process.md b/doc/api/child_process.md index 68f4d7ef14a..ef238fbe013 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -242,6 +242,11 @@ 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. +> 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 const { exec } = require('node:child_process'); exec('cat *.js missing_file | wc -l', (error, stdout, stderr) => { @@ -390,6 +395,11 @@ 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()`][]. +> 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 not spawned, behaviors such as I/O redirection and file globbing are not supported. @@ -585,6 +595,11 @@ current process. The `shell` option available in [`child_process.spawn()`][] is not supported by `child_process.fork()` and will be ignored if set. +> 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 `AbortController` is similar to calling `.kill()` on the child process except the error passed to the callback will be an `AbortError`: @@ -735,6 +750,11 @@ process, the default is [`process.env`][]. `undefined` values in `env` will be ignored. +> 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 exit code: diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index ee2c3ef3e1b..3abfd75ce8d 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -4718,6 +4718,85 @@ 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 +async function example() { + const ac = new AbortController(); + const server = http.createServer(handler); + server.listen({ port: 3000, signal: ac.signal }); + + await doWork(); + ac.abort(); +} +``` + +```js +// Use this instead +async function example() { + await using server = http.createServer(handler); + server.listen(3000); + + await doWork(); +} +``` + +```js +// Deprecated +async function example() { + const ac = new AbortController(); + const stream = addAbortSignal(ac.signal, fs.createReadStream(file)); + + await consume(stream); + ac.abort(); +} +``` + +```js +// Use this instead +async function example() { + await using stream = fs.createReadStream(file); + + await consume(stream); +} +``` + +```js +// Deprecated +async function example() { + const ac = new AbortController(); + const child = spawn(command, args, { signal: ac.signal }); + + await doWork(); + ac.abort(); +} +``` + +```js +// Use this instead +async function example() { + 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 348f0e75992..ab569a7b9c6 100644 --- a/doc/api/net.md +++ b/doc/api/net.md @@ -785,6 +785,11 @@ 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. +> 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 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 3b2308851f0..fea60dcc202 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.