From e081c17805203b5e87073e2c766280a84b08e52c Mon Sep 17 00:00:00 2001 From: gareth Date: Sun, 31 Mar 2013 21:24:58 +0100 Subject: [PATCH] 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. --- src/libcore/run.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/libcore/run.rs b/src/libcore/run.rs index 98564beeba9..c6d79bd2ecd 100644 --- a/src/libcore/run.rs +++ b/src/libcore/run.rs @@ -172,6 +172,14 @@ fn with_dirp(d: &Option<~str>, } } +/// helper function that closes non-NULL files and then makes them NULL +priv unsafe fn fclose_and_null(f: &mut *libc::FILE) { + if *f != 0 as *libc::FILE { + libc::fclose(*f); + *f = 0 as *libc::FILE; + } +} + /** * Spawns a process and waits for it to terminate * @@ -249,8 +257,8 @@ pub fn start_program(prog: &str, args: &[~str]) -> @Program { fn destroy_repr(r: &mut ProgRepr) { unsafe { finish_repr(&mut *r); - libc::fclose(r.out_file); - libc::fclose(r.err_file); + fclose_and_null(&mut r.out_file); + fclose_and_null(&mut r.err_file); } } struct ProgRes { @@ -507,6 +515,19 @@ mod tests { assert!(status == 1); } + #[test] + pub fn test_destroy_once() { + let mut p = run::start_program("echo", []); + p.destroy(); // this shouldn't crash (and nor should the destructor) + } + + #[test] + pub fn test_destroy_twice() { + let mut p = run::start_program("echo", []); + p.destroy(); // this shouldnt crash... + p.destroy(); // ...and nor should this (and nor should the destructor) + } + } // Local Variables: