diff options
| author | Josh Stone <jistone@redhat.com> | 2019-02-13 12:20:23 -0800 |
|---|---|---|
| committer | Josh Stone <jistone@redhat.com> | 2019-02-13 12:20:23 -0800 |
| commit | a301655c8aed20e5cea9a062663820fc29c5e80c (patch) | |
| tree | 9497fbbd2baab5c9ff60c8338d3a8b14bbe65fb7 | |
| parent | 0f949c2fcc696d0260a99196d5e5400c59a26a54 (diff) | |
| download | rust-a301655c8aed20e5cea9a062663820fc29c5e80c.tar.gz rust-a301655c8aed20e5cea9a062663820fc29c5e80c.zip | |
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()`.
| -rw-r--r-- | src/libstd/sys/unix/process/process_unix.rs | 24 |
1 files 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 @@ impl Command { 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 @@ impl Command { } } + // 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 @@ impl Command { 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))?; |
