mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
refactor: setup child process pipe in Rust (#21579)
Avoid passing the fd into JS and back into Rust. Instead we setup the child's end of the pipe directly using a special Rust op.
This commit is contained in:
parent
62e3f5060e
commit
81a6504e67
7 changed files with 41 additions and 9 deletions
|
@ -30,6 +30,7 @@ mod path;
|
||||||
mod polyfill;
|
mod polyfill;
|
||||||
mod resolution;
|
mod resolution;
|
||||||
|
|
||||||
|
pub use ops::ipc::ChildPipeFd;
|
||||||
pub use ops::v8::VM_CONTEXT_INDEX;
|
pub use ops::v8::VM_CONTEXT_INDEX;
|
||||||
pub use package_json::PackageJson;
|
pub use package_json::PackageJson;
|
||||||
pub use path::PathClean;
|
pub use path::PathClean;
|
||||||
|
@ -313,6 +314,7 @@ deno_core::extension!(deno_node,
|
||||||
ops::util::op_node_guess_handle_type,
|
ops::util::op_node_guess_handle_type,
|
||||||
ops::crypto::op_node_create_private_key,
|
ops::crypto::op_node_create_private_key,
|
||||||
ops::ipc::op_node_ipc_pipe,
|
ops::ipc::op_node_ipc_pipe,
|
||||||
|
ops::ipc::op_node_child_ipc_pipe,
|
||||||
ops::ipc::op_node_ipc_write,
|
ops::ipc::op_node_ipc_write,
|
||||||
ops::ipc::op_node_ipc_read,
|
ops::ipc::op_node_ipc_read,
|
||||||
],
|
],
|
||||||
|
|
|
@ -6,6 +6,8 @@ pub use unix::*;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
pub use windows::*;
|
pub use windows::*;
|
||||||
|
|
||||||
|
pub struct ChildPipeFd(pub i32);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
mod unix {
|
mod unix {
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
@ -46,6 +48,22 @@ mod unix {
|
||||||
Ok(state.resource_table.add(IpcJsonStreamResource::new(fd)?))
|
Ok(state.resource_table.add(IpcJsonStreamResource::new(fd)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Open IPC pipe from bootstrap options.
|
||||||
|
#[op2]
|
||||||
|
#[smi]
|
||||||
|
pub fn op_node_child_ipc_pipe(
|
||||||
|
state: &mut OpState,
|
||||||
|
) -> Result<Option<ResourceId>, AnyError> {
|
||||||
|
let fd = match state.try_borrow_mut::<crate::ChildPipeFd>() {
|
||||||
|
Some(child_pipe_fd) => child_pipe_fd.0,
|
||||||
|
None => return Ok(None),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Some(
|
||||||
|
state.resource_table.add(IpcJsonStreamResource::new(fd)?),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
#[op2(async)]
|
#[op2(async)]
|
||||||
pub async fn op_node_ipc_write(
|
pub async fn op_node_ipc_write(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
|
@ -492,6 +510,12 @@ mod windows {
|
||||||
Err(deno_core::error::not_supported())
|
Err(deno_core::error::not_supported())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[op2(fast)]
|
||||||
|
#[smi]
|
||||||
|
pub fn op_node_child_ipc_pipe() -> Result<i32, AnyError> {
|
||||||
|
Ok(-1)
|
||||||
|
}
|
||||||
|
|
||||||
#[op2(async)]
|
#[op2(async)]
|
||||||
pub async fn op_node_ipc_write() -> Result<(), AnyError> {
|
pub async fn op_node_ipc_write() -> Result<(), AnyError> {
|
||||||
Err(deno_core::error::not_supported())
|
Err(deno_core::error::not_supported())
|
||||||
|
|
|
@ -12,7 +12,6 @@ let initialized = false;
|
||||||
function initialize(
|
function initialize(
|
||||||
usesLocalNodeModulesDir,
|
usesLocalNodeModulesDir,
|
||||||
argv0,
|
argv0,
|
||||||
ipcFd,
|
|
||||||
) {
|
) {
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
throw Error("Node runtime already initialized");
|
throw Error("Node runtime already initialized");
|
||||||
|
@ -38,7 +37,7 @@ function initialize(
|
||||||
// but it's the only way to get `args` and `version` and this point.
|
// but it's the only way to get `args` and `version` and this point.
|
||||||
internals.__bootstrapNodeProcess(argv0, Deno.args, Deno.version);
|
internals.__bootstrapNodeProcess(argv0, Deno.args, Deno.version);
|
||||||
internals.__initWorkerThreads();
|
internals.__initWorkerThreads();
|
||||||
internals.__setupChildProcessIpcChannel(ipcFd);
|
internals.__setupChildProcessIpcChannel();
|
||||||
// `Deno[Deno.internal].requireImpl` will be unreachable after this line.
|
// `Deno[Deno.internal].requireImpl` will be unreachable after this line.
|
||||||
delete internals.requireImpl;
|
delete internals.requireImpl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ import {
|
||||||
} from "ext:deno_node/internal/util.mjs";
|
} from "ext:deno_node/internal/util.mjs";
|
||||||
|
|
||||||
const { core } = globalThis.__bootstrap;
|
const { core } = globalThis.__bootstrap;
|
||||||
|
const ops = core.ops;
|
||||||
|
|
||||||
const MAX_BUFFER = 1024 * 1024;
|
const MAX_BUFFER = 1024 * 1024;
|
||||||
|
|
||||||
|
@ -822,7 +823,8 @@ export function execFileSync(
|
||||||
return ret.stdout as string | Buffer;
|
return ret.stdout as string | Buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupChildProcessIpcChannel(fd: number) {
|
function setupChildProcessIpcChannel() {
|
||||||
|
const fd = ops.op_node_child_ipc_pipe();
|
||||||
if (typeof fd != "number" || fd < 0) return;
|
if (typeof fd != "number" || fd < 0) return;
|
||||||
setupChannel(process, fd);
|
setupChannel(process, fd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -440,7 +440,6 @@ function bootstrapMainRuntime(runtimeOptions) {
|
||||||
3: inspectFlag,
|
3: inspectFlag,
|
||||||
5: hasNodeModulesDir,
|
5: hasNodeModulesDir,
|
||||||
6: maybeBinaryNpmCommandName,
|
6: maybeBinaryNpmCommandName,
|
||||||
7: nodeIpcFd,
|
|
||||||
} = runtimeOptions;
|
} = runtimeOptions;
|
||||||
|
|
||||||
performance.setTimeOrigin(DateNow());
|
performance.setTimeOrigin(DateNow());
|
||||||
|
@ -546,7 +545,7 @@ function bootstrapMainRuntime(runtimeOptions) {
|
||||||
ObjectDefineProperty(globalThis, "Deno", util.readOnly(finalDenoNs));
|
ObjectDefineProperty(globalThis, "Deno", util.readOnly(finalDenoNs));
|
||||||
|
|
||||||
if (nodeBootstrap) {
|
if (nodeBootstrap) {
|
||||||
nodeBootstrap(hasNodeModulesDir, maybeBinaryNpmCommandName, nodeIpcFd);
|
nodeBootstrap(hasNodeModulesDir, maybeBinaryNpmCommandName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -487,7 +487,16 @@ impl MainWorker {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bootstrap(&mut self, options: BootstrapOptions) {
|
pub fn bootstrap(&mut self, options: BootstrapOptions) {
|
||||||
self.js_runtime.op_state().borrow_mut().put(options.clone());
|
// Setup bootstrap options for ops.
|
||||||
|
{
|
||||||
|
let op_state = self.js_runtime.op_state();
|
||||||
|
let mut state = op_state.borrow_mut();
|
||||||
|
state.put(options.clone());
|
||||||
|
if let Some(node_ipc_fd) = options.node_ipc_fd {
|
||||||
|
state.put(deno_node::ChildPipeFd(node_ipc_fd));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let scope = &mut self.js_runtime.handle_scope();
|
let scope = &mut self.js_runtime.handle_scope();
|
||||||
let args = options.as_v8(scope);
|
let args = options.as_v8(scope);
|
||||||
let bootstrap_fn = self.bootstrap_fn_global.take().unwrap();
|
let bootstrap_fn = self.bootstrap_fn_global.take().unwrap();
|
||||||
|
|
|
@ -117,8 +117,6 @@ struct BootstrapV8<'a>(
|
||||||
bool,
|
bool,
|
||||||
// maybe_binary_npm_command_name
|
// maybe_binary_npm_command_name
|
||||||
Option<&'a str>,
|
Option<&'a str>,
|
||||||
// node_ipc_fd
|
|
||||||
i32,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
impl BootstrapOptions {
|
impl BootstrapOptions {
|
||||||
|
@ -138,7 +136,6 @@ impl BootstrapOptions {
|
||||||
self.enable_testing_features,
|
self.enable_testing_features,
|
||||||
self.has_node_modules_dir,
|
self.has_node_modules_dir,
|
||||||
self.maybe_binary_npm_command_name.as_deref(),
|
self.maybe_binary_npm_command_name.as_deref(),
|
||||||
self.node_ipc_fd.unwrap_or(-1),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
bootstrap.serialize(ser).unwrap()
|
bootstrap.serialize(ser).unwrap()
|
||||||
|
|
Loading…
Reference in a new issue