Skip to content

Commit a5342d5

Browse files
committed
auto merge of #12380 : alexcrichton/rust/run-rewrite, r=brson
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
2 parents 3c2650b + a9bd447 commit a5342d5

24 files changed

+674
-817
lines changed

src/compiletest/procsrv.rs

+15-12
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@
99
// except according to those terms.
1010

1111
use std::os;
12-
use std::run;
1312
use std::str;
14-
use std::io::process::ProcessExit;
13+
use std::io::process::{ProcessExit, Process, ProcessConfig, ProcessOutput};
1514

1615
#[cfg(target_os = "win32")]
1716
fn target_env(lib_path: &str, prog: &str) -> ~[(~str,~str)] {
@@ -49,17 +48,19 @@ pub fn run(lib_path: &str,
4948
input: Option<~str>) -> Option<Result> {
5049

5150
let env = env + target_env(lib_path, prog);
52-
let mut opt_process = run::Process::new(prog, args, run::ProcessOptions {
53-
env: Some(env),
54-
.. run::ProcessOptions::new()
51+
let mut opt_process = Process::configure(ProcessConfig {
52+
program: prog,
53+
args: args,
54+
env: Some(env.as_slice()),
55+
.. ProcessConfig::new()
5556
});
5657

5758
match opt_process {
5859
Ok(ref mut process) => {
5960
for input in input.iter() {
60-
process.input().write(input.as_bytes()).unwrap();
61+
process.stdin.get_mut_ref().write(input.as_bytes()).unwrap();
6162
}
62-
let run::ProcessOutput { status, output, error } = process.finish_with_output();
63+
let ProcessOutput { status, output, error } = process.wait_with_output();
6364

6465
Some(Result {
6566
status: status,
@@ -75,18 +76,20 @@ pub fn run_background(lib_path: &str,
7576
prog: &str,
7677
args: &[~str],
7778
env: ~[(~str, ~str)],
78-
input: Option<~str>) -> Option<run::Process> {
79+
input: Option<~str>) -> Option<Process> {
7980

8081
let env = env + target_env(lib_path, prog);
81-
let opt_process = run::Process::new(prog, args, run::ProcessOptions {
82-
env: Some(env),
83-
.. run::ProcessOptions::new()
82+
let opt_process = Process::configure(ProcessConfig {
83+
program: prog,
84+
args: args,
85+
env: Some(env.as_slice()),
86+
.. ProcessConfig::new()
8487
});
8588

8689
match opt_process {
8790
Ok(mut process) => {
8891
for input in input.iter() {
89-
process.input().write(input.as_bytes()).unwrap();
92+
process.stdin.get_mut_ref().write(input.as_bytes()).unwrap();
9093
}
9194

9295
Some(process)

src/compiletest/runtest.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ fn run_debuginfo_test(config: &config, props: &TestProps, testfile: &Path) {
360360
stdout: out,
361361
stderr: err,
362362
cmdline: cmdline};
363-
process.force_destroy().unwrap();
363+
process.signal_kill().unwrap();
364364
}
365365

366366
_=> {

src/libextra/workcache.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -464,8 +464,8 @@ impl<'a, T:Send +
464464
#[test]
465465
#[cfg(not(target_os="android"))] // FIXME(#10455)
466466
fn test() {
467-
use std::{os, run};
468-
use std::io::fs;
467+
use std::os;
468+
use std::io::{fs, Process};
469469
use std::str::from_utf8_owned;
470470

471471
// Create a path to a new file 'filename' in the directory in which
@@ -499,9 +499,9 @@ fn test() {
499499
prep.exec(proc(_exe) {
500500
let out = make_path(~"foo.o");
501501
// FIXME (#9639): This needs to handle non-utf8 paths
502-
run::process_status("gcc", [pth.as_str().unwrap().to_owned(),
503-
~"-o",
504-
out.as_str().unwrap().to_owned()]).unwrap();
502+
Process::status("gcc", [pth.as_str().unwrap().to_owned(),
503+
~"-o",
504+
out.as_str().unwrap().to_owned()]).unwrap();
505505

506506
let _proof_of_concept = subcx.prep("subfn");
507507
// Could run sub-rules inside here.

src/libnative/io/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,9 @@ impl rtio::IoFactory for IoFactory {
287287
io.move_iter().map(|p| p.map(|p| ~p as ~RtioPipe)).collect())
288288
})
289289
}
290+
fn kill(&mut self, pid: libc::pid_t, signum: int) -> IoResult<()> {
291+
process::Process::kill(pid, signum)
292+
}
290293
fn pipe_open(&mut self, fd: c_int) -> IoResult<~RtioPipe> {
291294
Ok(~file::FileDesc::new(fd, true) as ~RtioPipe)
292295
}

src/libnative/io/process.rs

+62-36
Original file line numberDiff line numberDiff line change
@@ -66,35 +66,33 @@ impl Process {
6666
-> Result<(Process, ~[Option<file::FileDesc>]), io::IoError>
6767
{
6868
// right now we only handle stdin/stdout/stderr.
69-
if config.io.len() > 3 {
69+
if config.extra_io.len() > 0 {
7070
return Err(super::unimpl());
7171
}
7272

73-
fn get_io(io: &[p::StdioContainer],
74-
ret: &mut ~[Option<file::FileDesc>],
75-
idx: uint) -> (Option<os::Pipe>, c_int) {
76-
if idx >= io.len() { return (None, -1); }
77-
ret.push(None);
78-
match io[idx] {
79-
p::Ignored => (None, -1),
80-
p::InheritFd(fd) => (None, fd),
73+
fn get_io(io: p::StdioContainer, ret: &mut ~[Option<file::FileDesc>])
74+
-> (Option<os::Pipe>, c_int)
75+
{
76+
match io {
77+
p::Ignored => { ret.push(None); (None, -1) }
78+
p::InheritFd(fd) => { ret.push(None); (None, fd) }
8179
p::CreatePipe(readable, _writable) => {
8280
let pipe = os::pipe();
8381
let (theirs, ours) = if readable {
8482
(pipe.input, pipe.out)
8583
} else {
8684
(pipe.out, pipe.input)
8785
};
88-
ret[idx] = Some(file::FileDesc::new(ours, true));
86+
ret.push(Some(file::FileDesc::new(ours, true)));
8987
(Some(pipe), theirs)
9088
}
9189
}
9290
}
9391

9492
let mut ret_io = ~[];
95-
let (in_pipe, in_fd) = get_io(config.io, &mut ret_io, 0);
96-
let (out_pipe, out_fd) = get_io(config.io, &mut ret_io, 1);
97-
let (err_pipe, err_fd) = get_io(config.io, &mut ret_io, 2);
93+
let (in_pipe, in_fd) = get_io(config.stdin, &mut ret_io);
94+
let (out_pipe, out_fd) = get_io(config.stdout, &mut ret_io);
95+
let (err_pipe, err_fd) = get_io(config.stderr, &mut ret_io);
9896

9997
let env = config.env.map(|a| a.to_owned());
10098
let cwd = config.cwd.map(|a| Path::new(a));
@@ -115,6 +113,10 @@ impl Process {
115113
Err(e) => Err(e)
116114
}
117115
}
116+
117+
pub fn kill(pid: libc::pid_t, signum: int) -> IoResult<()> {
118+
unsafe { killpid(pid, signum) }
119+
}
118120
}
119121

120122
impl rtio::RtioProcess for Process {
@@ -144,34 +146,58 @@ impl rtio::RtioProcess for Process {
144146
None => {}
145147
}
146148
return unsafe { killpid(self.pid, signum) };
149+
}
150+
}
147151

148-
#[cfg(windows)]
149-
unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> {
150-
match signal {
151-
io::process::PleaseExitSignal | io::process::MustDieSignal => {
152-
let ret = libc::TerminateProcess(pid as libc::HANDLE, 1);
153-
super::mkerr_winbool(ret)
154-
}
155-
_ => Err(io::IoError {
152+
impl Drop for Process {
153+
fn drop(&mut self) {
154+
free_handle(self.handle);
155+
}
156+
}
157+
158+
#[cfg(windows)]
159+
unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> {
160+
let handle = libc::OpenProcess(libc::PROCESS_TERMINATE |
161+
libc::PROCESS_QUERY_INFORMATION,
162+
libc::FALSE, pid as libc::DWORD);
163+
if handle.is_null() {
164+
return Err(super::last_error())
165+
}
166+
let ret = match signal {
167+
// test for existence on signal 0
168+
0 => {
169+
let mut status = 0;
170+
let ret = libc::GetExitCodeProcess(handle, &mut status);
171+
if ret == 0 {
172+
Err(super::last_error())
173+
} else if status != libc::STILL_ACTIVE {
174+
Err(io::IoError {
156175
kind: io::OtherIoError,
157-
desc: "unsupported signal on windows",
176+
desc: "process no longer alive",
158177
detail: None,
159178
})
179+
} else {
180+
Ok(())
160181
}
161182
}
162-
163-
#[cfg(not(windows))]
164-
unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> {
165-
let r = libc::funcs::posix88::signal::kill(pid, signal as c_int);
166-
super::mkerr_libc(r)
183+
io::process::PleaseExitSignal | io::process::MustDieSignal => {
184+
let ret = libc::TerminateProcess(handle, 1);
185+
super::mkerr_winbool(ret)
167186
}
168-
}
187+
_ => Err(io::IoError {
188+
kind: io::OtherIoError,
189+
desc: "unsupported signal on windows",
190+
detail: None,
191+
})
192+
};
193+
let _ = libc::CloseHandle(handle);
194+
return ret;
169195
}
170196

171-
impl Drop for Process {
172-
fn drop(&mut self) {
173-
free_handle(self.handle);
174-
}
197+
#[cfg(not(windows))]
198+
unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> {
199+
let r = libc::funcs::posix88::signal::kill(pid, signal as c_int);
200+
super::mkerr_libc(r)
175201
}
176202

177203
struct SpawnProcessResult {
@@ -536,10 +562,10 @@ fn spawn_process_os(config: p::ProcessConfig,
536562
if !envp.is_null() {
537563
set_environ(envp);
538564
}
539-
});
540-
with_argv(config.program, config.args, |argv| {
541-
let _ = execvp(*argv, argv);
542-
fail(&mut output);
565+
with_argv(config.program, config.args, |argv| {
566+
let _ = execvp(*argv, argv);
567+
fail(&mut output);
568+
})
543569
})
544570
}
545571
}

src/librustc/back/archive.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::io::fs;
2020
use std::io;
2121
use std::libc;
2222
use std::os;
23-
use std::run::{ProcessOptions, Process, ProcessOutput};
23+
use std::io::process::{ProcessConfig, Process, ProcessOutput};
2424
use std::str;
2525
use std::raw;
2626
use extra::tempfile::TempDir;
@@ -44,16 +44,19 @@ fn run_ar(sess: Session, args: &str, cwd: Option<&Path>,
4444
let mut args = ~[args.to_owned()];
4545
let mut paths = paths.iter().map(|p| p.as_str().unwrap().to_owned());
4646
args.extend(&mut paths);
47-
let mut opts = ProcessOptions::new();
48-
opts.dir = cwd;
4947
debug!("{} {}", ar, args.connect(" "));
5048
match cwd {
5149
Some(p) => { debug!("inside {}", p.display()); }
5250
None => {}
5351
}
54-
match Process::new(ar, args.as_slice(), opts) {
52+
match Process::configure(ProcessConfig {
53+
program: ar.as_slice(),
54+
args: args.as_slice(),
55+
cwd: cwd.map(|a| &*a),
56+
.. ProcessConfig::new()
57+
}) {
5558
Ok(mut prog) => {
56-
let o = prog.finish_with_output();
59+
let o = prog.wait_with_output();
5760
if !o.status.success() {
5861
sess.err(format!("{} {} failed with: {}", ar, args.connect(" "),
5962
o.status));

src/librustc/back/link.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ use std::c_str::ToCStr;
3030
use std::char;
3131
use std::os::consts::{macos, freebsd, linux, android, win32};
3232
use std::ptr;
33-
use std::run;
3433
use std::str;
3534
use std::io;
35+
use std::io::Process;
3636
use std::io::fs;
3737
use flate;
3838
use serialize::hex::ToHex;
@@ -101,8 +101,8 @@ pub mod write {
101101
use syntax::abi;
102102

103103
use std::c_str::ToCStr;
104+
use std::io::Process;
104105
use std::libc::{c_uint, c_int};
105-
use std::run;
106106
use std::str;
107107

108108
// On android, we by default compile for armv7 processors. This enables
@@ -333,7 +333,7 @@ pub mod write {
333333
assembly.as_str().unwrap().to_owned()];
334334

335335
debug!("{} '{}'", cc, args.connect("' '"));
336-
match run::process_output(cc, args) {
336+
match Process::output(cc, args) {
337337
Ok(prog) => {
338338
if !prog.status.success() {
339339
sess.err(format!("linking with `{}` failed: {}", cc, prog.status));
@@ -1033,7 +1033,7 @@ fn link_natively(sess: Session, dylib: bool, obj_filename: &Path,
10331033
// Invoke the system linker
10341034
debug!("{} {}", cc_prog, cc_args.connect(" "));
10351035
let prog = time(sess.time_passes(), "running linker", (), |()|
1036-
run::process_output(cc_prog, cc_args));
1036+
Process::output(cc_prog, cc_args));
10371037
match prog {
10381038
Ok(prog) => {
10391039
if !prog.status.success() {
@@ -1054,7 +1054,7 @@ fn link_natively(sess: Session, dylib: bool, obj_filename: &Path,
10541054
// the symbols
10551055
if sess.targ_cfg.os == abi::OsMacos && sess.opts.debuginfo {
10561056
// FIXME (#9639): This needs to handle non-utf8 paths
1057-
match run::process_status("dsymutil",
1057+
match Process::status("dsymutil",
10581058
[out_filename.as_str().unwrap().to_owned()]) {
10591059
Ok(..) => {}
10601060
Err(e) => {

src/librustdoc/test.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
// except according to those terms.
1010

1111
use std::cell::RefCell;
12-
use collections::HashSet;
12+
use std::io::Process;
1313
use std::local_data;
1414
use std::os;
15-
use std::run;
1615
use std::str;
1716

17+
use collections::HashSet;
1818
use testing;
1919
use extra::tempfile::TempDir;
2020
use rustc::back::link;
@@ -126,7 +126,7 @@ fn runtest(test: &str, cratename: &str, libs: HashSet<Path>, should_fail: bool)
126126
driver::compile_input(sess, cfg, &input, &out, &None);
127127

128128
let exe = outdir.path().join("rust_out");
129-
let out = run::process_output(exe.as_str().unwrap(), []);
129+
let out = Process::output(exe.as_str().unwrap(), []);
130130
match out {
131131
Err(e) => fail!("couldn't run the test: {}", e),
132132
Ok(out) => {

src/librustuv/process.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ impl Process {
4444
-> Result<(~Process, ~[Option<PipeWatcher>]), UvError>
4545
{
4646
let cwd = config.cwd.map(|s| s.to_c_str());
47-
let io = config.io;
47+
let mut io = ~[config.stdin, config.stdout, config.stderr];
48+
for slot in config.extra_io.iter() {
49+
io.push(*slot);
50+
}
4851
let mut stdio = vec::with_capacity::<uvll::uv_stdio_container_t>(io.len());
4952
let mut ret_io = vec::with_capacity(io.len());
5053
unsafe {
@@ -105,6 +108,15 @@ impl Process {
105108
Err(e) => Err(e),
106109
}
107110
}
111+
112+
pub fn kill(pid: libc::pid_t, signum: int) -> Result<(), UvError> {
113+
match unsafe {
114+
uvll::uv_kill(pid as libc::c_int, signum as libc::c_int)
115+
} {
116+
0 => Ok(()),
117+
n => Err(UvError(n))
118+
}
119+
}
108120
}
109121

110122
extern fn on_exit(handle: *uvll::uv_process_t,

src/librustuv/uvio.rs

+4
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ impl IoFactory for UvIoFactory {
277277
}
278278
}
279279

280+
fn kill(&mut self, pid: libc::pid_t, signum: int) -> Result<(), IoError> {
281+
Process::kill(pid, signum).map_err(uv_error_to_io_error)
282+
}
283+
280284
fn unix_bind(&mut self, path: &CString) -> Result<~rtio::RtioUnixListener, IoError>
281285
{
282286
match PipeListener::bind(self, path) {

0 commit comments

Comments
 (0)