Skip to content

Commit 11696ac

Browse files
alexcrichtonbdrewery
authored andcommitted
Support posix_spawn() when possible.
1 parent 518b3f7 commit 11696ac

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed

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

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ impl Command {
2424
-> io::Result<(Process, StdioPipes)> {
2525
use sys;
2626

27+
2728
const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX";
2829

2930
let envp = self.capture_env();
@@ -34,6 +35,11 @@ impl Command {
3435
}
3536

3637
let (ours, theirs) = self.setup_io(default, needs_stdin)?;
38+
39+
if let Some(ret) = self.posix_spawn(&theirs, envp.as_ref())? {
40+
return Ok((ret, ours))
41+
}
42+
3743
let (input, output) = sys::pipe::anon_pipe()?;
3844

3945
let pid = unsafe {
@@ -229,6 +235,102 @@ impl Command {
229235
libc::execvp(self.get_argv()[0], self.get_argv().as_ptr());
230236
io::Error::last_os_error()
231237
}
238+
239+
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
240+
fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>)
241+
-> io::Result<Option<Process>>
242+
{
243+
Ok(None)
244+
}
245+
246+
#[cfg(any(target_os = "linux", target_os = "macos"))]
247+
fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>)
248+
-> io::Result<Option<Process>>
249+
{
250+
use mem;
251+
use sys;
252+
253+
if self.get_cwd().is_some() ||
254+
self.get_gid().is_some() ||
255+
self.get_uid().is_some() ||
256+
self.get_closures().len() != 0 {
257+
return Ok(None)
258+
}
259+
260+
let mut p = Process { pid: 0, status: None };
261+
262+
struct PosixSpawnFileActions(libc::posix_spawn_file_actions_t);
263+
264+
impl Drop for PosixSpawnFileActions {
265+
fn drop(&mut self) {
266+
unsafe {
267+
libc::posix_spawn_file_actions_destroy(&mut self.0);
268+
}
269+
}
270+
}
271+
272+
struct PosixSpawnattr(libc::posix_spawnattr_t);
273+
274+
impl Drop for PosixSpawnattr {
275+
fn drop(&mut self) {
276+
unsafe {
277+
libc::posix_spawnattr_destroy(&mut self.0);
278+
}
279+
}
280+
}
281+
282+
unsafe {
283+
let mut file_actions = PosixSpawnFileActions(mem::zeroed());
284+
let mut attrs = PosixSpawnattr(mem::zeroed());
285+
286+
libc::posix_spawnattr_init(&mut attrs.0);
287+
libc::posix_spawn_file_actions_init(&mut file_actions.0);
288+
289+
if let Some(fd) = stdio.stdin.fd() {
290+
cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
291+
fd,
292+
libc::STDIN_FILENO))?;
293+
}
294+
if let Some(fd) = stdio.stdout.fd() {
295+
cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
296+
fd,
297+
libc::STDOUT_FILENO))?;
298+
}
299+
if let Some(fd) = stdio.stderr.fd() {
300+
cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
301+
fd,
302+
libc::STDERR_FILENO))?;
303+
}
304+
305+
let mut set: libc::sigset_t = mem::zeroed();
306+
cvt(libc::sigemptyset(&mut set))?;
307+
cvt(libc::posix_spawnattr_setsigmask(&mut attrs.0,
308+
&set))?;
309+
cvt(libc::sigaddset(&mut set, libc::SIGPIPE))?;
310+
cvt(libc::posix_spawnattr_setsigdefault(&mut attrs.0,
311+
&set))?;
312+
313+
let flags = libc::POSIX_SPAWN_SETSIGDEF |
314+
libc::POSIX_SPAWN_SETSIGMASK;
315+
cvt(libc::posix_spawnattr_setflags(&mut attrs.0, flags as _))?;
316+
317+
let envp = envp.map(|c| c.as_ptr())
318+
.unwrap_or(sys::os::environ() as *const _);
319+
let ret = libc::posix_spawnp(
320+
&mut p.pid,
321+
self.get_argv()[0],
322+
&file_actions.0,
323+
&attrs.0,
324+
self.get_argv().as_ptr() as *const _,
325+
envp as *const _,
326+
);
327+
if ret == 0 {
328+
Ok(Some(p))
329+
} else {
330+
Err(io::Error::last_os_error())
331+
}
332+
}
333+
}
232334
}
233335

234336
////////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)