Skip to content

Commit

Permalink
feat(runtime/spawn): add AbortSignal support (denoland#14538)
Browse files Browse the repository at this point in the history
  • Loading branch information
crowlKats authored May 11, 2022
1 parent e3f4b02 commit b67f874
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 1 deletion.
6 changes: 6 additions & 0 deletions cli/dts/lib.deno.unstable.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1346,6 +1346,12 @@ declare namespace Deno {
uid?: number;
/** Similar to `uid`, but sets the group ID of the child process. */
gid?: number;
/**
* An AbortSignal that allows closing the process using the corresponding
* AbortController by sending the process a SIGTERM signal.
* Not Supported by execSync.
*/
signal?: AbortSignal;

/** Defaults to "null". */
stdin?: "piped" | "inherit" | "null";
Expand Down
26 changes: 26 additions & 0 deletions cli/tests/unit/command_test.ts → cli/tests/unit/spawn_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,32 @@ Deno.test(
},
);

Deno.test(
{ permissions: { run: true, read: true } },
async function spawnAbort() {
const ac = new AbortController();
const child = Deno.spawnChild(Deno.execPath(), {
args: [
"eval",
"setTimeout(console.log, 1e8)",
],
signal: ac.signal,
stdout: "null",
stderr: "null",
});
queueMicrotask(() => ac.abort());
const status = await child.status;
assertEquals(status.success, false);
if (Deno.build.os === "windows") {
assertEquals(status.code, 1);
assertEquals(status.signal, null);
} else {
assertEquals(status.success, false);
assertEquals(status.code, 143);
}
},
);

Deno.test(
{ permissions: { read: true, run: false } },
async function spawnPermissions() {
Expand Down
12 changes: 11 additions & 1 deletion runtime/js/40_spawn.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
const core = window.Deno.core;
const { pathFromURL } = window.__bootstrap.util;
const { illegalConstructorKey } = window.__bootstrap.webUtil;
const { add, remove } = window.__bootstrap.abortSignal;
const {
ArrayPrototypeMap,
ObjectEntries,
Expand All @@ -26,6 +27,7 @@
stdin = "null",
stdout = "piped",
stderr = "piped",
signal = undefined,
} = {}) {
const child = core.opSync("op_spawn_child", {
cmd: pathFromURL(command),
Expand All @@ -39,7 +41,10 @@
stdout,
stderr,
});
return new Child(illegalConstructorKey, child);
return new Child(illegalConstructorKey, {
...child,
signal,
});
}

async function collectOutput(readableStream) {
Expand Down Expand Up @@ -91,6 +96,7 @@
}

constructor(key = null, {
signal,
rid,
pid,
stdinRid,
Expand Down Expand Up @@ -119,8 +125,12 @@
this.#stderr = readableStreamForRid(stderrRid);
}

const onAbort = () => this.kill("SIGTERM");
signal?.[add](onAbort);

this.#status = core.opAsync("op_spawn_wait", this.#rid).then((res) => {
this.#rid = null;
signal?.[remove](onAbort);
return res;
});
}
Expand Down

0 comments on commit b67f874

Please sign in to comment.