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