Skip to content
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

Rollup of 9 pull requests #127650

Closed
wants to merge 41 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
a1ad634
Add fn allocator method to rc/sync::Weak. Relax Rc<T>/Arc<T>::allocat…
zachs18 May 10, 2024
5c46aca
document the cvt methods
the8472 Jun 22, 2024
6687a3f
use pidfd_spawn for faster process creation when pidfds are requested
the8472 Jun 22, 2024
0ce3619
document safety properties of the internal Process::new constructor
the8472 Jun 24, 2024
3e4e31b
more fine-grained feature-detection for pidfd spawning
the8472 Jun 24, 2024
ec0c755
Check that we get somewhat sane PIDs when spawning with pidfds
the8472 Jun 24, 2024
04eed9b
Initial implementation of annoymous_pipe
NobodyXu Jun 30, 2024
72bda33
Fix compilation errors
NobodyXu Jun 30, 2024
42e8beb
Implement validation in `TryFrom<OwnedFd> for PIpe*` on unix
NobodyXu Jun 30, 2024
e170c78
Move the mod `pipe` to `std::net`
NobodyXu Jun 30, 2024
473fbce
Fix typo
NobodyXu Jun 30, 2024
97626b6
Fix tidy errors
NobodyXu Jun 30, 2024
d60438f
Validate pipe in `TryFrom<OwnedHandle> for Pipe*`
NobodyXu Jun 30, 2024
b7af685
Refactor: Extract new method `FileDesc::get_access_mode`
NobodyXu Jun 30, 2024
4c6b6bb
Add testing for anonymous pipe
NobodyXu Jul 1, 2024
594abec
Refactor: Put mod `unix` & `windows` into separate files
NobodyXu Jul 2, 2024
d9f0980
Fix `anonymous_pipe` impl for not supported targets
NobodyXu Jul 2, 2024
6c755a3
Optimize: Add `#[inline]` to very simple function
NobodyXu Jul 2, 2024
53d3e62
Stabilize const_cstr_from_ptr (CStr::from_ptr, CStr::count_bytes)
dtolnay Jul 6, 2024
d15cee5
Refactor: Make `AcessMode` an enum`
NobodyXu Jul 9, 2024
0134bd2
remove unnecessary `git` usages
onur-ozkan Jul 10, 2024
e22dd1a
Update mod.rs
NobodyXu Jul 10, 2024
100fe5c
Move `std::net::pip*` to a new mod `std::pipe`
NobodyXu Jul 10, 2024
62b846e
Remove use of `macro_rules!`
NobodyXu Jul 10, 2024
4547b30
Replace `TryFrom<Owned*>` with `From`
NobodyXu Jul 10, 2024
f56b207
solve -> solve/mod
lcnr Jul 11, 2024
72f5999
Fix compilation on non-unix, non-windows targets
NobodyXu Jul 11, 2024
55256c5
Update dist-riscv64-linux to binutils 2.40
nikic Jul 10, 2024
ec05c4e
Add the feature gate and target-features
sayantn Jun 23, 2024
7f1518b
Add instability attribute on private const_strlen function
dtolnay Jul 12, 2024
3f4b9dd
Lower timeout of CI jobs to 4 hours
Kobzol Jul 12, 2024
15f770b
enable fuzzing of `SearchGraph`
lcnr Jul 11, 2024
0097800
Rollup merge of #124980 - zachs18:rc-allocator, r=Amanieu
matthiaskrgr Jul 12, 2024
c30bedf
Rollup merge of #126639 - sayantn:amx, r=Amanieu
matthiaskrgr Jul 12, 2024
627a13b
Rollup merge of #126827 - the8472:pidfd-spawn, r=workingjubilee
matthiaskrgr Jul 12, 2024
d9e13af
Rollup merge of #127153 - NobodyXu:pipe, r=jhpratt
matthiaskrgr Jul 12, 2024
f9ceb65
Rollup merge of #127433 - dtolnay:conststrlen, r=workingjubilee
matthiaskrgr Jul 12, 2024
d0e1f4c
Rollup merge of #127552 - onur-ozkan:unnecessary-git-usage, r=Kobzol
matthiaskrgr Jul 12, 2024
1ddb2d2
Rollup merge of #127613 - nikic:riscv-update, r=cuviper
matthiaskrgr Jul 12, 2024
e486eeb
Rollup merge of #127627 - lcnr:rustc_search_graph, r=compiler-errors
matthiaskrgr Jul 12, 2024
f5909c5
Rollup merge of #127648 - Kobzol:ci-lower-timeout, r=pietroalbini
matthiaskrgr Jul 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
use pidfd_spawn for faster process creation when pidfds are requested
  • Loading branch information
the8472 committed Jun 24, 2024
commit 6687a3f7da60a4d0f06fd84fea75bec1dd0fce2a
13 changes: 11 additions & 2 deletions library/std/src/sys/pal/unix/linux/pidfd/tests.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::assert_matches::assert_matches;
use crate::os::fd::{AsRawFd, RawFd};
use crate::os::linux::process::{ChildExt, CommandExt};
use crate::os::unix::process::ExitStatusExt;
use crate::os::linux::process::{ChildExt, CommandExt as _};
use crate::os::unix::process::{CommandExt as _, ExitStatusExt};
use crate::process::Command;

#[test]
Expand Down Expand Up @@ -42,6 +42,15 @@ fn test_command_pidfd() {
.unwrap()
.pidfd()
.expect_err("pidfd should not have been created");

// exercise the fork/exec path since the earlier attempts may have used pidfd_spawnp()
let mut child =
unsafe { Command::new("false").pre_exec(|| Ok(())) }.create_pidfd(true).spawn().unwrap();

if pidfd_open_available {
assert!(child.pidfd().is_ok())
}
child.wait().expect("error waiting on child");
}

#[test]
Expand Down
99 changes: 95 additions & 4 deletions library/std/src/sys/pal/unix/process/process_unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,17 +449,70 @@ impl Command {
use crate::mem::MaybeUninit;
use crate::sys::weak::weak;
use crate::sys::{self, cvt_nz, on_broken_pipe_flag_used};
#[cfg(target_os = "linux")]
use core::sync::atomic::{AtomicU8, Ordering};

if self.get_gid().is_some()
|| self.get_uid().is_some()
|| (self.env_saw_path() && !self.program_is_path())
|| !self.get_closures().is_empty()
|| self.get_groups().is_some()
|| self.get_create_pidfd()
{
return Ok(None);
}

cfg_if::cfg_if! {
if #[cfg(target_os = "linux")] {
weak! {
fn pidfd_spawnp(
*mut libc::c_int,
*const libc::c_char,
*const libc::posix_spawn_file_actions_t,
*const libc::posix_spawnattr_t,
*const *mut libc::c_char,
*const *mut libc::c_char
) -> libc::c_int
}

weak! { fn pidfd_getpid(libc::c_int) -> libc::c_int }

static PIDFD_SPAWN_SUPPORTED: AtomicU8 = AtomicU8::new(0);
const UNKNOWN: u8 = 0;
const YES: u8 = 1;
// NO currently forces a fallback to fork/exec. We could be more nuanced here and keep using spawn
// if we know pidfd's aren't supported at all and the fallback would be futile.
const NO: u8 = 2;

if self.get_create_pidfd() {
let flag = PIDFD_SPAWN_SUPPORTED.load(Ordering::Relaxed);
if flag == NO || pidfd_spawnp.get().is_none() || pidfd_getpid.get().is_none() {
return Ok(None);
}
if flag == UNKNOWN {
let mut support = NO;
let our_pid = crate::process::id();
let pidfd =
unsafe { libc::syscall(libc::SYS_pidfd_open, our_pid, 0) } as libc::c_int;
if pidfd >= 0 {
let pid = unsafe { pidfd_getpid.get().unwrap()(pidfd) } as u32;
unsafe { libc::close(pidfd) };
if pid == our_pid {
support = YES
};
}
PIDFD_SPAWN_SUPPORTED.store(support, Ordering::Relaxed);
if support != YES {
return Ok(None);
}
}
}
} else {
if self.get_create_pidfd() {
unreachable!("only implemented on linux")
}
}
}

// Only glibc 2.24+ posix_spawn() supports returning ENOENT directly.
#[cfg(all(target_os = "linux", target_env = "gnu"))]
{
Expand Down Expand Up @@ -543,9 +596,6 @@ impl Command {

let pgroup = self.get_pgroup();

// Safety: -1 indicates we don't have a pidfd.
let mut p = unsafe { Process::new(0, -1) };

struct PosixSpawnFileActions<'a>(&'a mut MaybeUninit<libc::posix_spawn_file_actions_t>);

impl Drop for PosixSpawnFileActions<'_> {
Expand Down Expand Up @@ -640,6 +690,47 @@ impl Command {
#[cfg(target_os = "nto")]
let spawn_fn = retrying_libc_posix_spawnp;

#[cfg(target_os = "linux")]
if self.get_create_pidfd() {
let mut pidfd: libc::c_int = -1;
let spawn_res = pidfd_spawnp.get().unwrap()(
&mut pidfd,
self.get_program_cstr().as_ptr(),
file_actions.0.as_ptr(),
attrs.0.as_ptr(),
self.get_argv().as_ptr() as *const _,
envp as *const _,
);

let spawn_res = cvt_nz(spawn_res);
if let Err(ref e) = spawn_res
&& e.raw_os_error() == Some(libc::ENOSYS)
{
PIDFD_SPAWN_SUPPORTED.store(NO, Ordering::Relaxed);
return Ok(None);
}
spawn_res?;

let pid = match cvt(pidfd_getpid.get().unwrap()(pidfd)) {
Ok(pid) => pid,
Err(e) => {
// The child has been spawned and we are holding its pidfd.
// But we cannot obtain its pid even though pidfd_getpid support was verified earlier.
// This might happen if libc can't open procfs because the file descriptor limit has been reached.
libc::close(pidfd);
return Err(Error::new(
e.kind(),
"pidfd_spawnp succeeded but the child's PID could not be obtained",
));
}
};

return Ok(Some(Process::new(pid, pidfd)));
}

// Safety: -1 indicates we don't have a pidfd.
let mut p = Process::new(0, -1);

let spawn_res = spawn_fn(
&mut p.pid,
self.get_program_cstr().as_ptr(),
Expand Down