#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ProcessIdentifierFileDescriptor(RawFd);
impl Drop for ProcessIdentifierFileDescriptor
{
#[inline(always)]
fn drop(&mut self)
{
self.0.close()
}
}
impl AsRawFd for ProcessIdentifierFileDescriptor
{
#[inline(always)]
fn as_raw_fd(&self) -> RawFd
{
self.0
}
}
impl IntoRawFd for ProcessIdentifierFileDescriptor
{
#[inline(always)]
fn into_raw_fd(self) -> RawFd
{
self.0
}
}
impl FromRawFd for ProcessIdentifierFileDescriptor
{
#[inline(always)]
unsafe fn from_raw_fd(fd: RawFd) -> Self
{
Self(fd)
}
}
impl FileDescriptor for ProcessIdentifierFileDescriptor
{
}
impl ProcessIdentifierFileDescriptor
{
#[inline(always)]
pub fn open(process_identifier: ProcessIdentifierChoice) -> Result<Self, CreationError>
{
let pid: pid_t = process_identifier.into();
const flags: u32 = 0;
let result = pidfd_open.syscall2(pid as usize, flags as usize);
if likely!(result >= 0)
{
Ok(Self(result as RawFd))
}
else if likely!(result == -1)
{
use self::CreationError::*;
match errno().0
{
EMFILE => Err(PerProcessLimitOnNumberOfFileDescriptorsWouldBeExceeded),
ENFILE => Err(SystemWideLimitOnTotalNumberOfFileDescriptorsWouldBeExceeded),
ENOMEM => Err(KernelWouldBeOutOfMemory),
ESRCH => Err(ProcessForProcessIdentifierDoesNotExist),
ENODEV => panic!("The anonymous inode filesystem is not available in this kernel"),
EINVAL => panic!("flags is not 0 or pid is not valid"),
_ => unreachable_code(format_args!("")),
}
}
else
{
panic!("Unexpected result from pidfd_open of `{}`", result)
}
}
#[inline(always)]
pub fn send_signal(&self, signal: Signal, signal_information: Option<&siginfo_t>) -> Result<(), SendSignalError>
{
let signo: i32 = signal.into();
let information = match signal_information
{
Some(signal_information) => signal_information as *const siginfo_t,
None => null(),
};
const flags: u32 = 0;
let result = pidfd_send_signal.syscall4(self.0 as usize, signo as usize, information as usize, flags as usize);
if likely!(result == 0)
{
Ok(())
}
else if likely!(result == -1)
{
use self::SendSignalError::*;
match errno().0
{
EPERM => Err(PermissionDenied),
ESRCH => Err(ProcessHasFinished),
EINVAL => panic!("sig is not a valid signal, or, the calling process is not in a PID namespace from which it can send a signal to the target process, or, flags is not 0"),
unexpected @ _ => panic!("Unexpected error number {}", unexpected),
}
}
else
{
panic!("Unexpected result {}", result);
}
}
#[inline(always)]
pub fn duplicate_file_descriptor_from_other_process<FD: AsRawFd + FromRawFd>(&self, other_process_file_descriptor: &FD) -> Result<FD, CreationError>
{
const Flags: u32 = 0;
let result = pidfd_getfd.syscall3(self.as_raw_fd() as usize, other_process_file_descriptor.as_raw_fd() as usize, Flags as usize) as i32;
if likely!(result >= 0)
{
Ok(unsafe { FD::from_raw_fd(result) })
}
else if likely!(result == -1)
{
use self::CreationError::*;
match errno().0
{
EMFILE => Err(PerProcessLimitOnNumberOfFileDescriptorsWouldBeExceeded),
ENFILE => Err(SystemWideLimitOnTotalNumberOfFileDescriptorsWouldBeExceeded),
EPERM => Err(PermissionDenied),
ESRCH => Err(ProcessForProcessIdentifierDoesNotExist),
EBADF => panic!("pidfd is not a valid PID file descriptor, or targetfd is not an open file descriptor in the process referred to by pidfd"),
EINVAL => panic!("flags is not 0"),
unexpected @ _ => panic!("Unexpected error {} from pidfd_getfd()", unexpected)
}
}
else
{
unreachable_code(format_args!("Unexpected result {} from pidfd_getfd()", result))
}
}
}