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()`.
This commit is contained in:
@@ -281,8 +281,7 @@ impl Command {
|
|||||||
use mem;
|
use mem;
|
||||||
use sys;
|
use sys;
|
||||||
|
|
||||||
if self.get_cwd().is_some() ||
|
if self.get_gid().is_some() ||
|
||||||
self.get_gid().is_some() ||
|
|
||||||
self.get_uid().is_some() ||
|
self.get_uid().is_some() ||
|
||||||
self.env_saw_path() ||
|
self.env_saw_path() ||
|
||||||
self.get_closures().len() != 0 {
|
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 };
|
let mut p = Process { pid: 0, status: None };
|
||||||
|
|
||||||
struct PosixSpawnFileActions(libc::posix_spawn_file_actions_t);
|
struct PosixSpawnFileActions(libc::posix_spawn_file_actions_t);
|
||||||
@@ -345,6 +362,9 @@ impl Command {
|
|||||||
fd,
|
fd,
|
||||||
libc::STDERR_FILENO))?;
|
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();
|
let mut set: libc::sigset_t = mem::uninitialized();
|
||||||
cvt(libc::sigemptyset(&mut set))?;
|
cvt(libc::sigemptyset(&mut set))?;
|
||||||
|
|||||||
Reference in New Issue
Block a user