feat(unstable): Deno.ppid (#6539)

This commit is contained in:
uki00a 2020-07-08 23:35:45 +09:00 committed by GitHub
parent 231899695d
commit a2bf61d1ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 91 additions and 2 deletions

View file

@ -64,7 +64,7 @@ swc_ecma_visit = "0.7.0"
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.8", features = ["knownfolders", "objbase", "shlobj",
"winbase", "winerror"] }
"winbase", "winerror", "tlhelp32"] }
fwdansi = "1.1.0"
[target.'cfg(unix)'.dependencies]

View file

@ -1194,4 +1194,9 @@ declare namespace Deno {
* ```
*/
export function fstat(rid: number): Promise<FileInfo>;
/** **UNSTABLE**: New API, yet to be vetted.
* The pid of the current process's parent.
*/
export const ppid: number;
}

View file

@ -9,6 +9,7 @@ export interface Start {
denoVersion: string;
noColor: boolean;
pid: number;
ppid: number;
repl: boolean;
target: string;
tsVersion: string;

View file

@ -96,10 +96,11 @@ export function bootstrapMainRuntime(): void {
}
});
const { args, cwd, noColor, pid, repl, unstableFlag } = runtime.start();
const { args, cwd, noColor, pid, ppid, repl, unstableFlag } = runtime.start();
Object.defineProperties(denoNs, {
pid: readOnly(pid),
ppid: readOnly(ppid),
noColor: readOnly(noColor),
args: readOnly(Object.freeze(args)),
});

View file

@ -32,6 +32,7 @@ fn op_start(
"denoVersion": version::DENO,
"noColor": !colors::use_color(),
"pid": std::process::id(),
"ppid": ppid(),
"repl": gs.flags.subcommand == DenoSubcommand::Repl,
"target": env!("TARGET"),
"tsVersion": version::TYPESCRIPT,
@ -78,3 +79,62 @@ fn op_metrics(
"bytesReceived": m.bytes_received
})))
}
fn ppid() -> Value {
#[cfg(windows)]
{
// Adopted from rustup:
// https://github.com/rust-lang/rustup/blob/1.21.1/src/cli/self_update.rs#L1036
// Copyright Diggory Blake, the Mozilla Corporation, and rustup contributors.
// Licensed under either of
// - Apache License, Version 2.0
// - MIT license
use std::mem;
use winapi::shared::minwindef::DWORD;
use winapi::um::handleapi::{CloseHandle, INVALID_HANDLE_VALUE};
use winapi::um::processthreadsapi::GetCurrentProcessId;
use winapi::um::tlhelp32::{
CreateToolhelp32Snapshot, Process32First, Process32Next, PROCESSENTRY32,
TH32CS_SNAPPROCESS,
};
unsafe {
// Take a snapshot of system processes, one of which is ours
// and contains our parent's pid
let snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if snapshot == INVALID_HANDLE_VALUE {
return serde_json::to_value(-1).unwrap();
}
let mut entry: PROCESSENTRY32 = mem::zeroed();
entry.dwSize = mem::size_of::<PROCESSENTRY32>() as DWORD;
// Iterate over system processes looking for ours
let success = Process32First(snapshot, &mut entry);
if success == 0 {
CloseHandle(snapshot);
return serde_json::to_value(-1).unwrap();
}
let this_pid = GetCurrentProcessId();
while entry.th32ProcessID != this_pid {
let success = Process32Next(snapshot, &mut entry);
if success == 0 {
CloseHandle(snapshot);
return serde_json::to_value(-1).unwrap();
}
}
CloseHandle(snapshot);
// FIXME: Using the process ID exposes a race condition
// wherein the parent process already exited and the OS
// reassigned its ID.
let parent_id = entry.th32ParentProcessID;
serde_json::to_value(parent_id).unwrap()
}
}
#[cfg(not(windows))]
{
use std::os::unix::process::parent_id;
serde_json::to_value(parent_id()).unwrap()
}
}

View file

@ -111,6 +111,28 @@ unitTest(function osPid(): void {
assert(Deno.pid > 0);
});
unitTest(function osPpid(): void {
assert(Deno.ppid > 0);
});
unitTest(
{ perms: { run: true, read: true } },
async function osPpidIsEqualToPidOfParentProcess(): Promise<void> {
const decoder = new TextDecoder();
const process = Deno.run({
cmd: [Deno.execPath(), "eval", "-p", "--unstable", "Deno.ppid"],
stdout: "piped",
env: { NO_COLOR: "true" },
});
const output = await process.output();
process.close();
const expected = Deno.pid;
const actual = parseInt(decoder.decode(output));
assertEquals(actual, expected);
}
);
unitTest({ perms: { read: true } }, function execPath(): void {
assertNotEquals(Deno.execPath(), "");
});