1 use crate::io
::{self, Error, ErrorKind}
;
2 use libc
::{self, c_int, c_char}
;
6 use crate::sys
::process
::rtp
;
7 use crate::sys
::process
::process_common
::*;
9 ////////////////////////////////////////////////////////////////////////////////
11 ////////////////////////////////////////////////////////////////////////////////
14 pub fn spawn(&mut self, default: Stdio
, needs_stdin
: bool
)
15 -> io
::Result
<(Process
, StdioPipes
)> {
16 use crate::sys
::{cvt_r}
;
17 const CLOEXEC_MSG_FOOTER
: &'
static [u8] = b
"NOEX";
20 return Err(io
::Error
::new(ErrorKind
::InvalidInput
,
21 "nul byte found in provided data"));
23 let (ours
, theirs
) = self.setup_io(default, needs_stdin
)?
;
24 let mut p
= Process { pid: 0, status: None }
;
28 ($e
:expr
) => (match $e
{
30 Err(e
) => return Err(e
.into()),
34 let mut orig_stdin
= libc
::STDIN_FILENO
;
35 let mut orig_stdout
= libc
::STDOUT_FILENO
;
36 let mut orig_stderr
= libc
::STDERR_FILENO
;
38 if let Some(fd
) = theirs
.stdin
.fd() {
39 orig_stdin
= t
!(cvt_r(|| libc
::dup(libc
::STDIN_FILENO
)));
40 t
!(cvt_r(|| libc
::dup2(fd
, libc
::STDIN_FILENO
)));
42 if let Some(fd
) = theirs
.stdout
.fd() {
43 orig_stdout
= t
!(cvt_r(|| libc
::dup(libc
::STDOUT_FILENO
)));
44 t
!(cvt_r(|| libc
::dup2(fd
, libc
::STDOUT_FILENO
)));
46 if let Some(fd
) = theirs
.stderr
.fd() {
47 orig_stderr
= t
!(cvt_r(|| libc
::dup(libc
::STDERR_FILENO
)));
48 t
!(cvt_r(|| libc
::dup2(fd
, libc
::STDERR_FILENO
)));
51 if let Some(ref cwd
) = *self.get_cwd() {
52 t
!(cvt(libc
::chdir(cwd
.as_ptr())));
55 let ret
= rtp
::rtpSpawn(
56 self.get_argv()[0], // executing program
57 self.get_argv().as_ptr() as *const _
, // argv
58 *sys
::os
::environ() as *const *const c_char
,
59 100 as c_int
, // initial priority
60 0x16000, // initial stack size. 0 defaults
61 // to 0x4000 in 32 bit and 0x8000 in 64 bit
66 // Because FileDesc was not used, each duplicated file descriptor
67 // needs to be closed manually
68 if orig_stdin
!= libc
::STDIN_FILENO
{
69 t
!(cvt_r(|| libc
::dup2(orig_stdin
, libc
::STDIN_FILENO
)));
70 libc
::close(orig_stdin
);
72 if orig_stdout
!= libc
::STDOUT_FILENO
{
73 t
!(cvt_r(|| libc
::dup2(orig_stdout
, libc
::STDOUT_FILENO
)));
74 libc
::close(orig_stdout
);
76 if orig_stderr
!= libc
::STDERR_FILENO
{
77 t
!(cvt_r(|| libc
::dup2(orig_stderr
, libc
::STDERR_FILENO
)));
78 libc
::close(orig_stderr
);
81 if ret
!= rtp
::RTP_ID_ERROR
{
85 Err(io
::Error
::last_os_error())
90 pub fn exec(&mut self, default: Stdio
) -> io
::Error
{
91 let ret
= Command
::spawn(self, default, false);
94 let mut status
= 0 as c_int
;
95 libc
::waitpid(t
.0.pid
, &mut status
, 0);
103 ////////////////////////////////////////////////////////////////////////////////
105 ////////////////////////////////////////////////////////////////////////////////
107 /// The unique id of the process (this should never be negative).
110 status
: Option
<ExitStatus
>,
114 pub fn id(&self) -> u32 {
118 pub fn kill(&mut self) -> io
::Result
<()> {
119 // If we've already waited on this process then the pid can be recycled
120 // and used for another process, and we probably shouldn't be killing
121 // random processes, so just return an error.
122 if self.status
.is_some() {
123 Err(Error
::new(ErrorKind
::InvalidInput
,
124 "invalid argument: can't kill an exited process"))
126 cvt(unsafe { libc::kill(self.pid, libc::SIGKILL) }
).map(|_
| ())
130 pub fn wait(&mut self) -> io
::Result
<ExitStatus
> {
131 use crate::sys
::cvt_r
;
132 if let Some(status
) = self.status
{
135 let mut status
= 0 as c_int
;
136 cvt_r(|| unsafe { libc::waitpid(self.pid, &mut status, 0) }
)?
;
137 self.status
= Some(ExitStatus
::new(status
));
138 Ok(ExitStatus
::new(status
))
141 pub fn try_wait(&mut self) -> io
::Result
<Option
<ExitStatus
>> {
142 if let Some(status
) = self.status
{
143 return Ok(Some(status
))
145 let mut status
= 0 as c_int
;
146 let pid
= cvt(unsafe {
147 libc
::waitpid(self.pid
, &mut status
, libc
::WNOHANG
)
152 self.status
= Some(ExitStatus
::new(status
));
153 Ok(Some(ExitStatus
::new(status
)))