use std::io;
use super::AnchorCreation;
use crate::group_guard::child_exit;
#[derive(Debug)]
pub(in crate::group_guard) struct PreparedAnchor;
impl AnchorCreation for PreparedAnchor {
fn prepare() -> io::Result<Self> {
Ok(Self)
}
fn child_create(&self) -> Result<libc::pid_t, libc::c_int> {
let mut child_tid: libc::pid_t = 0;
let anchor = raw_fork(&mut child_tid);
if anchor == 0 {
child_lead_new_group();
}
if anchor < 0 {
return Err(crate::raw::last_errno());
}
let _ = unsafe { libc::setpgid(anchor, anchor) };
Ok(anchor)
}
}
fn child_lead_new_group() -> ! {
loop {
if unsafe { libc::setpgid(0, 0) } == 0 || crate::raw::last_errno() != libc::EINTR {
child_exit(0);
}
}
}
#[cfg(all(
any(target_os = "linux", target_os = "android"),
not(any(target_env = "musl", target_env = "ohos"))
))]
fn raw_fork(child_tid: &mut libc::pid_t) -> libc::pid_t {
let flags =
libc::c_long::from(libc::CLONE_CHILD_SETTID | libc::CLONE_CHILD_CLEARTID | libc::SIGCHLD);
let zero: libc::c_long = 0;
let no_parent_tid: *mut libc::pid_t = std::ptr::null_mut();
let child_tid: *mut libc::pid_t = child_tid;
#[cfg(any(target_arch = "x86_64", target_arch = "loongarch64"))]
let result = unsafe {
libc::syscall(
libc::SYS_clone,
flags,
zero,
no_parent_tid,
child_tid,
zero,
)
};
#[cfg(any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "mips",
target_arch = "mips32r6",
target_arch = "mips64",
target_arch = "mips64r6",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "riscv32",
target_arch = "riscv64",
target_arch = "x86",
))]
let result = unsafe {
libc::syscall(
libc::SYS_clone,
flags,
zero,
no_parent_tid,
zero,
child_tid,
)
};
#[cfg(target_arch = "s390x")]
let result = unsafe {
libc::syscall(
libc::SYS_clone,
zero,
flags,
no_parent_tid,
child_tid,
zero,
)
};
libc::pid_t::try_from(result).unwrap_or(-1)
}
#[cfg(all(
target_os = "linux",
any(target_env = "musl", target_env = "ohos"),
any(
target_arch = "arm",
target_arch = "mips",
target_arch = "mips64",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "s390x",
target_arch = "x86",
target_arch = "x86_64",
)
))]
fn raw_fork(_child_tid: &mut libc::pid_t) -> libc::pid_t {
let result = unsafe { libc::syscall(libc::SYS_fork) };
libc::pid_t::try_from(result).unwrap_or(-1)
}
#[cfg(all(
target_os = "linux",
any(target_env = "musl", target_env = "ohos"),
not(any(
target_arch = "arm",
target_arch = "mips",
target_arch = "mips64",
target_arch = "powerpc",
target_arch = "powerpc64",
target_arch = "s390x",
target_arch = "x86",
target_arch = "x86_64",
))
))]
fn raw_fork(_child_tid: &mut libc::pid_t) -> libc::pid_t {
let flags = libc::c_long::from(libc::SIGCHLD);
let no_stack: libc::c_long = 0;
let result = unsafe { libc::syscall(libc::SYS_clone, flags, no_stack) };
libc::pid_t::try_from(result).unwrap_or(-1)
}
#[cfg(target_os = "freebsd")]
fn raw_fork(_child_tid: &mut libc::pid_t) -> libc::pid_t {
unsafe { libc::rfork(libc::RFPROC | libc::RFFDG) }
}