Skip to content

Commit 7b00921

Browse files
committed
libcore: convert the Program @-object to be a plain struct + impl.
Removes the dynamic @ indirection, and also converts the functions acting on `ProgRepr`s to methods.
1 parent 6c0a7c7 commit 7b00921

File tree

1 file changed

+104
-114
lines changed

1 file changed

+104
-114
lines changed

src/libcore/run.rs

+104-114
Original file line numberDiff line numberDiff line change
@@ -47,28 +47,117 @@ pub struct RunProgramResult {
4747
handle: *(),
4848
}
4949

50+
struct ProgRepr {
51+
pid: pid_t,
52+
handle: *(),
53+
in_fd: c_int,
54+
out_file: *libc::FILE,
55+
err_file: *libc::FILE,
56+
finished: bool,
57+
}
58+
59+
impl ProgRepr {
60+
fn close_input(&mut self) {
61+
let invalid_fd = -1i32;
62+
if self.in_fd != invalid_fd {
63+
unsafe {
64+
libc::close(self.in_fd);
65+
}
66+
self.in_fd = invalid_fd;
67+
}
68+
}
69+
70+
fn close_outputs(&mut self) {
71+
unsafe {
72+
fclose_and_null(&mut self.out_file);
73+
fclose_and_null(&mut self.err_file);
74+
}
75+
}
76+
77+
fn finish(&mut self) -> int {
78+
if self.finished { return 0; }
79+
self.finished = true;
80+
self.close_input();
81+
return waitpid(self.pid);
82+
}
83+
84+
fn destroy(&mut self, force: bool) {
85+
killpid(self.pid, force);
86+
self.finish();
87+
self.close_outputs();
88+
89+
#[cfg(windows)]
90+
fn killpid(pid: pid_t, _force: bool) {
91+
unsafe {
92+
libc::funcs::extra::kernel32::TerminateProcess(
93+
cast::transmute(pid), 1);
94+
}
95+
}
96+
97+
#[cfg(unix)]
98+
fn killpid(pid: pid_t, force: bool) {
99+
let signal = if force {
100+
libc::consts::os::posix88::SIGKILL
101+
} else {
102+
libc::consts::os::posix88::SIGTERM
103+
};
104+
105+
unsafe {
106+
libc::funcs::posix88::signal::kill(pid, signal as c_int);
107+
}
108+
}
109+
}
110+
}
111+
50112
/// A value representing a child process
51-
pub trait Program {
113+
pub struct Program {
114+
priv r: ProgRepr,
115+
}
116+
117+
impl Drop for Program {
118+
fn finalize(&self) {
119+
// FIXME #4943: transmute is bad.
120+
let selfr: &mut ProgRepr = unsafe { cast::transmute(&self.r) };
121+
122+
selfr.finish();
123+
selfr.close_outputs();
124+
free_handle(self.r.handle);
125+
}
126+
}
127+
128+
pub impl Program {
129+
priv fn new(r: ProgRepr) -> Program {
130+
Program {
131+
r: r
132+
}
133+
}
134+
52135
/// Returns the process id of the program
53-
fn get_id(&mut self) -> pid_t;
136+
fn get_id(&mut self) -> pid_t { self.r.pid }
54137

55138
/// Returns an io::Writer that can be used to write to stdin
56-
fn input(&mut self) -> @io::Writer;
139+
fn input(&mut self) -> @io::Writer {
140+
io::fd_writer(self.r.in_fd, false)
141+
}
57142

58143
/// Returns an io::Reader that can be used to read from stdout
59-
fn output(&mut self) -> @io::Reader;
144+
fn output(&mut self) -> @io::Reader {
145+
io::FILE_reader(self.r.out_file, false)
146+
}
60147

61148
/// Returns an io::Reader that can be used to read from stderr
62-
fn err(&mut self) -> @io::Reader;
149+
fn err(&mut self) -> @io::Reader {
150+
io::FILE_reader(self.r.err_file, false)
151+
}
63152

64153
/// Closes the handle to the child processes standard input
65-
fn close_input(&mut self);
154+
fn close_input(&mut self) { self.r.close_input(); }
66155

67156
/**
68157
* Waits for the child process to terminate. Closes the handle
69158
* to stdin if necessary.
70159
*/
71-
fn finish(&mut self) -> int;
160+
fn finish(&mut self) -> int { self.r.finish() }
72161

73162
/**
74163
* Terminate the program, giving it a chance to clean itself up if
@@ -77,7 +166,7 @@ pub trait Program {
77166
* On Posix OSs SIGTERM will be sent to the process. On Win32
78167
* TerminateProcess(..) will be called.
79168
*/
80-
fn destroy(&mut self);
169+
fn destroy(&mut self) { self.r.destroy(false); }
81170

82171
/**
83172
* Terminate the program as soon as possible without giving it a
@@ -86,7 +175,7 @@ pub trait Program {
86175
* On Posix OSs SIGKILL will be sent to the process. On Win32
87176
* TerminateProcess(..) will be called.
88177
*/
89-
fn force_destroy(&mut self);
178+
fn force_destroy(&mut self) { self.r.destroy(true); }
90179
}
91180

92181

@@ -248,9 +337,9 @@ pub fn run_program(prog: &str, args: &[~str]) -> int {
248337
/**
249338
* Spawns a process and returns a Program
250339
*
251-
* The returned value is a boxed class containing a <Program> object that can
252-
* be used for sending and receiving data over the standard file descriptors.
253-
* The class will ensure that file descriptors are closed properly.
340+
* The returned value is a <Program> object that can be used for sending and
341+
* receiving data over the standard file descriptors. The class will ensure
342+
* that file descriptors are closed properly.
254343
*
255344
* # Arguments
256345
*
@@ -259,9 +348,9 @@ pub fn run_program(prog: &str, args: &[~str]) -> int {
259348
*
260349
* # Return value
261350
*
262-
* A class with a <program> field
351+
* A <Program> object
263352
*/
264-
pub fn start_program(prog: &str, args: &[~str]) -> @Program {
353+
pub fn start_program(prog: &str, args: &[~str]) -> Program {
265354
let pipe_input = os::pipe();
266355
let pipe_output = os::pipe();
267356
let pipe_err = os::pipe();
@@ -277,105 +366,6 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program {
277366
libc::close(pipe_err.out);
278367
}
279368

280-
struct ProgRepr {
281-
pid: pid_t,
282-
handle: *(),
283-
in_fd: c_int,
284-
out_file: *libc::FILE,
285-
err_file: *libc::FILE,
286-
finished: bool,
287-
}
288-
289-
fn close_repr_input(r: &mut ProgRepr) {
290-
let invalid_fd = -1i32;
291-
if r.in_fd != invalid_fd {
292-
unsafe {
293-
libc::close(r.in_fd);
294-
}
295-
r.in_fd = invalid_fd;
296-
}
297-
}
298-
299-
fn close_repr_outputs(r: &mut ProgRepr) {
300-
unsafe {
301-
fclose_and_null(&mut r.out_file);
302-
fclose_and_null(&mut r.err_file);
303-
}
304-
}
305-
306-
fn finish_repr(r: &mut ProgRepr) -> int {
307-
if r.finished { return 0; }
308-
r.finished = true;
309-
close_repr_input(&mut *r);
310-
return waitpid(r.pid);
311-
}
312-
313-
fn destroy_repr(r: &mut ProgRepr, force: bool) {
314-
killpid(r.pid, force);
315-
finish_repr(&mut *r);
316-
close_repr_outputs(&mut *r);
317-
318-
#[cfg(windows)]
319-
fn killpid(pid: pid_t, _force: bool) {
320-
unsafe {
321-
libc::funcs::extra::kernel32::TerminateProcess(
322-
cast::transmute(pid), 1);
323-
}
324-
}
325-
326-
#[cfg(unix)]
327-
fn killpid(pid: pid_t, force: bool) {
328-
329-
let signal = if force {
330-
libc::consts::os::posix88::SIGKILL
331-
} else {
332-
libc::consts::os::posix88::SIGTERM
333-
};
334-
335-
unsafe {
336-
libc::funcs::posix88::signal::kill(pid, signal as c_int);
337-
}
338-
}
339-
}
340-
341-
struct ProgRes {
342-
r: ProgRepr,
343-
}
344-
345-
impl Drop for ProgRes {
346-
fn finalize(&self) {
347-
unsafe {
348-
// FIXME #4943: transmute is bad.
349-
finish_repr(cast::transmute(&self.r));
350-
close_repr_outputs(cast::transmute(&self.r));
351-
}
352-
free_handle(self.r.handle);
353-
}
354-
}
355-
356-
fn ProgRes(r: ProgRepr) -> ProgRes {
357-
ProgRes {
358-
r: r
359-
}
360-
}
361-
362-
impl Program for ProgRes {
363-
fn get_id(&mut self) -> pid_t { return self.r.pid; }
364-
fn input(&mut self) -> @io::Writer {
365-
io::fd_writer(self.r.in_fd, false)
366-
}
367-
fn output(&mut self) -> @io::Reader {
368-
io::FILE_reader(self.r.out_file, false)
369-
}
370-
fn err(&mut self) -> @io::Reader {
371-
io::FILE_reader(self.r.err_file, false)
372-
}
373-
fn close_input(&mut self) { close_repr_input(&mut self.r); }
374-
fn finish(&mut self) -> int { finish_repr(&mut self.r) }
375-
fn destroy(&mut self) { destroy_repr(&mut self.r, false); }
376-
fn force_destroy(&mut self) { destroy_repr(&mut self.r, true); }
377-
}
378-
379369
let repr = ProgRepr {
380370
pid: res.pid,
381371
handle: res.handle,
@@ -385,7 +375,7 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program {
385375
finished: false,
386376
};
387377

388-
@ProgRes(repr) as @Program
378+
Program::new(repr)
389379
}
390380

391381
fn read_all(rd: @io::Reader) -> ~str {

0 commit comments

Comments
 (0)