From 3fa177deaa6dbd76525272ad7b746947106ec50d Mon Sep 17 00:00:00 2001 From: Kamal Marhubi Date: Tue, 12 Apr 2016 17:12:09 -0400 Subject: [PATCH] clone: Allow specifying termination signal DO NOT MERGE: proof of concept for comment Fixes #343 --- src/sched.rs | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/src/sched.rs b/src/sched.rs index 303084460c..c78f08dd6c 100644 --- a/src/sched.rs +++ b/src/sched.rs @@ -1,4 +1,4 @@ -use std::mem; +use std::{mem, ops}; use std::os::unix::io::RawFd; use libc::{self, c_int, c_void, c_ulong, pid_t}; use {Errno, Result}; @@ -35,6 +35,39 @@ bitflags!{ } } +#[derive(Clone, Copy, Debug)] +pub struct CloneFlagsArg { + flags: CloneFlags, + signal: Option, +} + +impl CloneFlagsArg { + fn bits(self) -> c_int { + self.flags.bits() | self.signal.unwrap_or(0) + } +} + +impl ops::BitOr for CloneFlags { + type Output = CloneFlagsArg; + fn bitor(self, rhs: c_int) -> CloneFlagsArg { + CloneFlagsArg { + flags: self, + signal: Some(rhs), + } + } +} + +impl From for CloneFlagsArg { + fn from(flags: CloneFlags) -> CloneFlagsArg { + CloneFlagsArg { + flags: flags, + signal: None, + } + } +} + + + // Support a maximum CPU set of 1024 nodes #[cfg(all(target_arch = "x86_64", target_os = "linux"))] mod cpuset_attribs { @@ -197,12 +230,32 @@ pub fn sched_setaffinity(pid: isize, cpuset: &CpuSet) -> Result<()> { Errno::result(res).map(drop) } -pub fn clone(mut cb: CloneCb, stack: &mut [u8], flags: CloneFlags) -> Result { +/// The clone(2) system call. +/// +/// # Examples +/// +/// ```no_run +/// use std::thread; +/// use std::time::Duration; +/// +/// use nix::sched::clone; +/// use nix::sched::CLONE_NEWUTS; +/// use nix::sys::signal::SIGCHLD; +/// +/// let mut stack = Box::new([0u8; 1024 * 1024]); +/// let pid = clone(Box::new(|| { +/// thread::sleep(Duration::from_secs(5)); +/// 0 +/// }), &mut stack[..], CLONE_NEWUTS | SIGCHLD).unwrap(); +/// ``` +pub fn clone>(mut cb: CloneCb, stack: &mut [u8], flags: F) -> Result { extern "C" fn callback(data: *mut CloneCb) -> c_int { let cb: &mut CloneCb = unsafe { &mut *data }; (*cb)() as c_int } + let flags: CloneFlagsArg = flags.into(); + let res = unsafe { let ptr = stack.as_mut_ptr().offset(stack.len() as isize); ffi::clone(mem::transmute(callback), ptr as *mut c_void, flags.bits(), &mut cb)