summaryrefslogtreecommitdiff
path: root/js
diff options
context:
space:
mode:
Diffstat (limited to 'js')
-rw-r--r--js/deno.ts9
-rw-r--r--js/process.ts89
-rw-r--r--js/process_test.ts68
3 files changed, 164 insertions, 2 deletions
diff --git a/js/deno.ts b/js/deno.ts
index 51cc0791a..46f018afc 100644
--- a/js/deno.ts
+++ b/js/deno.ts
@@ -68,7 +68,14 @@ export { FileInfo } from "./file_info";
export { connect, dial, listen, Listener, Conn } from "./net";
export { metrics, Metrics } from "./metrics";
export { resources } from "./resources";
-export { run, RunOptions, Process, ProcessStatus } from "./process";
+export {
+ kill,
+ run,
+ RunOptions,
+ Process,
+ ProcessStatus,
+ Signal
+} from "./process";
export { inspect } from "./console";
export { build, platform, OperatingSystem, Arch } from "./build";
export { version } from "./version";
diff --git a/js/process.ts b/js/process.ts
index a0eef63dd..c0a66f311 100644
--- a/js/process.ts
+++ b/js/process.ts
@@ -7,6 +7,7 @@ import { File, close } from "./files";
import { ReadCloser, WriteCloser } from "./io";
import { readAll } from "./buffer";
import { assert, unreachable } from "./util";
+import { platform } from "./build";
/** How to handle subprocess stdio.
*
@@ -51,6 +52,16 @@ async function runStatus(rid: number): Promise<ProcessStatus> {
}
}
+/** Send a signal to process under given PID. Unix only at this moment.
+ * If pid is negative, the signal will be sent to the process group identified
+ * by -pid.
+ */
+export function kill(pid: number, signo: number): void {
+ const builder = flatbuffers.createBuilder();
+ const inner = msg.Kill.createKill(builder, pid, signo);
+ dispatch.sendSync(builder, msg.Any.Kill, inner);
+}
+
export class Process {
readonly rid: number;
readonly pid: number;
@@ -113,6 +124,10 @@ export class Process {
close(): void {
close(this.rid);
}
+
+ kill(signo: number): void {
+ kill(this.pid, signo);
+ }
}
export interface ProcessStatus {
@@ -179,3 +194,77 @@ export function run(opt: RunOptions): Process {
return new Process(res);
}
+
+// From `kill -l`
+enum LinuxSignal {
+ SIGHUP = 1,
+ SIGINT = 2,
+ SIGQUIT = 3,
+ SIGILL = 4,
+ SIGTRAP = 5,
+ SIGABRT = 6,
+ SIGBUS = 7,
+ SIGFPE = 8,
+ SIGKILL = 9,
+ SIGUSR1 = 10,
+ SIGSEGV = 11,
+ SIGUSR2 = 12,
+ SIGPIPE = 13,
+ SIGALRM = 14,
+ SIGTERM = 15,
+ SIGSTKFLT = 16,
+ SIGCHLD = 17,
+ SIGCONT = 18,
+ SIGSTOP = 19,
+ SIGTSTP = 20,
+ SIGTTIN = 21,
+ SIGTTOU = 22,
+ SIGURG = 23,
+ SIGXCPU = 24,
+ SIGXFSZ = 25,
+ SIGVTALRM = 26,
+ SIGPROF = 27,
+ SIGWINCH = 28,
+ SIGIO = 29,
+ SIGPWR = 30,
+ SIGSYS = 31
+}
+
+// From `kill -l`
+enum MacOSSignal {
+ SIGHUP = 1,
+ SIGINT = 2,
+ SIGQUIT = 3,
+ SIGILL = 4,
+ SIGTRAP = 5,
+ SIGABRT = 6,
+ SIGEMT = 7,
+ SIGFPE = 8,
+ SIGKILL = 9,
+ SIGBUS = 10,
+ SIGSEGV = 11,
+ SIGSYS = 12,
+ SIGPIPE = 13,
+ SIGALRM = 14,
+ SIGTERM = 15,
+ SIGURG = 16,
+ SIGSTOP = 17,
+ SIGTSTP = 18,
+ SIGCONT = 19,
+ SIGCHLD = 20,
+ SIGTTIN = 21,
+ SIGTTOU = 22,
+ SIGIO = 23,
+ SIGXCPU = 24,
+ SIGXFSZ = 25,
+ SIGVTALRM = 26,
+ SIGPROF = 27,
+ SIGWINCH = 28,
+ SIGINFO = 29,
+ SIGUSR1 = 30,
+ SIGUSR2 = 31
+}
+
+/** Signals numbers. This is platform dependent.
+ */
+export const Signal = platform.os === "mac" ? MacOSSignal : LinuxSignal;
diff --git a/js/process_test.ts b/js/process_test.ts
index c89e1cae7..8d266617a 100644
--- a/js/process_test.ts
+++ b/js/process_test.ts
@@ -1,6 +1,6 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { test, testPerm, assert, assertEquals } from "./test_util.ts";
-const { run, DenoError, ErrorKind } = Deno;
+const { kill, run, DenoError, ErrorKind } = Deno;
test(function runPermissions(): void {
let caughtError = false;
@@ -223,3 +223,69 @@ testPerm({ run: true }, async function runEnv(): Promise<void> {
assertEquals(s, "01234567");
p.close();
});
+
+testPerm({ run: true }, async function runClose(): Promise<void> {
+ const p = run({
+ args: [
+ "python",
+ "-c",
+ "from time import sleep; import sys; sleep(10000); sys.stderr.write('error')"
+ ],
+ stderr: "piped"
+ });
+ assert(!p.stdin);
+ assert(!p.stdout);
+
+ p.close();
+
+ const data = new Uint8Array(10);
+ let r = await p.stderr.read(data);
+ assertEquals(r.nread, 0);
+ assertEquals(r.eof, true);
+});
+
+test(function signalNumbers(): void {
+ if (Deno.platform.os === "mac") {
+ assertEquals(Deno.Signal.SIGSTOP, 17);
+ } else if (Deno.platform.os === "linux") {
+ assertEquals(Deno.Signal.SIGSTOP, 19);
+ }
+});
+
+// Ignore signal tests on windows for now...
+if (Deno.platform.os !== "win") {
+ testPerm({ run: true }, async function killSuccess(): Promise<void> {
+ const p = run({
+ args: ["python", "-c", "from time import sleep; sleep(10000)"]
+ });
+
+ assertEquals(Deno.Signal.SIGINT, 2);
+ kill(p.pid, Deno.Signal.SIGINT);
+ const status = await p.status();
+
+ assertEquals(status.success, false);
+ assertEquals(status.code, undefined);
+ assertEquals(status.signal, Deno.Signal.SIGINT);
+ });
+
+ testPerm({ run: true }, async function killFailed(): Promise<void> {
+ const p = run({
+ args: ["python", "-c", "from time import sleep; sleep(10000)"]
+ });
+ assert(!p.stdin);
+ assert(!p.stdout);
+
+ let err;
+ try {
+ kill(p.pid, 12345);
+ } catch (e) {
+ err = e;
+ }
+
+ assert(!!err);
+ assertEquals(err.kind, Deno.ErrorKind.InvalidInput);
+ assertEquals(err.name, "InvalidInput");
+
+ p.close();
+ });
+}