summaryrefslogtreecommitdiffstats
path: root/crates/runner/src/util/clone.rs
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2021-10-25 00:19:45 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2021-10-25 00:19:45 +0200
commit34ac18d20c13a78914d447fee83204811a27b1e4 (patch)
tree56763d4ea46927105fcc6a71e03d5bd75a6947a6 /crates/runner/src/util/clone.rs
parenta1a185370da27f2cc3df84d3a8d7141f9ce7db16 (diff)
downloadrebel-34ac18d20c13a78914d447fee83204811a27b1e4.tar
rebel-34ac18d20c13a78914d447fee83204811a27b1e4.zip
Move runner into separate crate
Diffstat (limited to 'crates/runner/src/util/clone.rs')
-rw-r--r--crates/runner/src/util/clone.rs58
1 files changed, 58 insertions, 0 deletions
diff --git a/crates/runner/src/util/clone.rs b/crates/runner/src/util/clone.rs
new file mode 100644
index 0000000..4835b53
--- /dev/null
+++ b/crates/runner/src/util/clone.rs
@@ -0,0 +1,58 @@
+use std::{mem, process};
+
+use nix::{errno, sched, unistd};
+
+#[repr(C)]
+#[derive(Debug, Default)]
+struct CloneArgs {
+ flags: u64,
+ pidfd: u64,
+ child_tid: u64,
+ parent_tid: u64,
+ exit_signal: u64,
+ stack: u64,
+ stack_size: u64,
+ tls: u64,
+}
+
+pub unsafe fn clone(flags: sched::CloneFlags) -> nix::Result<unistd::ForkResult> {
+ let mut args = CloneArgs {
+ flags: flags.bits() as u64,
+ exit_signal: libc::SIGCHLD as u64,
+ ..CloneArgs::default()
+ };
+ let size = mem::size_of_val(&args) as libc::size_t;
+
+ let pid = libc::syscall(libc::SYS_clone3, &mut args, size);
+ if pid < 0 {
+ Err(errno::Errno::last())
+ } else if pid == 0 {
+ Ok(unistd::ForkResult::Child)
+ } else {
+ Ok(unistd::ForkResult::Parent {
+ child: unistd::Pid::from_raw(pid as libc::pid_t),
+ })
+ }
+}
+
+pub unsafe fn spawn<T, F>(
+ flags: Option<sched::CloneFlags>,
+ arg: T,
+ f: F,
+) -> nix::Result<(unistd::Pid, T)>
+where
+ F: FnOnce(T),
+{
+ let res = if let Some(flags) = flags {
+ clone(flags)
+ } else {
+ unistd::fork()
+ };
+ match res? {
+ unistd::ForkResult::Parent { child } => Ok((child, arg)),
+ unistd::ForkResult::Child => {
+ f(arg);
+ process::exit(0)
+ }
+ }
+}