diff --git a/src/libstd/process.rs b/src/libstd/process.rs index be921d9aef0..79f2d16fef4 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -582,6 +582,7 @@ impl Child { /// to run. #[stable(feature = "rust1", since = "1.0.0")] pub fn exit(code: i32) -> ! { + ::rt::cleanup(); ::sys::os::exit(code) } diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index cf8bac31057..8de713aeac8 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -64,7 +64,6 @@ mod imp { pub unsafe fn cleanup() { take(); - LOCK.destroy(); } pub fn take() -> Option>> { diff --git a/src/libstd/rt/at_exit_imp.rs b/src/libstd/rt/at_exit_imp.rs index 54e5b499e53..379c86eb2a0 100644 --- a/src/libstd/rt/at_exit_imp.rs +++ b/src/libstd/rt/at_exit_imp.rs @@ -12,10 +12,6 @@ //! //! Documentation can be found on the `rt::at_exit` function. -// FIXME: switch this to use atexit. Currently this -// segfaults (the queue's memory is mysteriously gone), so -// instead the cleanup is tied to the `std::rt` entry point. - use alloc::boxed::FnBox; use boxed::Box; use ptr; diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 5464e7f9d89..2cbf81b2fc7 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -23,6 +23,7 @@ #![allow(missing_docs)] use prelude::v1::*; +use sync::Once; use sys; use thread; @@ -124,16 +125,11 @@ pub fn at_exit(f: F) -> Result<(), ()> { } /// One-time runtime cleanup. -/// -/// This function is unsafe because it performs no checks to ensure that the -/// runtime has completely ceased running. It is the responsibility of the -/// caller to ensure that the runtime is entirely shut down and nothing will be -/// poking around at the internal components. -/// -/// Invoking cleanup while portions of the runtime are still in use may cause -/// undefined behavior. -pub unsafe fn cleanup() { - args::cleanup(); - sys::stack_overflow::cleanup(); - at_exit_imp::cleanup(); +pub fn cleanup() { + static CLEANUP: Once = Once::new(); + CLEANUP.call_once(|| unsafe { + args::cleanup(); + sys::stack_overflow::cleanup(); + at_exit_imp::cleanup(); + }); } diff --git a/src/test/run-pass/exit-flushes.rs b/src/test/run-pass/exit-flushes.rs new file mode 100644 index 00000000000..76ecbfd2f22 --- /dev/null +++ b/src/test/run-pass/exit-flushes.rs @@ -0,0 +1,25 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::env; +use std::process::{exit, Command}; + +fn main() { + if env::args().len() > 1 { + print!("hello!"); + exit(0); + } else { + let out = Command::new(env::args().next().unwrap()).arg("foo") + .output().unwrap(); + assert!(out.status.success()); + assert_eq!(String::from_utf8(out.stdout).unwrap(), "hello!"); + assert_eq!(String::from_utf8(out.stderr).unwrap(), ""); + } +}