diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2014-02-18 12:04:51 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-02-23 21:51:17 -0800 |
| commit | a9bd447400c0854600e994f562e2b230171f328f (patch) | |
| tree | 09a6faa8d9f40a5dbf491b215e749c8dca4df0be /src/libnative/io/process.rs | |
| parent | 8786405047cadcfb5ec3a2d711ca264d74843c13 (diff) | |
| download | rust-a9bd447400c0854600e994f562e2b230171f328f.tar.gz rust-a9bd447400c0854600e994f562e2b230171f328f.zip | |
Roll std::run into std::io::process
The std::run module is a relic from a standard library long since past, and there's not much use to having two modules to execute processes with where one is slightly more convenient. This commit merges the two modules, moving lots of functionality from std::run into std::io::process and then deleting std::run. New things you can find in std::io::process are: * Process::new() now only takes prog/args * Process::configure() takes a ProcessConfig * Process::status() is the same as run::process_status * Process::output() is the same as run::process_output * I/O for spawned tasks is now defaulted to captured in pipes instead of ignored * Process::kill() was added (plus an associated green/native implementation) * Process::wait_with_output() is the same as the old finish_with_output() * destroy() is now signal_exit() * force_destroy() is now signal_kill() Closes #2625 Closes #10016
Diffstat (limited to 'src/libnative/io/process.rs')
| -rw-r--r-- | src/libnative/io/process.rs | 98 |
1 files changed, 62 insertions, 36 deletions
diff --git a/src/libnative/io/process.rs b/src/libnative/io/process.rs index affa3ebf544..0b833f47395 100644 --- a/src/libnative/io/process.rs +++ b/src/libnative/io/process.rs @@ -66,18 +66,16 @@ impl Process { -> Result<(Process, ~[Option<file::FileDesc>]), io::IoError> { // right now we only handle stdin/stdout/stderr. - if config.io.len() > 3 { + if config.extra_io.len() > 0 { return Err(super::unimpl()); } - fn get_io(io: &[p::StdioContainer], - ret: &mut ~[Option<file::FileDesc>], - idx: uint) -> (Option<os::Pipe>, c_int) { - if idx >= io.len() { return (None, -1); } - ret.push(None); - match io[idx] { - p::Ignored => (None, -1), - p::InheritFd(fd) => (None, fd), + fn get_io(io: p::StdioContainer, ret: &mut ~[Option<file::FileDesc>]) + -> (Option<os::Pipe>, c_int) + { + match io { + p::Ignored => { ret.push(None); (None, -1) } + p::InheritFd(fd) => { ret.push(None); (None, fd) } p::CreatePipe(readable, _writable) => { let pipe = os::pipe(); let (theirs, ours) = if readable { @@ -85,16 +83,16 @@ impl Process { } else { (pipe.out, pipe.input) }; - ret[idx] = Some(file::FileDesc::new(ours, true)); + ret.push(Some(file::FileDesc::new(ours, true))); (Some(pipe), theirs) } } } let mut ret_io = ~[]; - let (in_pipe, in_fd) = get_io(config.io, &mut ret_io, 0); - let (out_pipe, out_fd) = get_io(config.io, &mut ret_io, 1); - let (err_pipe, err_fd) = get_io(config.io, &mut ret_io, 2); + let (in_pipe, in_fd) = get_io(config.stdin, &mut ret_io); + let (out_pipe, out_fd) = get_io(config.stdout, &mut ret_io); + let (err_pipe, err_fd) = get_io(config.stderr, &mut ret_io); let env = config.env.map(|a| a.to_owned()); let cwd = config.cwd.map(|a| Path::new(a)); @@ -115,6 +113,10 @@ impl Process { Err(e) => Err(e) } } + + pub fn kill(pid: libc::pid_t, signum: int) -> IoResult<()> { + unsafe { killpid(pid, signum) } + } } impl rtio::RtioProcess for Process { @@ -144,34 +146,58 @@ impl rtio::RtioProcess for Process { None => {} } return unsafe { killpid(self.pid, signum) }; + } +} - #[cfg(windows)] - unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> { - match signal { - io::process::PleaseExitSignal | io::process::MustDieSignal => { - let ret = libc::TerminateProcess(pid as libc::HANDLE, 1); - super::mkerr_winbool(ret) - } - _ => Err(io::IoError { +impl Drop for Process { + fn drop(&mut self) { + free_handle(self.handle); + } +} + +#[cfg(windows)] +unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> { + let handle = libc::OpenProcess(libc::PROCESS_TERMINATE | + libc::PROCESS_QUERY_INFORMATION, + libc::FALSE, pid as libc::DWORD); + if handle.is_null() { + return Err(super::last_error()) + } + let ret = match signal { + // test for existence on signal 0 + 0 => { + let mut status = 0; + let ret = libc::GetExitCodeProcess(handle, &mut status); + if ret == 0 { + Err(super::last_error()) + } else if status != libc::STILL_ACTIVE { + Err(io::IoError { kind: io::OtherIoError, - desc: "unsupported signal on windows", + desc: "process no longer alive", detail: None, }) + } else { + Ok(()) } } - - #[cfg(not(windows))] - unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> { - let r = libc::funcs::posix88::signal::kill(pid, signal as c_int); - super::mkerr_libc(r) + io::process::PleaseExitSignal | io::process::MustDieSignal => { + let ret = libc::TerminateProcess(handle, 1); + super::mkerr_winbool(ret) } - } + _ => Err(io::IoError { + kind: io::OtherIoError, + desc: "unsupported signal on windows", + detail: None, + }) + }; + let _ = libc::CloseHandle(handle); + return ret; } -impl Drop for Process { - fn drop(&mut self) { - free_handle(self.handle); - } +#[cfg(not(windows))] +unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> { + let r = libc::funcs::posix88::signal::kill(pid, signal as c_int); + super::mkerr_libc(r) } struct SpawnProcessResult { @@ -536,10 +562,10 @@ fn spawn_process_os(config: p::ProcessConfig, if !envp.is_null() { set_environ(envp); } - }); - with_argv(config.program, config.args, |argv| { - let _ = execvp(*argv, argv); - fail(&mut output); + with_argv(config.program, config.args, |argv| { + let _ = execvp(*argv, argv); + fail(&mut output); + }) }) } } |
