use { crate::forker::ForkerError, uapi::{OwnedFd, c}, }; #[derive(Default, Copy, Clone)] #[expect(non_camel_case_types, dead_code)] struct clone_args { flags: u64, pidfd: u64, child_tid: u64, parent_tid: u64, exit_signal: u64, stack: u64, stack_size: u64, tls: u64, set_tid: u64, set_tid_size: u64, cgroup: u64, } pub enum Forked { Parent { pid: c::pid_t, pidfd: OwnedFd }, Child { _pidfd: Option }, } pub fn fork_with_pidfd(pidfd_for_child: bool) -> Result { let mut pidfd: c::c_int = 0; let mut args = clone_args { flags: c::CLONE_PIDFD as u64, pidfd: (&mut pidfd as *mut c::c_int) as _, exit_signal: c::SIGCHLD as _, ..Default::default() }; let mut child_pidfd = None; if pidfd_for_child { child_pidfd = Some(uapi::pidfd_open(uapi::getpid(), 0).unwrap()); } unsafe { let pid = c::syscall( c::SYS_clone3, &mut args as *const _ as usize, size_of::(), ); if let Err(e) = uapi::map_err!(pid) { return Err(ForkerError::Fork(e.into())); } let res = if pid == 0 { Forked::Child { _pidfd: child_pidfd, } } else { Forked::Parent { pid: pid as _, pidfd: OwnedFd::new(pidfd), } }; Ok(res) } }