Skip to content

Commit a301655

Browse files
committed
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()`.
1 parent 0f949c2 commit a301655

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

src/libstd/sys/unix/process/process_unix.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,7 @@ impl Command {
281281
use mem;
282282
use sys;
283283

284-
if self.get_cwd().is_some() ||
285-
self.get_gid().is_some() ||
284+
if self.get_gid().is_some() ||
286285
self.get_uid().is_some() ||
287286
self.env_saw_path() ||
288287
self.get_closures().len() != 0 {
@@ -301,6 +300,24 @@ impl Command {
301300
}
302301
}
303302

303+
// Solaris and glibc 2.29+ can set a new working directory, and maybe
304+
// others will gain this non-POSIX function too. We'll check for this
305+
// weak symbol as soon as it's needed, so we can return early otherwise
306+
// to do a manual chdir before exec.
307+
weak! {
308+
fn posix_spawn_file_actions_addchdir_np(
309+
*mut libc::posix_spawn_file_actions_t,
310+
*const libc::c_char
311+
) -> libc::c_int
312+
}
313+
let addchdir = match self.get_cwd() {
314+
Some(cwd) => match posix_spawn_file_actions_addchdir_np.get() {
315+
Some(f) => Some((f, cwd)),
316+
None => return Ok(None),
317+
},
318+
None => None,
319+
};
320+
304321
let mut p = Process { pid: 0, status: None };
305322

306323
struct PosixSpawnFileActions(libc::posix_spawn_file_actions_t);
@@ -345,6 +362,9 @@ impl Command {
345362
fd,
346363
libc::STDERR_FILENO))?;
347364
}
365+
if let Some((f, cwd)) = addchdir {
366+
cvt(f(&mut file_actions.0, cwd.as_ptr()))?;
367+
}
348368

349369
let mut set: libc::sigset_t = mem::uninitialized();
350370
cvt(libc::sigemptyset(&mut set))?;

0 commit comments

Comments
 (0)