1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2017 The ChromiumOS Authors 2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file. 4*bb4ee6a4SAndroid Build Coastguard Worker 5*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File; 6*bb4ee6a4SAndroid Build Coastguard Worker use std::mem; 7*bb4ee6a4SAndroid Build Coastguard Worker use std::os::raw::c_int; 8*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::io::AsRawFd; 9*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::io::FromRawFd; 10*bb4ee6a4SAndroid Build Coastguard Worker use std::os::unix::io::RawFd; 11*bb4ee6a4SAndroid Build Coastguard Worker use std::result; 12*bb4ee6a4SAndroid Build Coastguard Worker 13*bb4ee6a4SAndroid Build Coastguard Worker use libc::c_void; 14*bb4ee6a4SAndroid Build Coastguard Worker use libc::read; 15*bb4ee6a4SAndroid Build Coastguard Worker use libc::signalfd; 16*bb4ee6a4SAndroid Build Coastguard Worker use libc::signalfd_siginfo; 17*bb4ee6a4SAndroid Build Coastguard Worker use libc::EAGAIN; 18*bb4ee6a4SAndroid Build Coastguard Worker use libc::SFD_CLOEXEC; 19*bb4ee6a4SAndroid Build Coastguard Worker use libc::SFD_NONBLOCK; 20*bb4ee6a4SAndroid Build Coastguard Worker use log::error; 21*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted; 22*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error; 23*bb4ee6a4SAndroid Build Coastguard Worker 24*bb4ee6a4SAndroid Build Coastguard Worker use super::signal; 25*bb4ee6a4SAndroid Build Coastguard Worker use super::Error as ErrnoError; 26*bb4ee6a4SAndroid Build Coastguard Worker use super::RawDescriptor; 27*bb4ee6a4SAndroid Build Coastguard Worker use crate::descriptor::AsRawDescriptor; 28*bb4ee6a4SAndroid Build Coastguard Worker 29*bb4ee6a4SAndroid Build Coastguard Worker #[sorted] 30*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Error, Debug)] 31*bb4ee6a4SAndroid Build Coastguard Worker pub enum Error { 32*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to block the signal when creating signalfd. 33*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to block the signal when creating signalfd: {0}")] 34*bb4ee6a4SAndroid Build Coastguard Worker CreateBlockSignal(signal::Error), 35*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to create a new signalfd. 36*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to create a new signalfd: {0}")] 37*bb4ee6a4SAndroid Build Coastguard Worker CreateSignalFd(ErrnoError), 38*bb4ee6a4SAndroid Build Coastguard Worker /// Failed to construct sigset when creating signalfd. 39*bb4ee6a4SAndroid Build Coastguard Worker #[error("failed to construct sigset when creating signalfd: {0}")] 40*bb4ee6a4SAndroid Build Coastguard Worker CreateSigset(ErrnoError), 41*bb4ee6a4SAndroid Build Coastguard Worker /// Signalfd could be read, but didn't return a full siginfo struct. 42*bb4ee6a4SAndroid Build Coastguard Worker /// This wraps the number of bytes that were actually read. 43*bb4ee6a4SAndroid Build Coastguard Worker #[error("signalfd failed to return a full siginfo struct, read only {0} bytes")] 44*bb4ee6a4SAndroid Build Coastguard Worker SignalFdPartialRead(usize), 45*bb4ee6a4SAndroid Build Coastguard Worker /// Unable to read from signalfd. 46*bb4ee6a4SAndroid Build Coastguard Worker #[error("unable to read from signalfd: {0}")] 47*bb4ee6a4SAndroid Build Coastguard Worker SignalFdRead(ErrnoError), 48*bb4ee6a4SAndroid Build Coastguard Worker } 49*bb4ee6a4SAndroid Build Coastguard Worker 50*bb4ee6a4SAndroid Build Coastguard Worker pub type Result<T> = result::Result<T, Error>; 51*bb4ee6a4SAndroid Build Coastguard Worker 52*bb4ee6a4SAndroid Build Coastguard Worker /// A safe wrapper around a Linux signalfd (man 2 signalfd). 53*bb4ee6a4SAndroid Build Coastguard Worker /// 54*bb4ee6a4SAndroid Build Coastguard Worker /// A signalfd can be used for non-synchronous signals (such as SIGCHLD) so that 55*bb4ee6a4SAndroid Build Coastguard Worker /// signals can be processed without the use of a signal handler. 56*bb4ee6a4SAndroid Build Coastguard Worker pub struct SignalFd { 57*bb4ee6a4SAndroid Build Coastguard Worker signalfd: File, 58*bb4ee6a4SAndroid Build Coastguard Worker signal: c_int, 59*bb4ee6a4SAndroid Build Coastguard Worker } 60*bb4ee6a4SAndroid Build Coastguard Worker 61*bb4ee6a4SAndroid Build Coastguard Worker impl SignalFd { 62*bb4ee6a4SAndroid Build Coastguard Worker /// Creates a new SignalFd for the given signal, blocking the normal handler 63*bb4ee6a4SAndroid Build Coastguard Worker /// for the signal as well. Since we mask out the normal handler, this is 64*bb4ee6a4SAndroid Build Coastguard Worker /// a risky operation - signal masking will persist across fork and even 65*bb4ee6a4SAndroid Build Coastguard Worker /// **exec** so the user of SignalFd should think long and hard about 66*bb4ee6a4SAndroid Build Coastguard Worker /// when to mask signals. new(signal: c_int) -> Result<SignalFd>67*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(signal: c_int) -> Result<SignalFd> { 68*bb4ee6a4SAndroid Build Coastguard Worker let sigset = signal::create_sigset(&[signal]).map_err(Error::CreateSigset)?; 69*bb4ee6a4SAndroid Build Coastguard Worker 70*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 71*bb4ee6a4SAndroid Build Coastguard Worker // This is safe as we check the return value and know that fd is valid. 72*bb4ee6a4SAndroid Build Coastguard Worker let fd = unsafe { signalfd(-1, &sigset, SFD_CLOEXEC | SFD_NONBLOCK) }; 73*bb4ee6a4SAndroid Build Coastguard Worker if fd < 0 { 74*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::CreateSignalFd(ErrnoError::last())); 75*bb4ee6a4SAndroid Build Coastguard Worker } 76*bb4ee6a4SAndroid Build Coastguard Worker 77*bb4ee6a4SAndroid Build Coastguard Worker // Mask out the normal handler for the signal. 78*bb4ee6a4SAndroid Build Coastguard Worker signal::block_signal(signal).map_err(Error::CreateBlockSignal)?; 79*bb4ee6a4SAndroid Build Coastguard Worker 80*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 81*bb4ee6a4SAndroid Build Coastguard Worker // This is safe because we checked fd for success and know the 82*bb4ee6a4SAndroid Build Coastguard Worker // kernel gave us an fd that we own. 83*bb4ee6a4SAndroid Build Coastguard Worker unsafe { 84*bb4ee6a4SAndroid Build Coastguard Worker Ok(SignalFd { 85*bb4ee6a4SAndroid Build Coastguard Worker signalfd: File::from_raw_fd(fd), 86*bb4ee6a4SAndroid Build Coastguard Worker signal, 87*bb4ee6a4SAndroid Build Coastguard Worker }) 88*bb4ee6a4SAndroid Build Coastguard Worker } 89*bb4ee6a4SAndroid Build Coastguard Worker } 90*bb4ee6a4SAndroid Build Coastguard Worker 91*bb4ee6a4SAndroid Build Coastguard Worker /// Read a siginfo struct from the signalfd, if available. read(&self) -> Result<Option<signalfd_siginfo>>92*bb4ee6a4SAndroid Build Coastguard Worker pub fn read(&self) -> Result<Option<signalfd_siginfo>> { 93*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 94*bb4ee6a4SAndroid Build Coastguard Worker // signalfd_siginfo doesn't have a default, so just zero it. 95*bb4ee6a4SAndroid Build Coastguard Worker let mut siginfo: signalfd_siginfo = unsafe { mem::zeroed() }; 96*bb4ee6a4SAndroid Build Coastguard Worker let siginfo_size = mem::size_of::<signalfd_siginfo>(); 97*bb4ee6a4SAndroid Build Coastguard Worker 98*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 99*bb4ee6a4SAndroid Build Coastguard Worker // This read is safe since we've got the space allocated for a 100*bb4ee6a4SAndroid Build Coastguard Worker // single signalfd_siginfo, and that's exactly how much we're 101*bb4ee6a4SAndroid Build Coastguard Worker // reading. Handling of EINTR is not required since SFD_NONBLOCK 102*bb4ee6a4SAndroid Build Coastguard Worker // was specified. signalfds will always read in increments of 103*bb4ee6a4SAndroid Build Coastguard Worker // sizeof(signalfd_siginfo); see man 2 signalfd. 104*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { 105*bb4ee6a4SAndroid Build Coastguard Worker read( 106*bb4ee6a4SAndroid Build Coastguard Worker self.signalfd.as_raw_fd(), 107*bb4ee6a4SAndroid Build Coastguard Worker &mut siginfo as *mut signalfd_siginfo as *mut c_void, 108*bb4ee6a4SAndroid Build Coastguard Worker siginfo_size, 109*bb4ee6a4SAndroid Build Coastguard Worker ) 110*bb4ee6a4SAndroid Build Coastguard Worker }; 111*bb4ee6a4SAndroid Build Coastguard Worker 112*bb4ee6a4SAndroid Build Coastguard Worker if ret < 0 { 113*bb4ee6a4SAndroid Build Coastguard Worker let err = ErrnoError::last(); 114*bb4ee6a4SAndroid Build Coastguard Worker if err.errno() == EAGAIN { 115*bb4ee6a4SAndroid Build Coastguard Worker Ok(None) 116*bb4ee6a4SAndroid Build Coastguard Worker } else { 117*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::SignalFdRead(err)) 118*bb4ee6a4SAndroid Build Coastguard Worker } 119*bb4ee6a4SAndroid Build Coastguard Worker } else if ret == (siginfo_size as isize) { 120*bb4ee6a4SAndroid Build Coastguard Worker Ok(Some(siginfo)) 121*bb4ee6a4SAndroid Build Coastguard Worker } else { 122*bb4ee6a4SAndroid Build Coastguard Worker Err(Error::SignalFdPartialRead(ret as usize)) 123*bb4ee6a4SAndroid Build Coastguard Worker } 124*bb4ee6a4SAndroid Build Coastguard Worker } 125*bb4ee6a4SAndroid Build Coastguard Worker } 126*bb4ee6a4SAndroid Build Coastguard Worker 127*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawFd for SignalFd { as_raw_fd(&self) -> RawFd128*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_fd(&self) -> RawFd { 129*bb4ee6a4SAndroid Build Coastguard Worker self.signalfd.as_raw_fd() 130*bb4ee6a4SAndroid Build Coastguard Worker } 131*bb4ee6a4SAndroid Build Coastguard Worker } 132*bb4ee6a4SAndroid Build Coastguard Worker 133*bb4ee6a4SAndroid Build Coastguard Worker impl AsRawDescriptor for SignalFd { as_raw_descriptor(&self) -> RawDescriptor134*bb4ee6a4SAndroid Build Coastguard Worker fn as_raw_descriptor(&self) -> RawDescriptor { 135*bb4ee6a4SAndroid Build Coastguard Worker self.signalfd.as_raw_descriptor() 136*bb4ee6a4SAndroid Build Coastguard Worker } 137*bb4ee6a4SAndroid Build Coastguard Worker } 138*bb4ee6a4SAndroid Build Coastguard Worker 139*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for SignalFd { drop(&mut self)140*bb4ee6a4SAndroid Build Coastguard Worker fn drop(&mut self) { 141*bb4ee6a4SAndroid Build Coastguard Worker // This is thread-safe and safe in the sense that we're doing what 142*bb4ee6a4SAndroid Build Coastguard Worker // was promised - unmasking the signal when we go out of scope. 143*bb4ee6a4SAndroid Build Coastguard Worker let res = signal::unblock_signal(self.signal); 144*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = res { 145*bb4ee6a4SAndroid Build Coastguard Worker error!("signalfd failed to unblock signal {}: {}", self.signal, e); 146*bb4ee6a4SAndroid Build Coastguard Worker } 147*bb4ee6a4SAndroid Build Coastguard Worker } 148*bb4ee6a4SAndroid Build Coastguard Worker } 149*bb4ee6a4SAndroid Build Coastguard Worker 150*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)] 151*bb4ee6a4SAndroid Build Coastguard Worker mod tests { 152*bb4ee6a4SAndroid Build Coastguard Worker use std::mem; 153*bb4ee6a4SAndroid Build Coastguard Worker use std::ptr::null; 154*bb4ee6a4SAndroid Build Coastguard Worker 155*bb4ee6a4SAndroid Build Coastguard Worker use libc::pthread_sigmask; 156*bb4ee6a4SAndroid Build Coastguard Worker use libc::raise; 157*bb4ee6a4SAndroid Build Coastguard Worker use libc::sigismember; 158*bb4ee6a4SAndroid Build Coastguard Worker use libc::sigset_t; 159*bb4ee6a4SAndroid Build Coastguard Worker 160*bb4ee6a4SAndroid Build Coastguard Worker use super::super::signal::SIGRTMIN; 161*bb4ee6a4SAndroid Build Coastguard Worker use super::*; 162*bb4ee6a4SAndroid Build Coastguard Worker 163*bb4ee6a4SAndroid Build Coastguard Worker #[test] new()164*bb4ee6a4SAndroid Build Coastguard Worker fn new() { 165*bb4ee6a4SAndroid Build Coastguard Worker SignalFd::new(SIGRTMIN()).unwrap(); 166*bb4ee6a4SAndroid Build Coastguard Worker } 167*bb4ee6a4SAndroid Build Coastguard Worker 168*bb4ee6a4SAndroid Build Coastguard Worker #[test] read()169*bb4ee6a4SAndroid Build Coastguard Worker fn read() { 170*bb4ee6a4SAndroid Build Coastguard Worker let sigid = SIGRTMIN() + 1; 171*bb4ee6a4SAndroid Build Coastguard Worker let sigrt_fd = SignalFd::new(sigid).unwrap(); 172*bb4ee6a4SAndroid Build Coastguard Worker 173*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: Safe because sigid is valid and return value is checked. 174*bb4ee6a4SAndroid Build Coastguard Worker let ret = unsafe { raise(sigid) }; 175*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(ret, 0); 176*bb4ee6a4SAndroid Build Coastguard Worker 177*bb4ee6a4SAndroid Build Coastguard Worker let siginfo = sigrt_fd.read().unwrap().unwrap(); 178*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(siginfo.ssi_signo, sigid as u32); 179*bb4ee6a4SAndroid Build Coastguard Worker } 180*bb4ee6a4SAndroid Build Coastguard Worker 181*bb4ee6a4SAndroid Build Coastguard Worker #[test] drop()182*bb4ee6a4SAndroid Build Coastguard Worker fn drop() { 183*bb4ee6a4SAndroid Build Coastguard Worker let sigid = SIGRTMIN() + 2; 184*bb4ee6a4SAndroid Build Coastguard Worker 185*bb4ee6a4SAndroid Build Coastguard Worker let sigrt_fd = SignalFd::new(sigid).unwrap(); 186*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: Safe because sigset and sigid are valid and return value is checked. 187*bb4ee6a4SAndroid Build Coastguard Worker unsafe { 188*bb4ee6a4SAndroid Build Coastguard Worker let mut sigset: sigset_t = mem::zeroed(); 189*bb4ee6a4SAndroid Build Coastguard Worker pthread_sigmask(0, null(), &mut sigset as *mut sigset_t); 190*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(sigismember(&sigset, sigid), 1); 191*bb4ee6a4SAndroid Build Coastguard Worker } 192*bb4ee6a4SAndroid Build Coastguard Worker 193*bb4ee6a4SAndroid Build Coastguard Worker mem::drop(sigrt_fd); 194*bb4ee6a4SAndroid Build Coastguard Worker 195*bb4ee6a4SAndroid Build Coastguard Worker // The signal should no longer be masked. 196*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: Safe because sigset and sigid are valid and return value is checked. 197*bb4ee6a4SAndroid Build Coastguard Worker unsafe { 198*bb4ee6a4SAndroid Build Coastguard Worker let mut sigset: sigset_t = mem::zeroed(); 199*bb4ee6a4SAndroid Build Coastguard Worker pthread_sigmask(0, null(), &mut sigset as *mut sigset_t); 200*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(sigismember(&sigset, sigid), 0); 201*bb4ee6a4SAndroid Build Coastguard Worker } 202*bb4ee6a4SAndroid Build Coastguard Worker } 203*bb4ee6a4SAndroid Build Coastguard Worker } 204