Skip to content

Commit 5367d1a

Browse files
feat: pidfd_send_signal
1 parent e199d7f commit 5367d1a

File tree

5 files changed

+77
-1
lines changed

5 files changed

+77
-1
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
4545
([#1868](https://github.com/nix-rust/nix/pull/1868))
4646
- Added `pid_open` on Linux.
4747
([#1868](https://github.com/nix-rust/nix/pull/1868))
48+
- Added `pidfd_send_signal` on Linux.
49+
([#1868](https://github.com/nix-rust/nix/pull/1868))
4850

4951
## [0.27.1] - 2023-08-28
5052

src/sys/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,5 +230,5 @@ feature! {
230230
pub mod timer;
231231
}
232232

233-
#[cfg(all(target_os = "linux", feature = "process"))]
233+
#[cfg(all(target_os = "linux", feature = "signal", feature = "process"))]
234234
pub mod pidfd;

src/sys/pidfd.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! pidfd related functionality
22
33
use crate::errno::Errno;
4+
use crate::sys::signal::Signal;
45
use crate::unistd::Pid;
56
use crate::Result;
67
use std::convert::TryFrom;
@@ -70,3 +71,45 @@ pub fn pid_open(pid: Pid, nonblock: bool) -> Result<OwnedFd> {
7071
_ => unreachable!(),
7172
}
7273
}
74+
75+
/// Sends the signal `sig` to the target process referred to by `pid`, a PID file descriptor that
76+
/// refers to a process.
77+
///
78+
/// If the info argument is some [`libc::siginfo_t`] buffer, that buffer should be populated as
79+
/// described in [rt_sigqueueinfo(2)](https://man7.org/linux/man-pages/man2/rt_sigqueueinfo.2.html).
80+
///
81+
/// If the info argument is `None`, this is equivalent to specifying a pointer to a `siginfo_t`
82+
/// buffer whose fields match the values that are implicitly supplied when a signal is sent using
83+
/// [`crate::sys::signal::kill`]:
84+
///
85+
/// - `si_signo` is set to the signal number;
86+
/// - `si_errno` is set to 0;
87+
/// - `si_code` is set to SI_USER;
88+
/// - `si_pid` is set to the caller's PID; and
89+
/// - `si_uid` is set to the caller's real user ID.
90+
///
91+
/// The calling process must either be in the same PID namespace as the process referred to by
92+
/// pidfd, or be in an ancestor of that namespace.
93+
pub fn pidfd_send_signal<Fd: AsFd>(
94+
pid: Fd,
95+
sig: Signal,
96+
info: Option<libc::siginfo_t>,
97+
) -> Result<()> {
98+
let info = match info {
99+
Some(i) => &i,
100+
None => std::ptr::null(),
101+
};
102+
match unsafe {
103+
libc::syscall(
104+
libc::SYS_pidfd_send_signal,
105+
pid.as_fd().as_raw_fd(),
106+
sig as i32,
107+
info,
108+
0u32,
109+
)
110+
} {
111+
-1 => Err(Errno::last()),
112+
0 => Ok(()),
113+
_ => unreachable!(),
114+
}
115+
}

test/sys/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,6 @@ mod test_pthread;
5858
mod test_ptrace;
5959
#[cfg(any(target_os = "android", target_os = "linux"))]
6060
mod test_timerfd;
61+
62+
#[cfg(all(target_os = "linux", feature = "signal", feature = "process"))]
63+
pub mod test_pidfd;

test/sys/test_pidfd.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use nix::{
2+
sys::{
3+
pidfd::{pid_open, pidfd_send_signal},
4+
signal::Signal,
5+
signalfd::SigSet,
6+
wait::waitpid,
7+
},
8+
unistd::{fork, ForkResult},
9+
};
10+
11+
#[test]
12+
fn test_pidfd_send_signal() {
13+
match unsafe { fork().unwrap() } {
14+
ForkResult::Parent { child } => {
15+
// Send SIGUSR1
16+
let pid_fd = pid_open(child, false).unwrap();
17+
pidfd_send_signal(pid_fd, Signal::SIGUSR1, None).unwrap();
18+
// Wait for child to exit.
19+
waitpid(child, None).unwrap();
20+
}
21+
ForkResult::Child => {
22+
// Wait for SIGUSR1
23+
let mut mask = SigSet::empty();
24+
mask.add(Signal::SIGUSR1);
25+
assert_eq!(mask.wait().unwrap(), Signal::SIGUSR1);
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)