about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-09-04 10:33:42 +0000
committerbors <bors@rust-lang.org>2015-09-04 10:33:42 +0000
commit6f1014f3510f3c5cc2b524aa4cb18bf91c3fd50f (patch)
treee855c86773552140e5f2deca9ba37a4c20f153c6
parentb4de424e4175eefb4fda6e3ed634acfab3ec0daf (diff)
parent04c09f9466c57dca50c643c6099c0f9957d62220 (diff)
downloadrust-6f1014f3510f3c5cc2b524aa4cb18bf91c3fd50f.tar.gz
rust-6f1014f3510f3c5cc2b524aa4cb18bf91c3fd50f.zip
Auto merge of #28069 - alexcrichton:rt-atexit, r=brson
This adds a call to `rt::cleanup` on `process::exit` to make sure we clean up
after ourselves on the way out from Rust.

Closes #28065
-rw-r--r--src/libstd/process.rs1
-rw-r--r--src/libstd/rt/args.rs1
-rw-r--r--src/libstd/rt/at_exit_imp.rs4
-rw-r--r--src/libstd/rt/mod.rs20
-rw-r--r--src/test/run-pass/exit-flushes.rs25
5 files changed, 34 insertions, 17 deletions
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<Vec<Vec<u8>>> {
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: FnOnce() + Send + 'static>(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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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(), "");
+    }
+}