diff --git a/Cargo.toml b/Cargo.toml index 530252a11f..e935f869d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,10 @@ license = "MIT" authors = ["Jeremy Soller "] repository = "https://gitlab.redox-os.org/redox-os/syscall" documentation = "https://docs.rs/redox_syscall" +edition = "2018" [lib] name = "syscall" + +[dependencies] +bitflags = "1.1.0" diff --git a/src/call.rs b/src/call.rs index 8b56541419..76e804fec3 100644 --- a/src/call.rs +++ b/src/call.rs @@ -1,6 +1,7 @@ use super::arch::*; use super::data::{Map, SigAction, Stat, StatVfs, TimeSpec}; use super::error::Result; +use super::flag::*; use super::number::*; use core::{mem, ptr}; @@ -52,8 +53,8 @@ pub fn chmod>(path: T, mode: usize) -> Result { } /// Produce a fork of the current process, or a new process thread -pub unsafe fn clone(flags: usize) -> Result { - syscall1_clobber(SYS_CLONE, flags) +pub unsafe fn clone(flags: CloneFlags) -> Result { + syscall1_clobber(SYS_CLONE, flags.bits()) } /// Close a file @@ -235,8 +236,8 @@ pub fn mkns(schemes: &[[usize; 2]]) -> Result { } /// Change mapping flags -pub unsafe fn mprotect(addr: usize, size: usize, flags: usize) -> Result { - syscall3(SYS_MPROTECT, addr, size, flags) +pub unsafe fn mprotect(addr: usize, size: usize, flags: MapFlags) -> Result { + syscall3(SYS_MPROTECT, addr, size, flags.bits()) } /// Sleep for the time specified in `req` @@ -274,8 +275,8 @@ pub unsafe fn physfree(physical_address: usize, size: usize) -> Result { /// # Errors /// /// * `EPERM` - `uid != 0` -pub unsafe fn physmap(physical_address: usize, size: usize, flags: usize) -> Result { - syscall3(SYS_PHYSMAP, physical_address, size, flags) +pub unsafe fn physmap(physical_address: usize, size: usize, flags: PhysmapFlags) -> Result { + syscall3(SYS_PHYSMAP, physical_address, size, flags.bits()) } /// Unmap previously mapped physical memory @@ -363,8 +364,8 @@ pub unsafe fn virttophys(virtual_address: usize) -> Result { } /// Check if a child process has exited or received a signal -pub fn waitpid(pid: usize, status: &mut usize, options: usize) -> Result { - unsafe { syscall3(SYS_WAITPID, pid, status as *mut usize as usize, options) } +pub fn waitpid(pid: usize, status: &mut usize, options: WaitFlags) -> Result { + unsafe { syscall3(SYS_WAITPID, pid, status as *mut usize as usize, options.bits()) } } /// Write a buffer to a file descriptor diff --git a/src/data.rs b/src/data.rs index 6ad8d8b683..06484dfd1f 100644 --- a/src/data.rs +++ b/src/data.rs @@ -1,11 +1,12 @@ use core::ops::{Deref, DerefMut}; -use core::{fmt, mem, slice}; +use core::{mem, slice}; +use crate::flag::{EventFlags, MapFlags, PtraceFlags, SigActionFlags}; #[derive(Copy, Clone, Debug, Default)] #[repr(C)] pub struct Event { pub id: usize, - pub flags: usize, + pub flags: EventFlags, pub data: usize } @@ -57,7 +58,7 @@ impl DerefMut for ITimerSpec { pub struct Map { pub offset: usize, pub size: usize, - pub flags: usize, + pub flags: MapFlags, } impl Deref for Map { @@ -112,7 +113,7 @@ impl DerefMut for Packet { pub struct SigAction { pub sa_handler: Option, pub sa_mask: [u64; 2], - pub sa_flags: usize, + pub sa_flags: SigActionFlags, } #[allow(dead_code)] @@ -303,32 +304,16 @@ impl DerefMut for FloatRegisters { } } -#[derive(Clone, Copy)] -#[repr(C)] -pub union PtraceEventData { - pub clone: usize, - pub signal: usize -} - -impl Default for PtraceEventData { - fn default() -> Self { - Self { - clone: 0, - } - } -} - -impl fmt::Debug for PtraceEventData { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "PtraceEventData(...)") - } -} - #[derive(Clone, Copy, Debug, Default)] #[repr(C)] pub struct PtraceEvent { - pub tag: u16, - pub data: PtraceEventData, + pub cause: PtraceFlags, + pub a: usize, + pub b: usize, + pub c: usize, + pub d: usize, + pub e: usize, + pub f: usize } impl Deref for PtraceEvent { @@ -347,3 +332,18 @@ impl DerefMut for PtraceEvent { } } } + +#[macro_export] +macro_rules! ptrace_event { + ($cause:expr $(, $a:expr $(, $b:expr $(, $c:expr)?)?)?) => { + PtraceEvent { + cause: $cause, + $(a: $a, + $(b: $b, + $(c: $c,)? + )? + )? + ..Default::default() + } + } +} diff --git a/src/flag.rs b/src/flag.rs index 9c928b4caf..57f2246c57 100644 --- a/src/flag.rs +++ b/src/flag.rs @@ -1,17 +1,59 @@ -pub const CLONE_VM: usize = 0x100; -pub const CLONE_FS: usize = 0x200; -pub const CLONE_FILES: usize = 0x400; -pub const CLONE_SIGHAND: usize = 0x800; -pub const CLONE_VFORK: usize = 0x4000; -pub const CLONE_THREAD: usize = 0x10000; -pub const CLONE_STACK: usize = 0x1000_0000; +use bitflags::bitflags as inner_bitflags; +use core::{mem, ops::Deref, slice}; + +macro_rules! bitflags { + ( + $(#[$outer:meta])* + pub struct $BitFlags:ident: $T:ty { + $( + $(#[$inner:ident $($args:tt)*])* + const $Flag:ident = $value:expr; + )+ + } + ) => { + // First, use the inner bitflags + inner_bitflags! { + #[derive(Default)] + $(#[$outer])* + pub struct $BitFlags: $T { + $( + $(#[$inner $($args)*])* + const $Flag = $value; + )+ + } + } + + // Secondly, re-export all inner constants + // (`pub use self::Struct::*` doesn't work) + $( + $(#[$inner $($args)*])* + pub const $Flag: $BitFlags = $BitFlags::$Flag; + )+ + } +} + +bitflags! { + pub struct CloneFlags: usize { + const CLONE_VM = 0x100; + const CLONE_FS = 0x200; + const CLONE_FILES = 0x400; + const CLONE_SIGHAND = 0x800; + const CLONE_VFORK = 0x4000; + const CLONE_THREAD = 0x10000; + const CLONE_STACK = 0x1000_0000; + } +} pub const CLOCK_REALTIME: usize = 1; pub const CLOCK_MONOTONIC: usize = 4; -pub const EVENT_NONE: usize = 0; -pub const EVENT_READ: usize = 1; -pub const EVENT_WRITE: usize = 2; +bitflags! { + pub struct EventFlags: usize { + const EVENT_NONE = 0; + const EVENT_READ = 1; + const EVENT_WRITE = 2; + } +} pub const F_DUPFD: usize = 0; pub const F_GETFD: usize = 1; @@ -23,8 +65,17 @@ pub const FUTEX_WAIT: usize = 0; pub const FUTEX_WAKE: usize = 1; pub const FUTEX_REQUEUE: usize = 2; -pub const MAP_SHARED: usize = 0x0001; -pub const MAP_PRIVATE: usize = 0x0002; +bitflags! { + pub struct MapFlags: usize { + const PROT_NONE = 0x0000_0000; + const PROT_EXEC = 0x0001_0000; + const PROT_WRITE = 0x0002_0000; + const PROT_READ = 0x0004_0000; + + const MAP_SHARED = 0x0001; + const MAP_PRIVATE = 0x0002; + } +} pub const MODE_TYPE: u16 = 0xF000; pub const MODE_DIR: u16 = 0x4000; @@ -56,26 +107,45 @@ pub const O_SYMLINK: usize = 0x4000_0000; pub const O_NOFOLLOW: usize = 0x8000_0000; pub const O_ACCMODE: usize = O_RDONLY | O_WRONLY | O_RDWR; -pub const PHYSMAP_WRITE: usize = 0x0000_0001; -pub const PHYSMAP_WRITE_COMBINE: usize = 0x0000_0002; -pub const PHYSMAP_NO_CACHE: usize = 0x0000_0004; +bitflags! { + pub struct PhysmapFlags: usize { + const PHYSMAP_WRITE = 0x0000_0001; + const PHYSMAP_WRITE_COMBINE = 0x0000_0002; + const PHYSMAP_NO_CACHE = 0x0000_0004; + } +} -pub const PROT_NONE: usize = 0x0000_0000; -pub const PROT_EXEC: usize = 0x0001_0000; -pub const PROT_WRITE: usize = 0x0002_0000; -pub const PROT_READ: usize = 0x0004_0000; +// The top 48 bits of PTRACE_* are reserved, for now -pub const PTRACE_CONT: u8 = 0b0000_0001; -pub const PTRACE_SINGLESTEP: u8 = 0b0000_0010; -pub const PTRACE_SYSCALL: u8 = 0b0000_0011; -pub const PTRACE_WAIT: u8 = 0b0000_0100; -pub const PTRACE_SIGNAL: u8 = 0b0000_0101; +bitflags! { + pub struct PtraceFlags: u64 { + const PTRACE_STOP_PRE_SYSCALL = 0x0000_0000_0000_0001; + const PTRACE_STOP_POST_SYSCALL = 0x0000_0000_0000_0002; + const PTRACE_STOP_SINGLESTEP = 0x0000_0000_0000_0004; + const PTRACE_STOP_SIGNAL = 0x0000_0000_0000_0008; + const PTRACE_STOP_BREAKPOINT = 0x0000_0000_0000_0010; + const PTRACE_STOP_MASK = 0x0000_0000_0000_00FF; -pub const PTRACE_OPERATIONMASK: u8 = 0b0000_1111; -pub const PTRACE_SYSEMU: u8 = 0b0001_0000; + const PTRACE_EVENT_CLONE = 0x0000_0000_0000_0100; + const PTRACE_EVENT_MASK = 0x0000_0000_0000_0F00; -pub const PTRACE_EVENT_CLONE: u16 = 0; -pub const PTRACE_EVENT_SIGNAL: u16 = 1; + const PTRACE_FLAG_IGNORE = 0x0000_0000_0000_1000; + const PTRACE_FLAG_WAIT = 0x0000_0000_0000_2000; + const PTRACE_FLAG_MASK = 0x0000_0000_0000_F000; + } +} +impl Deref for PtraceFlags { + type Target = [u8]; + fn deref(&self) -> &Self::Target { + // Same as to_ne_bytes but in-place + unsafe { + slice::from_raw_parts( + &self.bits as *const _ as *const u8, + mem::size_of::() + ) + } + } +} pub const SEEK_SET: usize = 0; pub const SEEK_CUR: usize = 1; @@ -120,18 +190,26 @@ pub const SIG_BLOCK: usize = 0; pub const SIG_UNBLOCK: usize = 1; pub const SIG_SETMASK: usize = 2; -pub const SA_NOCLDSTOP: usize = 0x00000001; -pub const SA_NOCLDWAIT: usize = 0x00000002; -pub const SA_SIGINFO: usize = 0x00000004; -pub const SA_RESTORER: usize = 0x04000000; -pub const SA_ONSTACK: usize = 0x08000000; -pub const SA_RESTART: usize = 0x10000000; -pub const SA_NODEFER: usize = 0x40000000; -pub const SA_RESETHAND: usize = 0x80000000; +bitflags! { + pub struct SigActionFlags: usize { + const SA_NOCLDSTOP = 0x00000001; + const SA_NOCLDWAIT = 0x00000002; + const SA_SIGINFO = 0x00000004; + const SA_RESTORER = 0x04000000; + const SA_ONSTACK = 0x08000000; + const SA_RESTART = 0x10000000; + const SA_NODEFER = 0x40000000; + const SA_RESETHAND = 0x80000000; + } +} -pub const WNOHANG: usize = 0x01; -pub const WUNTRACED: usize = 0x02; -pub const WCONTINUED: usize = 0x08; +bitflags! { + pub struct WaitFlags: usize { + const WNOHANG = 0x01; + const WUNTRACED = 0x02; + const WCONTINUED = 0x08; + } +} /// True if status indicates the child is stopped. pub fn wifstopped(status: usize) -> bool { diff --git a/src/io/dma.rs b/src/io/dma.rs index d5334b843f..f2a9a12104 100644 --- a/src/io/dma.rs +++ b/src/io/dma.rs @@ -1,7 +1,7 @@ use core::{mem, ptr}; use core::ops::{Deref, DerefMut}; -use Result; +use crate::Result; struct PhysBox { address: usize, @@ -10,7 +10,7 @@ struct PhysBox { impl PhysBox { fn new(size: usize) -> Result { - let address = unsafe { ::physalloc(size)? }; + let address = unsafe { crate::physalloc(size)? }; Ok(PhysBox { address: address, size: size @@ -20,7 +20,7 @@ impl PhysBox { impl Drop for PhysBox { fn drop(&mut self) { - let _ = unsafe { ::physfree(self.address, self.size) }; + let _ = unsafe { crate::physfree(self.address, self.size) }; } } @@ -32,7 +32,7 @@ pub struct Dma { impl Dma { pub fn new(value: T) -> Result> { let phys = PhysBox::new(mem::size_of::())?; - let virt = unsafe { ::physmap(phys.address, phys.size, ::PHYSMAP_WRITE)? } as *mut T; + let virt = unsafe { crate::physmap(phys.address, phys.size, crate::PHYSMAP_WRITE)? } as *mut T; unsafe { ptr::write(virt, value); } Ok(Dma { phys: phys, @@ -42,7 +42,7 @@ impl Dma { pub fn zeroed() -> Result> { let phys = PhysBox::new(mem::size_of::())?; - let virt = unsafe { ::physmap(phys.address, phys.size, ::PHYSMAP_WRITE)? } as *mut T; + let virt = unsafe { crate::physmap(phys.address, phys.size, crate::PHYSMAP_WRITE)? } as *mut T; unsafe { ptr::write_bytes(virt as *mut u8, 0, phys.size); } Ok(Dma { phys: phys, @@ -71,6 +71,6 @@ impl DerefMut for Dma { impl Drop for Dma { fn drop(&mut self) { unsafe { drop(ptr::read(self.virt)); } - let _ = unsafe { ::physunmap(self.virt as usize) }; + let _ = unsafe { crate::physunmap(self.virt as usize) }; } } diff --git a/src/io/mmio.rs b/src/io/mmio.rs index b8e7727d3c..f2126362cf 100644 --- a/src/io/mmio.rs +++ b/src/io/mmio.rs @@ -1,19 +1,19 @@ use core::ptr::{read_volatile, write_volatile}; -use core::mem::uninitialized; +use core::mem::MaybeUninit; use core::ops::{BitAnd, BitOr, Not}; use super::io::Io; #[repr(packed)] pub struct Mmio { - value: T, + value: MaybeUninit, } impl Mmio { /// Create a new Mmio without initializing pub fn new() -> Self { Mmio { - value: unsafe { uninitialized() } + value: MaybeUninit::uninit() } } } @@ -22,10 +22,10 @@ impl Io for Mmio where T: Copy + PartialEq + BitAnd + BitOr T { - unsafe { read_volatile(&self.value) } + unsafe { read_volatile(self.value.as_ptr()) } } fn write(&mut self, value: T) { - unsafe { write_volatile(&mut self.value, value) }; + unsafe { write_volatile(self.value.as_mut_ptr(), value) }; } } diff --git a/src/lib.rs b/src/lib.rs index 6b8d130f01..92b30f5927 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #![feature(asm)] #![feature(const_fn)] +#![feature(maybe_uninit)] // remove when Redox updates their rust version #![cfg_attr(not(test), no_std)] #[cfg(test)] diff --git a/src/scheme/generate.sh b/src/scheme/generate.sh index e5d11ae300..f95bf8ac3c 100755 --- a/src/scheme/generate.sh +++ b/src/scheme/generate.sh @@ -11,7 +11,8 @@ echo "Generating SchemeBlock from Scheme" sed 's/trait Scheme/trait SchemeBlock/' scheme.rs \ | sed 's/fn handle(\&self, packet: \&mut Packet)/fn handle(\&self, packet: \&Packet) -> Option/' \ | sed 's/packet.a = Error::mux(res);/res.transpose().map(Error::mux)/' \ -| sed 's/Result/Result>/g' \ +| sed 's/\.map(|f| f\.bits())/\.map(|f| f.map(|f| f.bits()))/' \ +| sed 's/Result<\([^>]\+\)>/Result>/g' \ > scheme_block.rs echo "Generating SchemeBlockMut from SchemeBlock" diff --git a/src/scheme/scheme.rs b/src/scheme/scheme.rs index c047e96833..0c95a7415d 100644 --- a/src/scheme/scheme.rs +++ b/src/scheme/scheme.rs @@ -1,8 +1,9 @@ use core::{mem, slice}; -use data::*; -use error::*; -use number::*; +use crate::data::*; +use crate::error::*; +use crate::flag::*; +use crate::number::*; pub trait Scheme { fn handle(&self, packet: &mut Packet) { @@ -19,7 +20,7 @@ pub trait Scheme { SYS_FCHMOD => self.fchmod(packet.b, packet.c as u16), SYS_FCHOWN => self.fchown(packet.b, packet.c as u32, packet.d as u32), SYS_FCNTL => self.fcntl(packet.b, packet.c, packet.d), - SYS_FEVENT => self.fevent(packet.b, packet.c), + SYS_FEVENT => self.fevent(packet.b, EventFlags::from_bits_truncate(packet.c)).map(|f| f.bits()), SYS_FMAP => if packet.d >= mem::size_of::() { self.fmap(packet.b, unsafe { &*(packet.c as *const Map) }) } else { @@ -111,7 +112,7 @@ pub trait Scheme { } #[allow(unused_variables)] - fn fevent(&self, id: usize, flags: usize) -> Result { + fn fevent(&self, id: usize, flags: EventFlags) -> Result { Err(Error::new(EBADF)) } diff --git a/src/scheme/scheme_block.rs b/src/scheme/scheme_block.rs index 0407dde61d..4428eaa3fd 100644 --- a/src/scheme/scheme_block.rs +++ b/src/scheme/scheme_block.rs @@ -1,8 +1,9 @@ use core::{mem, slice}; -use data::*; -use error::*; -use number::*; +use crate::data::*; +use crate::error::*; +use crate::flag::*; +use crate::number::*; pub trait SchemeBlock { fn handle(&self, packet: &Packet) -> Option { @@ -19,7 +20,7 @@ pub trait SchemeBlock { SYS_FCHMOD => self.fchmod(packet.b, packet.c as u16), SYS_FCHOWN => self.fchown(packet.b, packet.c as u32, packet.d as u32), SYS_FCNTL => self.fcntl(packet.b, packet.c, packet.d), - SYS_FEVENT => self.fevent(packet.b, packet.c), + SYS_FEVENT => self.fevent(packet.b, EventFlags::from_bits_truncate(packet.c)).map(|f| f.map(|f| f.bits())), SYS_FMAP => if packet.d >= mem::size_of::() { self.fmap(packet.b, unsafe { &*(packet.c as *const Map) }) } else { @@ -111,7 +112,7 @@ pub trait SchemeBlock { } #[allow(unused_variables)] - fn fevent(&self, id: usize, flags: usize) -> Result> { + fn fevent(&self, id: usize, flags: EventFlags) -> Result> { Err(Error::new(EBADF)) } diff --git a/src/scheme/scheme_block_mut.rs b/src/scheme/scheme_block_mut.rs index 411035f42f..c4a49b3489 100644 --- a/src/scheme/scheme_block_mut.rs +++ b/src/scheme/scheme_block_mut.rs @@ -1,8 +1,9 @@ use core::{mem, slice}; -use data::*; -use error::*; -use number::*; +use crate::data::*; +use crate::error::*; +use crate::flag::*; +use crate::number::*; pub trait SchemeBlockMut { fn handle(&mut self, packet: &Packet) -> Option { @@ -19,7 +20,7 @@ pub trait SchemeBlockMut { SYS_FCHMOD => self.fchmod(packet.b, packet.c as u16), SYS_FCHOWN => self.fchown(packet.b, packet.c as u32, packet.d as u32), SYS_FCNTL => self.fcntl(packet.b, packet.c, packet.d), - SYS_FEVENT => self.fevent(packet.b, packet.c), + SYS_FEVENT => self.fevent(packet.b, EventFlags::from_bits_truncate(packet.c)).map(|f| f.map(|f| f.bits())), SYS_FMAP => if packet.d >= mem::size_of::() { self.fmap(packet.b, unsafe { &*(packet.c as *const Map) }) } else { @@ -111,7 +112,7 @@ pub trait SchemeBlockMut { } #[allow(unused_variables)] - fn fevent(&mut self, id: usize, flags: usize) -> Result> { + fn fevent(&mut self, id: usize, flags: EventFlags) -> Result> { Err(Error::new(EBADF)) } diff --git a/src/scheme/scheme_mut.rs b/src/scheme/scheme_mut.rs index abd2e88e5c..eea133103c 100644 --- a/src/scheme/scheme_mut.rs +++ b/src/scheme/scheme_mut.rs @@ -1,8 +1,9 @@ use core::{mem, slice}; -use data::*; -use error::*; -use number::*; +use crate::data::*; +use crate::error::*; +use crate::flag::*; +use crate::number::*; pub trait SchemeMut { fn handle(&mut self, packet: &mut Packet) { @@ -19,7 +20,7 @@ pub trait SchemeMut { SYS_FCHMOD => self.fchmod(packet.b, packet.c as u16), SYS_FCHOWN => self.fchown(packet.b, packet.c as u32, packet.d as u32), SYS_FCNTL => self.fcntl(packet.b, packet.c, packet.d), - SYS_FEVENT => self.fevent(packet.b, packet.c), + SYS_FEVENT => self.fevent(packet.b, EventFlags::from_bits_truncate(packet.c)).map(|f| f.bits()), SYS_FMAP => if packet.d >= mem::size_of::() { self.fmap(packet.b, unsafe { &*(packet.c as *const Map) }) } else { @@ -111,7 +112,7 @@ pub trait SchemeMut { } #[allow(unused_variables)] - fn fevent(&mut self, id: usize, flags: usize) -> Result { + fn fevent(&mut self, id: usize, flags: EventFlags) -> Result { Err(Error::new(EBADF)) } diff --git a/src/tests.rs b/src/tests.rs index 7dd2bad0c9..7f87a2b0ae 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -36,14 +36,14 @@ fn chdir() { #[test] fn clone() { let expected_status = 42; - let pid_res = unsafe { crate::clone(0) }; + let pid_res = unsafe { crate::clone(crate::CloneFlags::empty()) }; if pid_res == Ok(0) { crate::exit(expected_status).unwrap(); panic!("failed to exit"); } else { let pid = dbg!(pid_res).unwrap(); let mut status = 0; - assert_eq!(dbg!(crate::waitpid(pid, &mut status, 0)), Ok(pid)); + assert_eq!(dbg!(crate::waitpid(pid, &mut status, crate::WaitFlags::empty())), Ok(pid)); assert_eq!(dbg!(crate::wifexited(status)), true); assert_eq!(dbg!(crate::wexitstatus(status)), expected_status); } @@ -90,7 +90,7 @@ fn fexec() { let vars = &[]; - let pid_res = unsafe { crate::clone(0) }; + let pid_res = unsafe { crate::clone(crate::CloneFlags::empty()) }; if pid_res == Ok(0) { crate::fexec(fd, args, vars).unwrap(); panic!("failed to fexec"); @@ -99,7 +99,7 @@ fn fexec() { let pid = dbg!(pid_res).unwrap(); let mut status = 0; - assert_eq!(dbg!(crate::waitpid(pid, &mut status, 0)), Ok(pid)); + assert_eq!(dbg!(crate::waitpid(pid, &mut status, crate::WaitFlags::empty())), Ok(pid)); assert_eq!(dbg!(crate::wifexited(status)), true); assert_eq!(dbg!(crate::wexitstatus(status)), 0); } @@ -465,7 +465,7 @@ fn sigaction() { crate::kill(pid, crate::SIGUSR1).unwrap(); // actually exits } else { let mut status = 0; - dbg!(crate::waitpid(child, &mut status, 0)).unwrap(); + dbg!(crate::waitpid(child, &mut status, crate::WaitFlags::empty())).unwrap(); assert!(crate::wifsignaled(status)); assert_eq!(crate::wtermsig(status), crate::SIGUSR1);