diff options
Diffstat (limited to 'src/sys')
-rw-r--r-- | src/sys/epoll.rs | 64 | ||||
-rw-r--r-- | src/sys/event.rs | 16 | ||||
-rw-r--r-- | src/sys/eventfd.rs | 6 | ||||
-rw-r--r-- | src/sys/memfd.rs | 6 | ||||
-rw-r--r-- | src/sys/signalfd.rs | 38 | ||||
-rw-r--r-- | src/sys/wait.rs | 15 |
6 files changed, 83 insertions, 62 deletions
diff --git a/src/sys/epoll.rs b/src/sys/epoll.rs index 02c25d4d..36f9c17d 100644 --- a/src/sys/epoll.rs +++ b/src/sys/epoll.rs @@ -2,7 +2,7 @@ use crate::errno::Errno; use crate::Result; use libc::{self, c_int}; use std::mem; -use std::os::unix::io::{FromRawFd,RawFd, OwnedFd, AsFd, AsRawFd}; +use std::os::unix::io::{AsFd, AsRawFd, FromRawFd, OwnedFd, RawFd}; libc_bitflags!( pub struct EpollFlags: c_int { @@ -78,22 +78,22 @@ impl EpollEvent { /// # fn main() -> nix::Result<()> { /// const DATA: u64 = 17; /// const MILLIS: u64 = 100; -/// +/// /// // Create epoll /// let epoll = Epoll::new(EpollCreateFlags::empty())?; -/// +/// /// // Create eventfd & Add event -/// let eventfd = unsafe { OwnedFd::from_raw_fd(eventfd(0, EfdFlags::empty())?) }; +/// let eventfd = eventfd(0, EfdFlags::empty())?; /// epoll.add(&eventfd, EpollEvent::new(EpollFlags::EPOLLIN,DATA))?; -/// +/// /// // Arm eventfd & Time wait /// write(eventfd.as_raw_fd(), &1u64.to_ne_bytes())?; /// let now = Instant::now(); -/// +/// /// // Wait on event /// let mut events = [EpollEvent::empty()]; /// epoll.wait(&mut events, MILLIS as isize)?; -/// +/// /// // Assert data correct & timeout didn't occur /// assert_eq!(events[0].data(), DATA); /// assert!(now.elapsed() < Duration::from_millis(MILLIS)); @@ -104,7 +104,7 @@ impl EpollEvent { pub struct Epoll(pub OwnedFd); impl Epoll { /// Creates a new epoll instance and returns a file descriptor referring to that instance. - /// + /// /// [`epoll_create1`](https://man7.org/linux/man-pages/man2/epoll_create1.2.html). pub fn new(flags: EpollCreateFlags) -> Result<Self> { let res = unsafe { libc::epoll_create1(flags.bits()) }; @@ -113,30 +113,38 @@ impl Epoll { Ok(Self(owned_fd)) } /// Add an entry to the interest list of the epoll file descriptor for - /// specified in events. - /// + /// specified in events. + /// /// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_ADD`. pub fn add<Fd: AsFd>(&self, fd: Fd, mut event: EpollEvent) -> Result<()> { - self.epoll_ctl(EpollOp::EpollCtlAdd,fd,&mut event) + self.epoll_ctl(EpollOp::EpollCtlAdd, fd, &mut event) } /// Remove (deregister) the target file descriptor `fd` from the interest list. - /// + /// /// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_DEL` . pub fn delete<Fd: AsFd>(&self, fd: Fd) -> Result<()> { - self.epoll_ctl(EpollOp::EpollCtlDel,fd,None) + self.epoll_ctl(EpollOp::EpollCtlDel, fd, None) } /// Change the settings associated with `fd` in the interest list to the new settings specified /// in `event`. - /// + /// /// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) with `EPOLL_CTL_MOD`. - pub fn modify<Fd: AsFd>(&self,fd: Fd, event: &mut EpollEvent) -> Result<()> { - self.epoll_ctl(EpollOp::EpollCtlMod,fd,event) + pub fn modify<Fd: AsFd>( + &self, + fd: Fd, + event: &mut EpollEvent, + ) -> Result<()> { + self.epoll_ctl(EpollOp::EpollCtlMod, fd, event) } /// Waits for I/O events, blocking the calling thread if no events are currently available. /// (This can be thought of as fetching items from the ready list of the epoll instance.) - /// + /// /// [`epoll_wait`](https://man7.org/linux/man-pages/man2/epoll_wait.2.html) - pub fn wait(&self, events: &mut [EpollEvent], timeout: isize) -> Result<usize> { + pub fn wait( + &self, + events: &mut [EpollEvent], + timeout: isize, + ) -> Result<usize> { let res = unsafe { libc::epoll_wait( self.0.as_raw_fd(), @@ -145,15 +153,15 @@ impl Epoll { timeout as c_int, ) }; - + Errno::result(res).map(|r| r as usize) } /// This system call is used to add, modify, or remove entries in the interest list of the epoll /// instance referred to by `self`. It requests that the operation `op` be performed for the /// target file descriptor, `fd`. - /// + /// /// When possible prefer [`Epoll::add`], [`Epoll::delete`] and [`Epoll::modify`]. - /// + /// /// [`epoll_ctl`](https://man7.org/linux/man-pages/man2/epoll_ctl.2.html) fn epoll_ctl<'a, Fd: AsFd, T>( &self, @@ -165,9 +173,17 @@ impl Epoll { T: Into<Option<&'a mut EpollEvent>>, { let event: Option<&mut EpollEvent> = event.into(); - let ptr = event.map(|x|&mut x.event as *mut libc::epoll_event).unwrap_or(std::ptr::null_mut()); + let ptr = event + .map(|x| &mut x.event as *mut libc::epoll_event) + .unwrap_or(std::ptr::null_mut()); unsafe { - Errno::result(libc::epoll_ctl(self.0.as_raw_fd(), op as c_int, fd.as_fd().as_raw_fd(), ptr)).map(drop) + Errno::result(libc::epoll_ctl( + self.0.as_raw_fd(), + op as c_int, + fd.as_fd().as_raw_fd(), + ptr, + )) + .map(drop) } } } @@ -231,4 +247,4 @@ pub fn epoll_wait( }; Errno::result(res).map(|r| r as usize) -}
\ No newline at end of file +} diff --git a/src/sys/event.rs b/src/sys/event.rs index d8ad628e..f21ba173 100644 --- a/src/sys/event.rs +++ b/src/sys/event.rs @@ -8,7 +8,7 @@ use libc::{c_int, c_long, intptr_t, time_t, timespec, uintptr_t}; use libc::{c_long, intptr_t, size_t, time_t, timespec, uintptr_t}; use std::convert::TryInto; use std::mem; -use std::os::unix::io::RawFd; +use std::os::unix::io::{AsFd, AsRawFd, FromRawFd, OwnedFd}; use std::ptr; // Redefine kevent in terms of programmer-friendly enums and bitfields. @@ -207,10 +207,10 @@ libc_bitflags!( } ); -pub fn kqueue() -> Result<RawFd> { +pub fn kqueue() -> Result<OwnedFd> { let res = unsafe { libc::kqueue() }; - Errno::result(res) + Errno::result(res).map(|fd| unsafe { OwnedFd::from_raw_fd(fd) }) } // KEvent can't derive Send because on some operating systems, udata is defined @@ -267,8 +267,8 @@ impl KEvent { } } -pub fn kevent( - kq: RawFd, +pub fn kevent<Fd: AsFd>( + kq: Fd, changelist: &[KEvent], eventlist: &mut [KEvent], timeout_ms: usize, @@ -293,15 +293,15 @@ type type_of_nchanges = c_int; #[cfg(target_os = "netbsd")] type type_of_nchanges = size_t; -pub fn kevent_ts( - kq: RawFd, +pub fn kevent_ts<Fd: AsFd>( + kq: Fd, changelist: &[KEvent], eventlist: &mut [KEvent], timeout_opt: Option<timespec>, ) -> Result<usize> { let res = unsafe { libc::kevent( - kq, + kq.as_fd().as_raw_fd(), changelist.as_ptr() as *const libc::kevent, changelist.len() as type_of_nchanges, eventlist.as_mut_ptr() as *mut libc::kevent, diff --git a/src/sys/eventfd.rs b/src/sys/eventfd.rs index cd906720..f1723519 100644 --- a/src/sys/eventfd.rs +++ b/src/sys/eventfd.rs @@ -1,6 +1,6 @@ use crate::errno::Errno; use crate::Result; -use std::os::unix::io::RawFd; +use std::os::unix::io::{FromRawFd, OwnedFd}; libc_bitflags! { pub struct EfdFlags: libc::c_int { @@ -10,8 +10,8 @@ libc_bitflags! { } } -pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<RawFd> { +pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<OwnedFd> { let res = unsafe { libc::eventfd(initval, flags.bits()) }; - Errno::result(res).map(|r| r as RawFd) + Errno::result(res).map(|r| unsafe { OwnedFd::from_raw_fd(r) }) } diff --git a/src/sys/memfd.rs b/src/sys/memfd.rs index ad9345e8..f349a743 100644 --- a/src/sys/memfd.rs +++ b/src/sys/memfd.rs @@ -1,7 +1,7 @@ //! Interfaces for managing memory-backed files. use cfg_if::cfg_if; -use std::os::unix::io::RawFd; +use std::os::unix::io::{FromRawFd, OwnedFd, RawFd}; use crate::errno::Errno; use crate::Result; @@ -40,7 +40,7 @@ libc_bitflags!( /// For more information, see [`memfd_create(2)`]. /// /// [`memfd_create(2)`]: https://man7.org/linux/man-pages/man2/memfd_create.2.html -pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<RawFd> { +pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<OwnedFd> { let res = unsafe { cfg_if! { if #[cfg(all( @@ -60,5 +60,5 @@ pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<RawFd> { } }; - Errno::result(res).map(|r| r as RawFd) + Errno::result(res).map(|r| unsafe { OwnedFd::from_raw_fd(r as RawFd) }) } diff --git a/src/sys/signalfd.rs b/src/sys/signalfd.rs index 095e5908..2b80ea64 100644 --- a/src/sys/signalfd.rs +++ b/src/sys/signalfd.rs @@ -17,12 +17,11 @@ //! signal handlers. use crate::errno::Errno; pub use crate::sys::signal::{self, SigSet}; -use crate::unistd; use crate::Result; pub use libc::signalfd_siginfo as siginfo; use std::mem; -use std::os::unix::io::{AsRawFd, RawFd}; +use std::os::unix::io::{AsRawFd, RawFd, FromRawFd, OwnedFd, AsFd, BorrowedFd}; libc_bitflags! { pub struct SfdFlags: libc::c_int { @@ -31,7 +30,6 @@ libc_bitflags! { } } -pub const SIGNALFD_NEW: RawFd = -1; #[deprecated(since = "0.23.0", note = "use mem::size_of::<siginfo>() instead")] pub const SIGNALFD_SIGINFO_SIZE: usize = mem::size_of::<siginfo>(); @@ -46,13 +44,19 @@ pub const SIGNALFD_SIGINFO_SIZE: usize = mem::size_of::<siginfo>(); /// signalfd (the default handler will be invoked instead). /// /// See [the signalfd man page for more information](https://man7.org/linux/man-pages/man2/signalfd.2.html) -pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result<RawFd> { +#[deprecated(since = "0.27.0", note = "Use SignalFd instead")] +pub fn signalfd<F: AsFd>(fd: Option<F>, mask: &SigSet, flags: SfdFlags) -> Result<OwnedFd> { + _signalfd(fd, mask, flags) +} + +fn _signalfd<F: AsFd>(fd: Option<F>, mask: &SigSet, flags: SfdFlags) -> Result<OwnedFd> { + let raw_fd = fd.map_or(-1, |x|x.as_fd().as_raw_fd()); unsafe { Errno::result(libc::signalfd( - fd as libc::c_int, + raw_fd, mask.as_ref(), flags.bits(), - )) + )).map(|raw_fd|FromRawFd::from_raw_fd(raw_fd)) } } @@ -82,8 +86,8 @@ pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result<RawFd> { /// Err(err) => (), // some error happend /// } /// ``` -#[derive(Debug, Eq, Hash, PartialEq)] -pub struct SignalFd(RawFd); +#[derive(Debug)] +pub struct SignalFd(OwnedFd); impl SignalFd { pub fn new(mask: &SigSet) -> Result<SignalFd> { @@ -91,13 +95,13 @@ impl SignalFd { } pub fn with_flags(mask: &SigSet, flags: SfdFlags) -> Result<SignalFd> { - let fd = signalfd(SIGNALFD_NEW, mask, flags)?; + let fd = _signalfd(None::<OwnedFd>, mask, flags)?; Ok(SignalFd(fd)) } pub fn set_mask(&mut self, mask: &SigSet) -> Result<()> { - signalfd(self.0, mask, SfdFlags::empty()).map(drop) + _signalfd(Some(self.0.as_fd()), mask, SfdFlags::empty()).map(drop) } pub fn read_signal(&mut self) -> Result<Option<siginfo>> { @@ -105,7 +109,7 @@ impl SignalFd { let size = mem::size_of_val(&buffer); let res = Errno::result(unsafe { - libc::read(self.0, buffer.as_mut_ptr() as *mut libc::c_void, size) + libc::read(self.0.as_raw_fd(), buffer.as_mut_ptr() as *mut libc::c_void, size) }) .map(|r| r as usize); match res { @@ -117,18 +121,14 @@ impl SignalFd { } } -impl Drop for SignalFd { - fn drop(&mut self) { - let e = unistd::close(self.0); - if !std::thread::panicking() && e == Err(Errno::EBADF) { - panic!("Closing an invalid file descriptor!"); - }; +impl AsFd for SignalFd { + fn as_fd(&self) -> BorrowedFd { + self.0.as_fd() } } - impl AsRawFd for SignalFd { fn as_raw_fd(&self) -> RawFd { - self.0 + self.0.as_raw_fd() } } diff --git a/src/sys/wait.rs b/src/sys/wait.rs index b6524e86..f7a63ffc 100644 --- a/src/sys/wait.rs +++ b/src/sys/wait.rs @@ -10,7 +10,7 @@ use std::convert::TryFrom; target_os = "android", all(target_os = "linux", not(target_env = "uclibc")), ))] -use std::os::unix::io::RawFd; +use std::os::unix::io::{AsRawFd, BorrowedFd}; libc_bitflags!( /// Controls the behavior of [`waitpid`]. @@ -343,8 +343,8 @@ pub fn wait() -> Result<WaitStatus> { target_os = "haiku", all(target_os = "linux", not(target_env = "uclibc")), ))] -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum Id { +#[derive(Debug)] +pub enum Id<'fd> { /// Wait for any child All, /// Wait for the child whose process ID matches the given PID @@ -355,7 +355,11 @@ pub enum Id { PGid(Pid), /// Wait for the child referred to by the given PID file descriptor #[cfg(any(target_os = "android", target_os = "linux"))] - PIDFd(RawFd), + PIDFd(BorrowedFd<'fd>), + /// A helper variant to resolve the unused parameter (`'fd`) problem on platforms + /// other than Linux and Android. + #[doc(hidden)] + _Unreachable(std::marker::PhantomData<&'fd std::convert::Infallible>), } /// Wait for a process to change status @@ -373,7 +377,8 @@ pub fn waitid(id: Id, flags: WaitPidFlag) -> Result<WaitStatus> { Id::Pid(pid) => (libc::P_PID, pid.as_raw() as libc::id_t), Id::PGid(pid) => (libc::P_PGID, pid.as_raw() as libc::id_t), #[cfg(any(target_os = "android", target_os = "linux"))] - Id::PIDFd(fd) => (libc::P_PIDFD, fd as libc::id_t), + Id::PIDFd(fd) => (libc::P_PIDFD, fd.as_raw_fd() as libc::id_t), + Id::_Unreachable(_) => unreachable!("This variant could never be constructed"), }; let siginfo = unsafe { |