From a301655c8aed20e5cea9a062663820fc29c5e80c Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 13 Feb 2019 12:20:23 -0800 Subject: [PATCH] Use posix_spawn_file_actions_addchdir_np when possible This is a non-POSIX extension implemented in Solaris and in glibc 2.29. With this we can still use `posix_spawn()` when `Command::current_dir()` has been set, otherwise we fallback to `fork(); chdir(); exec()`. --- src/libstd/sys/unix/process/process_unix.rs | 24 +++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/unix/process/process_unix.rs b/src/libstd/sys/unix/process/process_unix.rs index 12d3e9b13b1..6fbbbb349b1 100644 --- a/src/libstd/sys/unix/process/process_unix.rs +++ b/src/libstd/sys/unix/process/process_unix.rs @@ -281,8 +281,7 @@ fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>) use mem; use sys; - if self.get_cwd().is_some() || - self.get_gid().is_some() || + if self.get_gid().is_some() || self.get_uid().is_some() || self.env_saw_path() || self.get_closures().len() != 0 { @@ -301,6 +300,24 @@ fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>) } } + // Solaris and glibc 2.29+ can set a new working directory, and maybe + // others will gain this non-POSIX function too. We'll check for this + // weak symbol as soon as it's needed, so we can return early otherwise + // to do a manual chdir before exec. + weak! { + fn posix_spawn_file_actions_addchdir_np( + *mut libc::posix_spawn_file_actions_t, + *const libc::c_char + ) -> libc::c_int + } + let addchdir = match self.get_cwd() { + Some(cwd) => match posix_spawn_file_actions_addchdir_np.get() { + Some(f) => Some((f, cwd)), + None => return Ok(None), + }, + None => None, + }; + let mut p = Process { pid: 0, status: None }; struct PosixSpawnFileActions(libc::posix_spawn_file_actions_t); @@ -345,6 +362,9 @@ fn drop(&mut self) { fd, libc::STDERR_FILENO))?; } + if let Some((f, cwd)) = addchdir { + cvt(f(&mut file_actions.0, cwd.as_ptr()))?; + } let mut set: libc::sigset_t = mem::uninitialized(); cvt(libc::sigemptyset(&mut set))?; -- 2.44.0