1 // Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use os
::unix
::prelude
::*;
13 use collections
::hash_map
::{HashMap, Entry}
;
15 use ffi
::{OsString, OsStr, CString, CStr}
;
17 use io
::{self, Error, ErrorKind}
;
18 use libc
::{self, pid_t, c_int, gid_t, uid_t, c_char}
;
21 use sys
::fd
::FileDesc
;
22 use sys
::fs
::{File, OpenOptions}
;
23 use sys
::pipe
::{self, AnonPipe}
;
24 use sys
::{self, cvt, cvt_r}
;
26 ////////////////////////////////////////////////////////////////////////////////
28 ////////////////////////////////////////////////////////////////////////////////
31 // Currently we try hard to ensure that the call to `.exec()` doesn't
32 // actually allocate any memory. While many platforms try to ensure that
33 // memory allocation works after a fork in a multithreaded process, it's
34 // been observed to be buggy and somewhat unreliable, so we do our best to
35 // just not do it at all!
37 // Along those lines, the `argv` and `envp` raw pointers here are exactly
38 // what's gonna get passed to `execvp`. The `argv` array starts with the
39 // `program` and ends with a NULL, and the `envp` pointer, if present, is
40 // also null-terminated.
42 // Right now we don't support removing arguments, so there's no much fancy
43 // support there, but we support adding and removing environment variables,
44 // so a side table is used to track where in the `envp` array each key is
45 // located. Whenever we add a key we update it in place if it's already
46 // present, and whenever we remove a key we update the locations of all
50 env
: Option
<HashMap
<OsString
, (usize, CString
)>>,
51 argv
: Vec
<*const c_char
>,
52 envp
: Option
<Vec
<*const c_char
>>,
58 closures
: Vec
<Box
<FnMut() -> io
::Result
<()> + Send
+ Sync
>>,
60 stdout
: Option
<Stdio
>,
61 stderr
: Option
<Stdio
>,
64 // passed back to std::process with the pipes connected to the child, if any
66 pub struct StdioPipes
{
67 pub stdin
: Option
<AnonPipe
>,
68 pub stdout
: Option
<AnonPipe
>,
69 pub stderr
: Option
<AnonPipe
>,
72 // passed to do_exec() with configuration of what the child stdio should look
94 pub fn new(program
: &OsStr
) -> Command
{
95 let mut saw_nul
= false;
96 let program
= os2c(program
, &mut saw_nul
);
98 argv
: vec
![program
.as_ptr(), ptr
::null()],
107 closures
: Vec
::new(),
114 pub fn arg(&mut self, arg
: &OsStr
) {
115 // Overwrite the trailing NULL pointer in `argv` and then add a new null
117 let arg
= os2c(arg
, &mut self.saw_nul
);
118 self.argv
[self.args
.len() + 1] = arg
.as_ptr();
119 self.argv
.push(ptr
::null());
121 // Also make sure we keep track of the owned value to schedule a
122 // destructor for this memory.
126 fn init_env_map(&mut self) -> (&mut HashMap
<OsString
, (usize, CString
)>,
127 &mut Vec
<*const c_char
>) {
128 if self.env
.is_none() {
129 let mut map
= HashMap
::new();
130 let mut envp
= Vec
::new();
131 for (k
, v
) in env
::vars_os() {
132 let s
= pair_to_key(&k
, &v
, &mut self.saw_nul
);
133 envp
.push(s
.as_ptr());
134 map
.insert(k
, (envp
.len() - 1, s
));
136 envp
.push(ptr
::null());
137 self.env
= Some(map
);
138 self.envp
= Some(envp
);
140 (self.env
.as_mut().unwrap(), self.envp
.as_mut().unwrap())
143 pub fn env(&mut self, key
: &OsStr
, val
: &OsStr
) {
144 let new_key
= pair_to_key(key
, val
, &mut self.saw_nul
);
145 let (map
, envp
) = self.init_env_map();
147 // If `key` is already present then we just update `envp` in place
148 // (and store the owned value), but if it's not there we override the
149 // trailing NULL pointer, add a new NULL pointer, and store where we
151 match map
.entry(key
.to_owned()) {
152 Entry
::Occupied(mut e
) => {
153 let (i
, ref mut s
) = *e
.get_mut();
154 envp
[i
] = new_key
.as_ptr();
157 Entry
::Vacant(e
) => {
158 let len
= envp
.len();
159 envp
[len
- 1] = new_key
.as_ptr();
160 envp
.push(ptr
::null());
161 e
.insert((len
- 1, new_key
));
166 pub fn env_remove(&mut self, key
: &OsStr
) {
167 let (map
, envp
) = self.init_env_map();
169 // If we actually ended up removing a key, then we need to update the
170 // position of all keys that come after us in `envp` because they're all
171 // one element sooner now.
172 if let Some((i
, _
)) = map
.remove(key
) {
175 for (_
, &mut (ref mut j
, _
)) in map
.iter_mut() {
183 pub fn env_clear(&mut self) {
184 self.env
= Some(HashMap
::new());
185 self.envp
= Some(vec
![ptr
::null()]);
188 pub fn cwd(&mut self, dir
: &OsStr
) {
189 self.cwd
= Some(os2c(dir
, &mut self.saw_nul
));
191 pub fn uid(&mut self, id
: uid_t
) {
194 pub fn gid(&mut self, id
: gid_t
) {
198 pub fn before_exec(&mut self,
199 f
: Box
<FnMut() -> io
::Result
<()> + Send
+ Sync
>) {
200 self.closures
.push(f
);
203 pub fn stdin(&mut self, stdin
: Stdio
) {
204 self.stdin
= Some(stdin
);
206 pub fn stdout(&mut self, stdout
: Stdio
) {
207 self.stdout
= Some(stdout
);
209 pub fn stderr(&mut self, stderr
: Stdio
) {
210 self.stderr
= Some(stderr
);
213 pub fn spawn(&mut self, default: Stdio
, needs_stdin
: bool
)
214 -> io
::Result
<(Process
, StdioPipes
)> {
215 const CLOEXEC_MSG_FOOTER
: &'
static [u8] = b
"NOEX";
218 return Err(io
::Error
::new(ErrorKind
::InvalidInput
,
219 "nul byte found in provided data"));
222 let (ours
, theirs
) = self.setup_io(default, needs_stdin
)?
;
223 let (input
, output
) = sys
::pipe
::anon_pipe()?
;
226 match cvt(libc
::fork())?
{
229 let err
= self.do_exec(theirs
);
230 let errno
= err
.raw_os_error().unwrap_or(libc
::EINVAL
) as u32;
236 CLOEXEC_MSG_FOOTER
[0], CLOEXEC_MSG_FOOTER
[1],
237 CLOEXEC_MSG_FOOTER
[2], CLOEXEC_MSG_FOOTER
[3]
239 // pipe I/O up to PIPE_BUF bytes should be atomic, and then
240 // we want to be sure we *don't* run at_exit destructors as
241 // we're being torn down regardless
242 assert
!(output
.write(&bytes
).is_ok());
249 let mut p
= Process { pid: pid, status: None }
;
251 let mut bytes
= [0; 8];
253 // loop to handle EINTR
255 match input
.read(&mut bytes
) {
256 Ok(0) => return Ok((p
, ours
)),
258 assert
!(combine(CLOEXEC_MSG_FOOTER
) == combine(&bytes
[4.. 8]),
259 "Validation on the CLOEXEC pipe failed: {:?}", bytes
);
260 let errno
= combine(&bytes
[0.. 4]);
261 assert
!(p
.wait().is_ok(),
262 "wait() should either return Ok or panic");
263 return Err(Error
::from_raw_os_error(errno
))
265 Err(ref e
) if e
.kind() == ErrorKind
::Interrupted
=> {}
267 assert
!(p
.wait().is_ok(),
268 "wait() should either return Ok or panic");
269 panic
!("the CLOEXEC pipe failed: {:?}", e
)
271 Ok(..) => { // pipe I/O up to PIPE_BUF bytes should be atomic
272 assert
!(p
.wait().is_ok(),
273 "wait() should either return Ok or panic");
274 panic
!("short read on the CLOEXEC pipe")
279 fn combine(arr
: &[u8]) -> i32 {
280 let a
= arr
[0] as u32;
281 let b
= arr
[1] as u32;
282 let c
= arr
[2] as u32;
283 let d
= arr
[3] as u32;
285 ((a
<< 24) | (b
<< 16) | (c
<< 8) | (d
<< 0)) as i32
289 pub fn exec(&mut self, default: Stdio
) -> io
::Error
{
291 return io
::Error
::new(ErrorKind
::InvalidInput
,
292 "nul byte found in provided data")
295 match self.setup_io(default, true) {
296 Ok((_
, theirs
)) => unsafe { self.do_exec(theirs) }
,
301 // And at this point we've reached a special time in the life of the
302 // child. The child must now be considered hamstrung and unable to
303 // do anything other than syscalls really. Consider the following
306 // 1. Thread A of process 1 grabs the malloc() mutex
307 // 2. Thread B of process 1 forks(), creating thread C
308 // 3. Thread C of process 2 then attempts to malloc()
309 // 4. The memory of process 2 is the same as the memory of
310 // process 1, so the mutex is locked.
312 // This situation looks a lot like deadlock, right? It turns out
313 // that this is what pthread_atfork() takes care of, which is
314 // presumably implemented across platforms. The first thing that
315 // threads to *before* forking is to do things like grab the malloc
316 // mutex, and then after the fork they unlock it.
318 // Despite this information, libnative's spawn has been witnessed to
319 // deadlock on both OSX and FreeBSD. I'm not entirely sure why, but
320 // all collected backtraces point at malloc/free traffic in the
321 // child spawned process.
323 // For this reason, the block of code below should contain 0
324 // invocations of either malloc of free (or their related friends).
326 // As an example of not having malloc/free traffic, we don't close
327 // this file descriptor by dropping the FileDesc (which contains an
328 // allocation). Instead we just close it manually. This will never
329 // have the drop glue anyway because this code never returns (the
330 // child will either exec() or invoke libc::exit)
331 unsafe fn do_exec(&mut self, stdio
: ChildPipes
) -> io
::Error
{
333 ($e
:expr
) => (match $e
{
339 if let Some(fd
) = stdio
.stdin
.fd() {
340 t
!(cvt_r(|| libc
::dup2(fd
, libc
::STDIN_FILENO
)));
342 if let Some(fd
) = stdio
.stdout
.fd() {
343 t
!(cvt_r(|| libc
::dup2(fd
, libc
::STDOUT_FILENO
)));
345 if let Some(fd
) = stdio
.stderr
.fd() {
346 t
!(cvt_r(|| libc
::dup2(fd
, libc
::STDERR_FILENO
)));
349 if let Some(u
) = self.gid
{
350 t
!(cvt(libc
::setgid(u
as gid_t
)));
352 if let Some(u
) = self.uid
{
353 // When dropping privileges from root, the `setgroups` call
354 // will remove any extraneous groups. If we don't call this,
355 // then even though our uid has dropped, we may still have
356 // groups that enable us to do super-user things. This will
357 // fail if we aren't root, so don't bother checking the
358 // return value, this is just done as an optimistic
359 // privilege dropping function.
360 let _
= libc
::setgroups(0, ptr
::null());
362 t
!(cvt(libc
::setuid(u
as uid_t
)));
364 if let Some(ref cwd
) = self.cwd
{
365 t
!(cvt(libc
::chdir(cwd
.as_ptr())));
367 if let Some(ref envp
) = self.envp
{
368 *sys
::os
::environ() = envp
.as_ptr();
371 // NaCl has no signal support.
372 if cfg
!(not(any(target_os
= "nacl", target_os
= "emscripten"))) {
373 // Reset signal handling so the child process starts in a
374 // standardized state. libstd ignores SIGPIPE, and signal-handling
375 // libraries often set a mask. Child processes inherit ignored
376 // signals and the signal mask from their parent, but most
377 // UNIX programs do not reset these things on their own, so we
378 // need to clean things up now to avoid confusing the program
379 // we're about to run.
380 let mut set
: libc
::sigset_t
= mem
::uninitialized();
381 t
!(cvt(libc
::sigemptyset(&mut set
)));
382 t
!(cvt(libc
::pthread_sigmask(libc
::SIG_SETMASK
, &set
,
384 let ret
= super::signal(libc
::SIGPIPE
, libc
::SIG_DFL
);
385 if ret
== libc
::SIG_ERR
{
386 return io
::Error
::last_os_error()
390 for callback
in self.closures
.iter_mut() {
394 libc
::execvp(self.argv
[0], self.argv
.as_ptr());
395 io
::Error
::last_os_error()
399 fn setup_io(&self, default: Stdio
, needs_stdin
: bool
)
400 -> io
::Result
<(StdioPipes
, ChildPipes
)> {
401 let null
= Stdio
::Null
;
402 let default_stdin
= if needs_stdin {&default}
else {&null}
;
403 let stdin
= self.stdin
.as_ref().unwrap_or(default_stdin
);
404 let stdout
= self.stdout
.as_ref().unwrap_or(&default);
405 let stderr
= self.stderr
.as_ref().unwrap_or(&default);
406 let (their_stdin
, our_stdin
) = stdin
.to_child_stdio(true)?
;
407 let (their_stdout
, our_stdout
) = stdout
.to_child_stdio(false)?
;
408 let (their_stderr
, our_stderr
) = stderr
.to_child_stdio(false)?
;
409 let ours
= StdioPipes
{
414 let theirs
= ChildPipes
{
416 stdout
: their_stdout
,
417 stderr
: their_stderr
,
423 fn os2c(s
: &OsStr
, saw_nul
: &mut bool
) -> CString
{
424 CString
::new(s
.as_bytes()).unwrap_or_else(|_e
| {
426 CString
::new("<string-with-nul>").unwrap()
431 fn to_child_stdio(&self, readable
: bool
)
432 -> io
::Result
<(ChildStdio
, Option
<AnonPipe
>)> {
434 Stdio
::Inherit
=> Ok((ChildStdio
::Inherit
, None
)),
436 // Make sure that the source descriptors are not an stdio
437 // descriptor, otherwise the order which we set the child's
438 // descriptors may blow away a descriptor which we are hoping to
439 // save. For example, suppose we want the child's stderr to be the
440 // parent's stdout, and the child's stdout to be the parent's
441 // stderr. No matter which we dup first, the second will get
442 // overwritten prematurely.
443 Stdio
::Fd(ref fd
) => {
444 if fd
.raw() >= 0 && fd
.raw() <= libc
::STDERR_FILENO
{
445 Ok((ChildStdio
::Owned(fd
.duplicate()?
), None
))
447 Ok((ChildStdio
::Explicit(fd
.raw()), None
))
452 let (reader
, writer
) = pipe
::anon_pipe()?
;
453 let (ours
, theirs
) = if readable
{
458 Ok((ChildStdio
::Owned(theirs
.into_fd()), Some(ours
)))
462 let mut opts
= OpenOptions
::new();
464 opts
.write(!readable
);
466 CStr
::from_ptr("/dev/null\0".as_ptr() as *const _
)
468 let fd
= File
::open_c(&path
, &opts
)?
;
469 Ok((ChildStdio
::Owned(fd
.into_fd()), None
))
476 fn fd(&self) -> Option
<c_int
> {
478 ChildStdio
::Inherit
=> None
,
479 ChildStdio
::Explicit(fd
) => Some(fd
),
480 ChildStdio
::Owned(ref fd
) => Some(fd
.raw()),
485 fn pair_to_key(key
: &OsStr
, value
: &OsStr
, saw_nul
: &mut bool
) -> CString
{
486 let (key
, value
) = (key
.as_bytes(), value
.as_bytes());
487 let mut v
= Vec
::with_capacity(key
.len() + value
.len() + 1);
491 CString
::new(v
).unwrap_or_else(|_e
| {
493 CString
::new("foo=bar").unwrap()
497 impl fmt
::Debug
for Command
{
498 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
499 write
!(f
, "{:?}", self.program
)?
;
500 for arg
in &self.args
{
501 write
!(f
, " {:?}", arg
)?
;
507 ////////////////////////////////////////////////////////////////////////////////
509 ////////////////////////////////////////////////////////////////////////////////
511 /// Unix exit statuses
512 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
513 pub struct ExitStatus(c_int
);
516 fn exited(&self) -> bool
{
517 unsafe { libc::WIFEXITED(self.0) }
520 pub fn success(&self) -> bool
{
521 self.code() == Some(0)
524 pub fn code(&self) -> Option
<i32> {
526 Some(unsafe { libc::WEXITSTATUS(self.0) }
)
532 pub fn signal(&self) -> Option
<i32> {
534 Some(unsafe { libc::WTERMSIG(self.0) }
)
541 impl From
<c_int
> for ExitStatus
{
542 fn from(a
: c_int
) -> ExitStatus
{
547 impl fmt
::Display
for ExitStatus
{
548 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
549 if let Some(code
) = self.code() {
550 write
!(f
, "exit code: {}", code
)
552 let signal
= self.signal().unwrap();
553 write
!(f
, "signal: {}", signal
)
558 /// The unique id of the process (this should never be negative).
561 status
: Option
<ExitStatus
>,
565 pub fn id(&self) -> u32 {
569 pub fn kill(&mut self) -> io
::Result
<()> {
570 // If we've already waited on this process then the pid can be recycled
571 // and used for another process, and we probably shouldn't be killing
572 // random processes, so just return an error.
573 if self.status
.is_some() {
574 Err(Error
::new(ErrorKind
::InvalidInput
,
575 "invalid argument: can't kill an exited process"))
577 cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }
).map(|_
| ())
581 pub fn wait(&mut self) -> io
::Result
<ExitStatus
> {
582 if let Some(status
) = self.status
{
585 let mut status
= 0 as c_int
;
586 cvt_r(|| unsafe { libc::waitpid(self.pid, &mut status, 0) }
)?
;
587 self.status
= Some(ExitStatus(status
));
588 Ok(ExitStatus(status
))
592 #[cfg(all(test, not(target_os = "emscripten")))]
606 Err(e
) => panic
!("received error for `{}`: {}", stringify
!($e
), e
),
611 #[cfg(not(target_os = "android"))]
613 #[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")]
614 fn sigaddset(set
: *mut libc
::sigset_t
, signum
: libc
::c_int
) -> libc
::c_int
;
617 #[cfg(target_os = "android")]
618 unsafe fn sigaddset(set
: *mut libc
::sigset_t
, signum
: libc
::c_int
) -> libc
::c_int
{
621 let raw
= slice
::from_raw_parts_mut(set
as *mut u8, mem
::size_of
::<libc
::sigset_t
>());
622 let bit
= (signum
- 1) as usize;
623 raw
[bit
/ 8] |= 1 << (bit
% 8);
627 // See #14232 for more information, but it appears that signal delivery to a
628 // newly spawned process may just be raced in the OSX, so to prevent this
629 // test from being flaky we ignore it on OSX.
631 #[cfg_attr(target_os = "macos", ignore)]
632 #[cfg_attr(target_os = "nacl", ignore)] // no signals on NaCl.
633 fn test_process_mask() {
635 // Test to make sure that a signal mask does not get inherited.
636 let mut cmd
= Command
::new(OsStr
::new("cat"));
638 let mut set
: libc
::sigset_t
= mem
::uninitialized();
639 let mut old_set
: libc
::sigset_t
= mem
::uninitialized();
640 t
!(cvt(libc
::sigemptyset(&mut set
)));
641 t
!(cvt(sigaddset(&mut set
, libc
::SIGINT
)));
642 t
!(cvt(libc
::pthread_sigmask(libc
::SIG_SETMASK
, &set
, &mut old_set
)));
644 cmd
.stdin(Stdio
::MakePipe
);
645 cmd
.stdout(Stdio
::MakePipe
);
647 let (mut cat
, mut pipes
) = t
!(cmd
.spawn(Stdio
::Null
, true));
648 let stdin_write
= pipes
.stdin
.take().unwrap();
649 let stdout_read
= pipes
.stdout
.take().unwrap();
651 t
!(cvt(libc
::pthread_sigmask(libc
::SIG_SETMASK
, &old_set
,
654 t
!(cvt(libc
::kill(cat
.id() as libc
::pid_t
, libc
::SIGINT
)));
655 // We need to wait until SIGINT is definitely delivered. The
656 // easiest way is to write something to cat, and try to read it
657 // back: if SIGINT is unmasked, it'll get delivered when cat is
659 let _
= stdin_write
.write(b
"Hello");
662 // Either EOF or failure (EPIPE) is okay.
663 let mut buf
= [0; 5];
664 if let Ok(ret
) = stdout_read
.read(&mut buf
) {