1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-25 15:29:32 -05:00

Implement Deno.kill for windows (#5347)

This commit is contained in:
Ali Hasani 2020-05-17 21:41:24 +04:30 committed by GitHub
parent a054250a2c
commit eddb916883
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 104 additions and 67 deletions

View file

@ -1120,8 +1120,6 @@ declare namespace Deno {
*
* Deno.kill(p.pid, Deno.Signal.SIGINT);
*
* Throws Error (not yet implemented) on Windows
*
* Requires `allow-run` permission. */
export function kill(pid: number, signo: number): void;

View file

@ -1,12 +1,8 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { sendSync, sendAsync } from "./dispatch_json.ts";
import { assert } from "../util.ts";
import { build } from "../build.ts";
export function kill(pid: number, signo: number): void {
if (build.os === "windows") {
throw new Error("Not yet implemented");
}
sendSync("op_kill", { pid, signo });
}

View file

@ -5,12 +5,20 @@ import {
assertStrContains,
unitTest,
} from "./test_util.ts";
const { kill, run, readFile, open, makeTempDir, writeFile } = Deno;
const {
kill,
run,
readFile,
open,
makeTempDir,
writeFile,
writeFileSync,
} = Deno;
unitTest(function runPermissions(): void {
let caughtError = false;
try {
Deno.run({ cmd: ["python", "-c", "print('hello world')"] });
run({ cmd: ["python", "-c", "print('hello world')"] });
} catch (e) {
caughtError = true;
assert(e instanceof Deno.errors.PermissionDenied);
@ -99,7 +107,7 @@ while True:
pass
`;
Deno.writeFileSync(`${cwd}/${pyProgramFile}.py`, enc.encode(pyProgram));
writeFileSync(`${cwd}/${pyProgramFile}.py`, enc.encode(pyProgram));
const p = run({
cwd,
cmd: ["python", `${pyProgramFile}.py`],
@ -108,7 +116,7 @@ while True:
// Write the expected exit code *after* starting python.
// This is how we verify that `run()` is actually asynchronous.
const code = 84;
Deno.writeFileSync(`${cwd}/${exitCodeFile}`, enc.encode(`${code}`));
writeFileSync(`${cwd}/${exitCodeFile}`, enc.encode(`${code}`));
const status = await p.status();
assertEquals(status.success, false);
@ -325,8 +333,6 @@ unitTest(function signalNumbers(): void {
}
});
// Ignore signal tests on windows for now...
if (Deno.build.os !== "windows") {
unitTest(function killPermissions(): void {
let caughtError = false;
try {
@ -334,7 +340,7 @@ if (Deno.build.os !== "windows") {
// subprocess we can safely kill. Instead we send SIGCONT to the current
// process - assuming that Deno does not have a special handler set for it
// and will just continue even if a signal is erroneously sent.
Deno.kill(Deno.pid, Deno.Signal.SIGCONT);
kill(Deno.pid, Deno.Signal.SIGCONT);
} catch (e) {
caughtError = true;
assert(e instanceof Deno.errors.PermissionDenied);
@ -342,9 +348,7 @@ if (Deno.build.os !== "windows") {
assert(caughtError);
});
unitTest({ perms: { run: true } }, async function killSuccess(): Promise<
void
> {
unitTest({ perms: { run: true } }, async function killSuccess(): Promise<void> {
const p = run({
cmd: ["python", "-c", "from time import sleep; sleep(10000)"],
});
@ -375,10 +379,8 @@ if (Deno.build.os !== "windows") {
} catch (e) {
err = e;
}
assert(!!err);
assert(err instanceof TypeError);
p.close();
});
}

View file

@ -1,6 +1,23 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
use crate::op_error::OpError;
#[cfg(not(unix))]
const SIGINT: i32 = 2;
#[cfg(not(unix))]
const SIGKILL: i32 = 9;
#[cfg(not(unix))]
const SIGTERM: i32 = 15;
#[cfg(not(unix))]
use winapi::{
shared::minwindef::DWORD,
um::{
handleapi::CloseHandle,
processthreadsapi::{OpenProcess, TerminateProcess},
winnt::PROCESS_TERMINATE,
},
};
#[cfg(unix)]
pub fn kill(pid: i32, signo: i32) -> Result<(), OpError> {
use nix::sys::signal::{kill as unix_kill, Signal};
@ -11,7 +28,29 @@ pub fn kill(pid: i32, signo: i32) -> Result<(), OpError> {
}
#[cfg(not(unix))]
pub fn kill(_pid: i32, _signal: i32) -> Result<(), OpError> {
// TODO: implement this for windows
pub fn kill(pid: i32, signal: i32) -> Result<(), OpError> {
match signal {
SIGINT | SIGKILL | SIGTERM => {
if pid <= 0 {
return Err(OpError::type_error("unsupported pid".to_string()));
}
unsafe {
let handle = OpenProcess(PROCESS_TERMINATE, 0, pid as DWORD);
if handle.is_null() {
return Err(OpError::from(std::io::Error::last_os_error()));
}
if TerminateProcess(handle, 1) == 0 {
CloseHandle(handle);
return Err(OpError::from(std::io::Error::last_os_error()));
}
if CloseHandle(handle) == 0 {
return Err(OpError::from(std::io::Error::last_os_error()));
}
}
}
_ => {
return Err(OpError::type_error("unsupported signal".to_string()));
}
}
Ok(())
}

View file

@ -351,12 +351,15 @@ test("requestBodyReaderWithTransferEncoding", async function (): Promise<void> {
test({
name: "destroyed connection",
// FIXME(bartlomieju): hangs on windows, cause can't do `Deno.kill`
ignore: true,
fn: async (): Promise<void> => {
// Runs a simple server as another process
const p = Deno.run({
cmd: [Deno.execPath(), "--allow-net", "http/testdata/simple_server.ts"],
cmd: [
Deno.execPath(),
"run",
"--allow-net",
"http/testdata/simple_server.ts",
],
stdout: "piped",
});
@ -392,13 +395,12 @@ test({
test({
name: "serveTLS",
// FIXME(bartlomieju): hangs on windows, cause can't do `Deno.kill`
ignore: true,
fn: async (): Promise<void> => {
// Runs a simple server as another process
const p = Deno.run({
cmd: [
Deno.execPath(),
"run",
"--allow-net",
"--allow-read",
"http/testdata/simple_https_server.ts",