@@ -63,10 +63,22 @@ pub trait Program {
63
63
fn finish ( & mut self ) -> int ;
64
64
65
65
/**
66
- * Forcibly terminate the program. On Posix OSs SIGKILL will be sent
67
- * to the process. On Win32 TerminateProcess(..) will be called.
66
+ * Terminate the program, giving it a chance to clean itself up if
67
+ * this is supported by the operating system.
68
+ *
69
+ * On Posix OSs SIGTERM will be sent to the process. On Win32
70
+ * TerminateProcess(..) will be called.
68
71
*/
69
72
fn destroy ( & mut self ) ;
73
+
74
+ /**
75
+ * Terminate the program as soon as possible without giving it a
76
+ * chance to clean itself up.
77
+ *
78
+ * On Posix OSs SIGKILL will be sent to the process. On Win32
79
+ * TerminateProcess(..) will be called.
80
+ */
81
+ fn force_destroy ( & mut self ) ;
70
82
}
71
83
72
84
@@ -266,24 +278,30 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program {
266
278
return waitpid ( r. pid ) ;
267
279
}
268
280
269
- fn destroy_repr ( r : & mut ProgRepr ) {
270
- killpid ( r. pid ) ;
281
+ fn destroy_repr ( r : & mut ProgRepr , force : bool ) {
282
+ killpid ( r. pid , force ) ;
271
283
finish_repr ( & mut * r) ;
272
284
close_repr_outputs ( & mut * r) ;
273
285
274
286
#[ cfg( windows) ]
275
- fn killpid ( pid : pid_t ) {
287
+ fn killpid ( pid : pid_t , _force : bool ) {
276
288
unsafe {
277
289
libc:: funcs:: extra:: kernel32:: TerminateProcess (
278
290
cast:: transmute ( pid) , 1 ) ;
279
291
}
280
292
}
281
293
282
294
#[ cfg( unix) ]
283
- fn killpid ( pid : pid_t ) {
295
+ fn killpid ( pid : pid_t , force : bool ) {
296
+
297
+ let signal = if force {
298
+ libc:: consts:: os:: posix88:: SIGKILL
299
+ } else {
300
+ libc:: consts:: os:: posix88:: SIGTERM
301
+ } ;
302
+
284
303
unsafe {
285
- libc:: funcs:: posix88:: signal:: kill (
286
- pid, libc:: consts:: os:: posix88:: SIGKILL as c_int ) ;
304
+ libc:: funcs:: posix88:: signal:: kill ( pid, signal as c_int ) ;
287
305
}
288
306
}
289
307
}
@@ -321,7 +339,8 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program {
321
339
}
322
340
fn close_input ( & mut self ) { close_repr_input ( & mut self . r ) ; }
323
341
fn finish ( & mut self ) -> int { finish_repr ( & mut self . r ) }
324
- fn destroy ( & mut self ) { destroy_repr ( & mut self . r ) ; }
342
+ fn destroy ( & mut self ) { destroy_repr ( & mut self . r , false ) ; }
343
+ fn force_destroy ( & mut self ) { destroy_repr ( & mut self . r , true ) ; }
325
344
}
326
345
327
346
let mut repr = ProgRepr {
@@ -559,10 +578,9 @@ mod tests {
559
578
p. destroy ( ) ; // ...and nor should this (and nor should the destructor)
560
579
}
561
580
562
- #[ test]
563
581
#[ cfg( unix) ] // there is no way to sleep on windows from inside libcore...
564
- pub fn test_destroy_actually_kills ( ) {
565
- let path = Path ( "test/core-run-test-destroy-actually-kills.tmp" ) ;
582
+ pub fn test_destroy_actually_kills ( force : bool ) {
583
+ let path = Path ( fmt ! ( "test/core-run-test-destroy-actually-kills-%? .tmp" , force ) ) ;
566
584
567
585
os:: remove_file ( & path) ;
568
586
@@ -580,6 +598,17 @@ mod tests {
580
598
assert ! ( !path. exists( ) ) ;
581
599
}
582
600
601
+ #[ test]
602
+ #[ cfg( unix) ]
603
+ pub fn test_unforced_destroy_actually_kills ( ) {
604
+ test_destroy_actually_kills ( false ) ;
605
+ }
606
+
607
+ #[ test]
608
+ #[ cfg( unix) ]
609
+ pub fn test_forced_destroy_actually_kills ( ) {
610
+ test_destroy_actually_kills ( true ) ;
611
+ }
583
612
}
584
613
585
614
// Local Variables:
0 commit comments