diff --git a/cli/dts/lib.deno.ns.d.ts b/cli/dts/lib.deno.ns.d.ts index 469b8a3299fc2e..e2f1cb7efc9009 100644 --- a/cli/dts/lib.deno.ns.d.ts +++ b/cli/dts/lib.deno.ns.d.ts @@ -2020,6 +2020,11 @@ declare namespace Deno { stdout?: "inherit" | "piped" | "null" | number; stderr?: "inherit" | "piped" | "null" | number; stdin?: "inherit" | "piped" | "null" | number; + /** + * An AbortSignal that allows closing the process using the corresponding + * AbortController by sending the process a SIGTERM signal. + */ + signal?: AbortSignal; } /** Spawns new subprocess. RunOptions must contain at a minimum the `opt.cmd`, diff --git a/cli/tests/unit/process_test.ts b/cli/tests/unit/process_test.ts index 9bb4d7fc20c111..99becbc0f66dc8 100644 --- a/cli/tests/unit/process_test.ts +++ b/cli/tests/unit/process_test.ts @@ -510,3 +510,24 @@ unitTest({ perms: { run: true, read: true } }, function killFailed(): void { p.close(); }); + +unitTest( + { perms: { run: true, read: true } }, + async function runAbortSignal(): Promise { + const ac = new AbortController(); + const p = Deno.run({ + cmd: [ + Deno.execPath(), + "eval", + "setTimeout(console.log, 1e8)", + ], + signal: ac.signal, + }); + queueMicrotask(() => ac.abort()); + const status = await p.status(); + assertEquals(status.success, false); + assertEquals(status.code, 143); + assertEquals(status.signal, Deno.Signal.SIGTERM); + p.close(); + }, +); diff --git a/runtime/js/40_process.js b/runtime/js/40_process.js index 70a590f36d89d7..26ef80ee08fd9c 100644 --- a/runtime/js/40_process.js +++ b/runtime/js/40_process.js @@ -104,6 +104,7 @@ stdout = "inherit", stderr = "inherit", stdin = "inherit", + signal, }) { if (cmd[0] != null) { cmd[0] = pathFromURL(cmd[0]); @@ -119,7 +120,17 @@ stdoutRid: isRid(stdout) ? stdout : 0, stderrRid: isRid(stderr) ? stderr : 0, }); - return new Process(res); + const p = new Process(res); + if (signal) { + const stopper = () => { + p.kill(Deno.Signal.SIGTERM); + }; + signal.addEventListener("abort", stopper); + p.status().then(() => { + signal.removeEventListener("abort", stopper); + }); + } + return p; } window.__bootstrap.process = {