@@ -47,28 +47,117 @@ pub struct RunProgramResult {
47
47
handle : * ( ) ,
48
48
}
49
49
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
+
50
112
/// 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
+
52
135
/// 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 }
54
137
55
138
/// 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
+ }
57
142
58
143
/// 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
+ }
60
147
61
148
/// 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
+ }
63
152
64
153
/// 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 ( ) ; }
66
155
67
156
/**
68
157
* Waits for the child process to terminate. Closes the handle
69
158
* to stdin if necessary.
70
159
*/
71
- fn finish ( & mut self ) -> int ;
160
+ fn finish ( & mut self ) -> int { self . r . finish ( ) }
72
161
73
162
/**
74
163
* Terminate the program, giving it a chance to clean itself up if
@@ -77,7 +166,7 @@ pub trait Program {
77
166
* On Posix OSs SIGTERM will be sent to the process. On Win32
78
167
* TerminateProcess(..) will be called.
79
168
*/
80
- fn destroy ( & mut self ) ;
169
+ fn destroy ( & mut self ) { self . r . destroy ( false ) ; }
81
170
82
171
/**
83
172
* Terminate the program as soon as possible without giving it a
@@ -86,7 +175,7 @@ pub trait Program {
86
175
* On Posix OSs SIGKILL will be sent to the process. On Win32
87
176
* TerminateProcess(..) will be called.
88
177
*/
89
- fn force_destroy ( & mut self ) ;
178
+ fn force_destroy ( & mut self ) { self . r . destroy ( true ) ; }
90
179
}
91
180
92
181
@@ -248,9 +337,9 @@ pub fn run_program(prog: &str, args: &[~str]) -> int {
248
337
/**
249
338
* Spawns a process and returns a Program
250
339
*
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.
254
343
*
255
344
* # Arguments
256
345
*
@@ -259,9 +348,9 @@ pub fn run_program(prog: &str, args: &[~str]) -> int {
259
348
*
260
349
* # Return value
261
350
*
262
- * A class with a <program> field
351
+ * A <Program> object
263
352
*/
264
- pub fn start_program ( prog : & str , args : & [ ~str ] ) -> @ Program {
353
+ pub fn start_program ( prog : & str , args : & [ ~str ] ) -> Program {
265
354
let pipe_input = os:: pipe ( ) ;
266
355
let pipe_output = os:: pipe ( ) ;
267
356
let pipe_err = os:: pipe ( ) ;
@@ -277,105 +366,6 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program {
277
366
libc:: close ( pipe_err. out ) ;
278
367
}
279
368
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
-
379
369
let repr = ProgRepr {
380
370
pid : res. pid ,
381
371
handle : res. handle ,
@@ -385,7 +375,7 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program {
385
375
finished : false ,
386
376
} ;
387
377
388
- @ ProgRes ( repr) as @ Program
378
+ Program :: new ( repr)
389
379
}
390
380
391
381
fn read_all ( rd : @io:: Reader ) -> ~str {
0 commit comments