@@ -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
391381fn read_all ( rd : @io:: Reader ) -> ~str {
0 commit comments