-
Notifications
You must be signed in to change notification settings - Fork 645
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pidfd_getfd
, pid_open
and pidfd_send_signal
#1868
Open
JonathanWoollett-Light
wants to merge
3
commits into
nix-rust:master
Choose a base branch
from
JonathanWoollett-Light:pidfd
base: master
Could not load branches
Branch not found: {{ refName }}
Could not load tags
Nothing to show
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
- Added `pidfd_getfd` on Linux. | ||
- Added `pid_open` on Linux. | ||
- Added `pidfd_send_signal` on Linux. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
//! pidfd related functionality | ||
|
||
use crate::errno::Errno; | ||
use crate::sys::signal::Signal; | ||
use crate::unistd::Pid; | ||
use crate::Result; | ||
use std::convert::TryFrom; | ||
use std::os::unix::io::{AsFd, AsRawFd, FromRawFd, OwnedFd}; | ||
|
||
/// Allocates a new file descriptor in the calling process. This new file descriptor is a duplicate | ||
/// of an existing file descriptor, `target`, in the process referred to by the PID file descriptor | ||
/// `pid`. | ||
/// | ||
/// The duplicate file descriptor refers to the same open file description (see | ||
/// [open(2)](https://man7.org/linux/man-pages/man2/open.2.html)) as the original file descriptor in | ||
/// the process referred to by `pid`. The two file descriptors thus share file status flags and | ||
/// file offset. Furthermore, operations on the underlying file object (for example, assigning an | ||
/// address to a socket object using [bind(2)](https://man7.org/linux/man-pages/man2/bind.2.html)) | ||
/// can equally be performed via the duplicate file descriptor. | ||
/// | ||
/// The close-on-exec flag ([`libc::FD_CLOEXEC`]; see | ||
/// [fcntl(2)](https://man7.org/linux/man-pages/man2/fcntl.2.html)) is set on the returned file | ||
/// descriptor. | ||
/// | ||
/// Permission to duplicate another process's file descriptor is governed by a ptrace access mode | ||
/// PTRACE_MODE_ATTACH_REALCREDS check (see | ||
/// [ptrace(2)](https://man7.org/linux/man-pages/man2/ptrace.2.html)). | ||
pub fn pidfd_getfd<PFd: AsFd, TFd: AsFd>( | ||
pid: PFd, | ||
target: TFd, | ||
) -> Result<OwnedFd> { | ||
#[allow(clippy::useless_conversion)] // Not useless on all OSes | ||
match unsafe { | ||
libc::syscall( | ||
libc::SYS_pidfd_getfd, | ||
pid.as_fd().as_raw_fd(), | ||
target.as_fd().as_raw_fd(), | ||
0, | ||
) | ||
} { | ||
-1 => Err(Errno::last()), | ||
fd @ 0.. => { | ||
Ok(unsafe { OwnedFd::from_raw_fd(i32::try_from(fd).unwrap()) }) | ||
} | ||
_ => unreachable!(), | ||
} | ||
} | ||
|
||
/// Creates a file descriptor that refers to the process whose PID is specified in `pid`. The file | ||
/// descriptor is returned as the function result; the close-on-exec flag is set on the file | ||
/// descriptor. | ||
/// | ||
/// If `nonblock == true` returns a nonblocking file descriptor. If the process | ||
/// referred to by the file descriptor has not yet terminated, | ||
/// then an attempt to wait on the file descriptor using | ||
/// waitid(2) will immediately return the error EAGAIN rather | ||
/// than blocking. | ||
pub fn pid_open(pid: Pid, nonblock: bool) -> Result<OwnedFd> { | ||
#[allow(clippy::useless_conversion)] // Not useless on all OSes | ||
match unsafe { | ||
libc::syscall( | ||
libc::SYS_pidfd_open, | ||
pid, | ||
if nonblock { libc::PIDFD_NONBLOCK } else { 0 }, | ||
) | ||
} { | ||
-1 => Err(Errno::last()), | ||
fd @ 0.. => { | ||
Ok(unsafe { OwnedFd::from_raw_fd(i32::try_from(fd).unwrap()) }) | ||
} | ||
_ => unreachable!(), | ||
} | ||
} | ||
|
||
/// Sends the signal `sig` to the target process referred to by `pid`, a PID file descriptor that | ||
/// refers to a process. | ||
/// | ||
/// If the info argument is some [`libc::siginfo_t`] buffer, that buffer should be populated as | ||
/// described in [rt_sigqueueinfo(2)](https://man7.org/linux/man-pages/man2/rt_sigqueueinfo.2.html). | ||
/// | ||
/// If the info argument is `None`, this is equivalent to specifying a pointer to a `siginfo_t` | ||
/// buffer whose fields match the values that are implicitly supplied when a signal is sent using | ||
/// [`crate::sys::signal::kill`]: | ||
/// | ||
/// - `si_signo` is set to the signal number; | ||
/// - `si_errno` is set to 0; | ||
/// - `si_code` is set to SI_USER; | ||
/// - `si_pid` is set to the caller's PID; and | ||
/// - `si_uid` is set to the caller's real user ID. | ||
/// | ||
/// The calling process must either be in the same PID namespace as the process referred to by | ||
/// pidfd, or be in an ancestor of that namespace. | ||
pub fn pidfd_send_signal<Fd: AsFd>( | ||
pid: Fd, | ||
sig: Signal, | ||
info: Option<libc::siginfo_t>, | ||
) -> Result<()> { | ||
let info = match info { | ||
Some(i) => &i, | ||
None => std::ptr::null(), | ||
}; | ||
match unsafe { | ||
libc::syscall( | ||
libc::SYS_pidfd_send_signal, | ||
pid.as_fd().as_raw_fd(), | ||
sig as i32, | ||
info, | ||
0u32, | ||
) | ||
} { | ||
-1 => Err(Errno::last()), | ||
0 => Ok(()), | ||
_ => unreachable!(), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
use nix::{ | ||
sys::{ | ||
pidfd::{pid_open, pidfd_send_signal}, | ||
signal::Signal, | ||
signalfd::SigSet, | ||
wait::waitpid, | ||
}, | ||
unistd::{fork, ForkResult}, | ||
}; | ||
|
||
#[test] | ||
fn test_pidfd_send_signal() { | ||
match unsafe { fork().unwrap() } { | ||
ForkResult::Parent { child } => { | ||
// Send SIGUSR1 | ||
let pid_fd = pid_open(child, false).unwrap(); | ||
pidfd_send_signal(pid_fd, Signal::SIGUSR1, None).unwrap(); | ||
// Wait for child to exit. | ||
waitpid(child, None).unwrap(); | ||
} | ||
ForkResult::Child => { | ||
// Wait for SIGUSR1 | ||
let mut mask = SigSet::empty(); | ||
mask.add(Signal::SIGUSR1); | ||
assert_eq!(mask.wait().unwrap(), Signal::SIGUSR1); | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The assertion is done in child process. So even if it fails, the main process would still succeed, which is not what we want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the parent needs to assert on the exit code of the child process? How would you suggest doing this?