|
3 | 3 | use std::{ |
4 | 4 | hint::unreachable_unchecked, |
5 | 5 | os::fd::{FromRawFd as _, OwnedFd, RawFd}, |
| 6 | + ptr, |
6 | 7 | }; |
7 | 8 |
|
8 | 9 | use bitflags::bitflags; |
@@ -58,3 +59,79 @@ pub fn pidfd_open(pid: Pid, flags: PidfdFlags) -> Result<OwnedFd, Errno> { |
58 | 59 | } |
59 | 60 | } |
60 | 61 | } |
| 62 | + |
| 63 | +feature! { |
| 64 | +#![feature = "signal"] |
| 65 | + |
| 66 | +use std::os::fd::{AsFd, AsRawFd}; |
| 67 | + |
| 68 | +use libc::siginfo_t; |
| 69 | + |
| 70 | +use crate::sys::signal::Signal; |
| 71 | + |
| 72 | +bitflags! { |
| 73 | + /// Flags for [`pidfd_send_signal`]. |
| 74 | + #[derive(Copy, Clone)] |
| 75 | + pub struct PidfdSignalFlags: libc::c_uint { |
| 76 | + /// See [`pidfd_send_signal(2)`] for details. |
| 77 | + /// |
| 78 | + /// [`pidfd_send_signal(2)`]: https://man7.org/linux/man-pages/man2/pidfd_send_signal.2.html |
| 79 | + const PIDFD_SIGNAL_THREAD = libc::PIDFD_SIGNAL_THREAD; |
| 80 | + |
| 81 | + /// See [`pidfd_send_signal(2)`] for details. |
| 82 | + /// |
| 83 | + /// [`pidfd_send_signal(2)`]: https://man7.org/linux/man-pages/man2/pidfd_send_signal.2.html |
| 84 | + const PIDFD_SIGNAL_THREAD_GROUP = libc::PIDFD_SIGNAL_THREAD_GROUP; |
| 85 | + |
| 86 | + /// See [`pidfd_send_signal(2)`] for details. |
| 87 | + /// |
| 88 | + /// [`pidfd_send_signal(2)`]: https://man7.org/linux/man-pages/man2/pidfd_send_signal.2.html |
| 89 | + const PIDFD_SIGNAL_PROCESS_GROUP = libc::PIDFD_SIGNAL_PROCESS_GROUP; |
| 90 | + } |
| 91 | +} |
| 92 | + |
| 93 | +/// Send a signal to a process by its PIDFD. |
| 94 | +/// |
| 95 | +/// See [`pidfd_send_signal(2)`] for details. |
| 96 | +/// |
| 97 | +/// [`pidfd_send_signal(2)`]: https://man7.org/linux/man-pages/man2/pidfd_send_signal.2.html |
| 98 | +/// |
| 99 | +/// # Safety |
| 100 | +/// |
| 101 | +/// This function is [async-signal-safe], although it may modify `errno`. |
| 102 | +/// |
| 103 | +/// [async-signal-safe]: https://man7.org/linux/man-pages/man7/signal-safety.7.html |
| 104 | +pub fn pidfd_send_signal<T>( |
| 105 | + pidfd: T, |
| 106 | + signal: Signal, |
| 107 | + signal_info: Option<siginfo_t>, |
| 108 | + flags: PidfdSignalFlags, |
| 109 | +) -> Result<(), Errno> |
| 110 | +where |
| 111 | + T: AsFd, |
| 112 | +{ |
| 113 | + let signal_info = match signal_info { |
| 114 | + Some(x) => &x, |
| 115 | + None => ptr::null(), |
| 116 | + }; |
| 117 | + |
| 118 | + // SAFETY: |
| 119 | + // |
| 120 | + // * Arguments passed to the syscall have the correct types. |
| 121 | + // * The kernel should not return any value other than `0` and `-1`. |
| 122 | + unsafe { |
| 123 | + match libc::syscall( |
| 124 | + libc::SYS_pidfd_send_signal, |
| 125 | + pidfd.as_fd().as_raw_fd(), |
| 126 | + signal as libc::c_int, |
| 127 | + signal_info, |
| 128 | + flags.bits(), |
| 129 | + ) { |
| 130 | + 0 => Ok(()), |
| 131 | + -1 => Err(Errno::last()), |
| 132 | + _ => unreachable_unchecked(), |
| 133 | + } |
| 134 | + } |
| 135 | +} |
| 136 | + |
| 137 | +} |
0 commit comments