Skip to content

Commit 99677ad

Browse files
committed
[musl] use posix_spawn if a directory change was requested
Currently, not all libcs have the `posix_spawn_file_actions_addchdir_np` symbol available to them. So we attempt to do a weak symbol lookup for that function. But that only works if libc is a dynamic library -- with statically linked musl binaries the symbol lookup would never work, so we would never be able to use it even if the musl in use supported the symbol. Now that Rust has a minimum musl version of 1.2.3, all supported musl versions now include this symbol, so we can unconditionally expect it to be there. This symbol was added to libc in rust-lang/libc#3949 -- use it here. I couldn't find any tests for whether the posix_spawn path is used, but I've verified with cargo-nextest that this change works. This is a substantial improvement to nextest's performance with musl. On my workstation with a Ryzen 7950x, against https://github.com/clap-rs/clap at 61f5ee514f8f60ed8f04c6494bdf36c19e7a8126: Before: ``` Summary [ 1.071s] 879 tests run: 879 passed, 0 skipped ``` After: ``` Summary [ 0.392s] 879 tests run: 879 passed, 0 skipped ``` Fixes rust-lang#99740.
1 parent 86bd459 commit 99677ad

File tree

3 files changed

+45
-16
lines changed

3 files changed

+45
-16
lines changed

library/Cargo.lock

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This file is automatically @generated by Cargo.
22
# It is not intended for manual editing.
3-
version = 3
3+
version = 4
44

55
[[package]]
66
name = "addr2line"
@@ -158,9 +158,9 @@ dependencies = [
158158

159159
[[package]]
160160
name = "libc"
161-
version = "0.2.159"
161+
version = "0.2.161"
162162
source = "registry+https://github.com/rust-lang/crates.io-index"
163-
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
163+
checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
164164
dependencies = [
165165
"rustc-std-workspace-core",
166166
]

library/std/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ miniz_oxide = { version = "0.7.0", optional = true, default-features = false }
3939
addr2line = { version = "0.22.0", optional = true, default-features = false }
4040

4141
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
42-
libc = { version = "0.2.159", default-features = false, features = [
42+
libc = { version = "0.2.161", default-features = false, features = [
4343
'rustc-dep-of-std',
4444
], public = true }
4545

library/std/src/sys/pal/unix/process/process_unix.rs

+41-12
Original file line numberDiff line numberDiff line change
@@ -575,16 +575,6 @@ impl Command {
575575
}
576576
}
577577

578-
// Solaris, glibc 2.29+, and musl 1.24+ can set a new working directory,
579-
// and maybe others will gain this non-POSIX function too. We'll check
580-
// for this weak symbol as soon as it's needed, so we can return early
581-
// otherwise to do a manual chdir before exec.
582-
weak! {
583-
fn posix_spawn_file_actions_addchdir_np(
584-
*mut libc::posix_spawn_file_actions_t,
585-
*const libc::c_char
586-
) -> libc::c_int
587-
}
588578
let addchdir = match self.get_cwd() {
589579
Some(cwd) => {
590580
if cfg!(target_vendor = "apple") {
@@ -597,7 +587,10 @@ impl Command {
597587
return Ok(None);
598588
}
599589
}
600-
match posix_spawn_file_actions_addchdir_np.get() {
590+
// Check for the availability of the posix_spawn addchdir
591+
// function now. If it isn't available, bail and use the
592+
// fork/exec path.
593+
match get_posix_spawn_addchdir() {
601594
Some(f) => Some((f, cwd)),
602595
None => return Ok(None),
603596
}
@@ -871,6 +864,42 @@ impl Command {
871864
}
872865
}
873866

867+
type PosixSpawnAddChdirFn =
868+
unsafe extern "C" fn(*mut libc::posix_spawn_file_actions_t, *const libc::c_char) -> libc::c_int;
869+
870+
/// Get the function pointer for adding a chdir action to a
871+
/// `posix_spawn_file_actions_t`, if available, assuming a dynamic libc.
872+
///
873+
/// Some platforms can set a new working directory for a spawned process in the
874+
/// `posix_spawn` path. This function looks up the function pointer for adding
875+
/// such an action to a `posix_spawn_file_actions_t` struct.
876+
#[cfg(not(all(target_os = "linux", target_env = "musl")))]
877+
fn get_posix_spawn_addchdir() -> Option<PosixSpawnAddChdirFn> {
878+
use crate::sys::weak::weak;
879+
880+
weak! {
881+
fn posix_spawn_file_actions_addchdir_np(
882+
*mut libc::posix_spawn_file_actions_t,
883+
*const libc::c_char
884+
) -> libc::c_int
885+
}
886+
887+
posix_spawn_file_actions_addchdir_np.get()
888+
}
889+
890+
/// Get the function pointer for adding a chdir action to a
891+
/// `posix_spawn_file_actions_t`, if available, on platforms where the function
892+
/// is known to exist.
893+
///
894+
/// Weak symbol lookup doesn't work with statically linked libcs, so in cases
895+
/// where static linking is possible we need to either check for the presence
896+
/// of the symbol at compile time or know about it upfront.
897+
#[cfg(all(target_os = "linux", target_env = "musl"))]
898+
fn get_posix_spawn_addchdir() -> Option<PosixSpawnAddChdirFn> {
899+
// Our minimum required musl supports this function, so we can just use it.
900+
Some(libc::posix_spawn_file_actions_addchdir_np)
901+
}
902+
874903
////////////////////////////////////////////////////////////////////////////////
875904
// Processes
876905
////////////////////////////////////////////////////////////////////////////////
@@ -1190,8 +1219,8 @@ impl ExitStatusError {
11901219
mod linux_child_ext {
11911220

11921221
use crate::os::linux::process as os;
1193-
use crate::sys::pal::unix::ErrorKind;
11941222
use crate::sys::pal::unix::linux::pidfd as imp;
1223+
use crate::sys::pal::unix::ErrorKind;
11951224
use crate::sys_common::FromInner;
11961225
use crate::{io, mem};
11971226

0 commit comments

Comments
 (0)