Skip to content

Commit e081c17

Browse files
garethgareth
gareth
authored and
gareth
committed
Fix a bug where calling p.destroy() on the result of calling
start_program(...) would cause a segfault when p went out of scope due to out_file/err_file being closed twice.
1 parent 44d4d6d commit e081c17

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

src/libcore/run.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,14 @@ fn with_dirp<T>(d: &Option<~str>,
172172
}
173173
}
174174

175+
/// helper function that closes non-NULL files and then makes them NULL
176+
priv unsafe fn fclose_and_null(f: &mut *libc::FILE) {
177+
if *f != 0 as *libc::FILE {
178+
libc::fclose(*f);
179+
*f = 0 as *libc::FILE;
180+
}
181+
}
182+
175183
/**
176184
* Spawns a process and waits for it to terminate
177185
*
@@ -249,8 +257,8 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program {
249257
fn destroy_repr(r: &mut ProgRepr) {
250258
unsafe {
251259
finish_repr(&mut *r);
252-
libc::fclose(r.out_file);
253-
libc::fclose(r.err_file);
260+
fclose_and_null(&mut r.out_file);
261+
fclose_and_null(&mut r.err_file);
254262
}
255263
}
256264
struct ProgRes {
@@ -507,6 +515,19 @@ mod tests {
507515
assert!(status == 1);
508516
}
509517

518+
#[test]
519+
pub fn test_destroy_once() {
520+
let mut p = run::start_program("echo", []);
521+
p.destroy(); // this shouldn't crash (and nor should the destructor)
522+
}
523+
524+
#[test]
525+
pub fn test_destroy_twice() {
526+
let mut p = run::start_program("echo", []);
527+
p.destroy(); // this shouldnt crash...
528+
p.destroy(); // ...and nor should this (and nor should the destructor)
529+
}
530+
510531
}
511532

512533
// Local Variables:

0 commit comments

Comments
 (0)