about summary refs log tree commit diff
path: root/library/std/src/sys
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-04-25 04:45:39 +0000
committerbors <bors@rust-lang.org>2021-04-25 04:45:39 +0000
commit5da10c01214a3d3ebec65b8ba6effada92a0673f (patch)
tree94bbe380b059b6f77025a1e7c8d290f62390998e /library/std/src/sys
parentf7c468fe9a1448b1f6ceee6a4c831fe6122a54f0 (diff)
parent7171fec13f3a3091f702a8e55f495ad1563dc4cd (diff)
downloadrust-5da10c01214a3d3ebec65b8ba6effada92a0673f.tar.gz
rust-5da10c01214a3d3ebec65b8ba6effada92a0673f.zip
Auto merge of #84115 - CDirkx:rt, r=m-ou-se
Rework `init` and `cleanup`

This PR reworks the code in `std` that runs before and after `main` and centralizes this code respectively in the functions `init` and `cleanup` in both `sys_common` and `sys`. This makes is easy to see what code is executed during initialization and cleanup on each platform just by looking at e.g. `sys::windows::init`.

Full list of changes:
- new module `rt` in `sys_common` to contain `init` and `cleanup` and the runtime macros.
- `at_exit` and the mechanism to register exit handlers has been completely removed. In practice this was only used for closing sockets on windows and flushing stdout, which have been moved to `cleanup`.
- <s>On windows `alloc` and `net` initialization is now done in `init`, this saves a runtime check in every allocation and network use.</s>
Diffstat (limited to 'library/std/src/sys')
-rw-r--r--library/std/src/sys/hermit/mod.rs13
-rw-r--r--library/std/src/sys/hermit/stack_overflow.rs5
-rw-r--r--library/std/src/sys/sgx/args.rs2
-rw-r--r--library/std/src/sys/sgx/mod.rs14
-rw-r--r--library/std/src/sys/sgx/stack_overflow.rs4
-rw-r--r--library/std/src/sys/unix/mod.rs62
-rw-r--r--library/std/src/sys/unsupported/args.rs3
-rw-r--r--library/std/src/sys/unsupported/common.rs9
-rw-r--r--library/std/src/sys/unsupported/mod.rs1
-rw-r--r--library/std/src/sys/unsupported/stack_overflow.rs3
-rw-r--r--library/std/src/sys/wasi/args.rs4
-rw-r--r--library/std/src/sys/wasi/mod.rs2
-rw-r--r--library/std/src/sys/wasm/args.rs6
-rw-r--r--library/std/src/sys/wasm/mod.rs2
-rw-r--r--library/std/src/sys/windows/args.rs4
-rw-r--r--library/std/src/sys/windows/mod.rs13
-rw-r--r--library/std/src/sys/windows/net.rs19
-rw-r--r--library/std/src/sys/windows/stack_overflow.rs2
-rw-r--r--library/std/src/sys/windows/stack_overflow_uwp.rs2
19 files changed, 81 insertions, 89 deletions
diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs
index 56497162c03..a70d1db7ca6 100644
--- a/library/std/src/sys/hermit/mod.rs
+++ b/library/std/src/sys/hermit/mod.rs
@@ -37,7 +37,6 @@ pub mod pipe;
 #[path = "../unsupported/process.rs"]
 pub mod process;
 pub mod rwlock;
-pub mod stack_overflow;
 pub mod stdio;
 pub mod thread;
 pub mod thread_local_dtor;
@@ -96,9 +95,17 @@ pub extern "C" fn __rust_abort() {
     abort_internal();
 }
 
-#[cfg(not(test))]
-pub fn init() {
+// SAFETY: must be called only once during runtime initialization.
+// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
+pub unsafe fn init(argc: isize, argv: *const *const u8) {
     let _ = net::init();
+    args::init(argc, argv);
+}
+
+// SAFETY: must be called only once during runtime cleanup.
+// NOTE: this is not guaranteed to run, for example when the program aborts.
+pub unsafe fn cleanup() {
+    args::cleanup();
 }
 
 #[cfg(not(test))]
diff --git a/library/std/src/sys/hermit/stack_overflow.rs b/library/std/src/sys/hermit/stack_overflow.rs
deleted file mode 100644
index 121fe42011d..00000000000
--- a/library/std/src/sys/hermit/stack_overflow.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#[inline]
-pub unsafe fn init() {}
-
-#[inline]
-pub unsafe fn cleanup() {}
diff --git a/library/std/src/sys/sgx/args.rs b/library/std/src/sys/sgx/args.rs
index 463188ad7c0..ef4176c4ac0 100644
--- a/library/std/src/sys/sgx/args.rs
+++ b/library/std/src/sys/sgx/args.rs
@@ -23,8 +23,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
     }
 }
 
-pub unsafe fn cleanup() {}
-
 pub fn args() -> Args {
     let args = unsafe { (ARGS.load(Ordering::Relaxed) as *const ArgsStore).as_ref() };
     if let Some(args) = args { Args(args.iter()) } else { Args([].iter()) }
diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs
index d6a56830733..059d6cb5ba1 100644
--- a/library/std/src/sys/sgx/mod.rs
+++ b/library/std/src/sys/sgx/mod.rs
@@ -32,7 +32,6 @@ pub mod pipe;
 #[path = "../unsupported/process.rs"]
 pub mod process;
 pub mod rwlock;
-pub mod stack_overflow;
 pub mod stdio;
 pub mod thread;
 pub mod thread_local_key;
@@ -40,8 +39,17 @@ pub mod time;
 
 pub use crate::sys_common::os_str_bytes as os_str;
 
-#[cfg(not(test))]
-pub fn init() {}
+// SAFETY: must be called only once during runtime initialization.
+// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
+pub unsafe fn init(argc: isize, argv: *const *const u8) {
+    unsafe {
+        args::init(argc, argv);
+    }
+}
+
+// SAFETY: must be called only once during runtime cleanup.
+// NOTE: this is not guaranteed to run, for example when the program aborts.
+pub unsafe fn cleanup() {}
 
 /// This function is used to implement functionality that simply doesn't exist.
 /// Programs relying on this functionality will need to deal with the error.
diff --git a/library/std/src/sys/sgx/stack_overflow.rs b/library/std/src/sys/sgx/stack_overflow.rs
deleted file mode 100644
index b96652a8330..00000000000
--- a/library/std/src/sys/sgx/stack_overflow.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-#[cfg_attr(test, allow(dead_code))]
-pub unsafe fn init() {}
-
-pub unsafe fn cleanup() {}
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index 1316835a89d..a0ee69c2f72 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -44,14 +44,13 @@ pub mod time;
 
 pub use crate::sys_common::os_str_bytes as os_str;
 
-#[cfg(not(test))]
-pub fn init() {
+// SAFETY: must be called only once during runtime initialization.
+// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
+pub unsafe fn init(argc: isize, argv: *const *const u8) {
     // The standard streams might be closed on application startup. To prevent
     // std::io::{stdin, stdout,stderr} objects from using other unrelated file
     // resources opened later, we reopen standards streams when they are closed.
-    unsafe {
-        sanitize_standard_fds();
-    }
+    sanitize_standard_fds();
 
     // By default, some platforms will send a *signal* when an EPIPE error
     // would otherwise be delivered. This runtime doesn't install a SIGPIPE
@@ -60,26 +59,24 @@ pub fn init() {
     //
     // Hence, we set SIGPIPE to ignore when the program starts up in order
     // to prevent this problem.
-    unsafe {
-        reset_sigpipe();
-    }
+    reset_sigpipe();
+
+    stack_overflow::init();
+    args::init(argc, argv);
 
-    cfg_if::cfg_if! {
-        if #[cfg(miri)] {
-            // The standard fds are always available in Miri.
-            unsafe fn sanitize_standard_fds() {}
-        } else if #[cfg(not(any(
-            target_os = "emscripten",
-            target_os = "fuchsia",
-            target_os = "vxworks",
-            // The poll on Darwin doesn't set POLLNVAL for closed fds.
-            target_os = "macos",
-            target_os = "ios",
-            target_os = "redox",
-        )))] {
-            // In the case when all file descriptors are open, the poll has been
-            // observed to perform better than fcntl (on GNU/Linux).
-            unsafe fn sanitize_standard_fds() {
+    unsafe fn sanitize_standard_fds() {
+        #[cfg(not(miri))]
+        // The standard fds are always available in Miri.
+        cfg_if::cfg_if! {
+            if #[cfg(not(any(
+                target_os = "emscripten",
+                target_os = "fuchsia",
+                target_os = "vxworks",
+                // The poll on Darwin doesn't set POLLNVAL for closed fds.
+                target_os = "macos",
+                target_os = "ios",
+                target_os = "redox",
+            )))] {
                 use crate::sys::os::errno;
                 let pfds: &mut [_] = &mut [
                     libc::pollfd { fd: 0, events: 0, revents: 0 },
@@ -104,9 +101,7 @@ pub fn init() {
                         libc::abort();
                     }
                 }
-            }
-        } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "redox"))] {
-            unsafe fn sanitize_standard_fds() {
+            } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "redox"))] {
                 use crate::sys::os::errno;
                 for fd in 0..3 {
                     if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
@@ -116,17 +111,20 @@ pub fn init() {
                     }
                 }
             }
-        } else {
-            unsafe fn sanitize_standard_fds() {}
         }
     }
 
-    #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))]
     unsafe fn reset_sigpipe() {
+        #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia")))]
         assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != libc::SIG_ERR);
     }
-    #[cfg(any(target_os = "emscripten", target_os = "fuchsia"))]
-    unsafe fn reset_sigpipe() {}
+}
+
+// SAFETY: must be called only once during runtime cleanup.
+// NOTE: this is not guaranteed to run, for example when the program aborts.
+pub unsafe fn cleanup() {
+    args::cleanup();
+    stack_overflow::cleanup();
 }
 
 #[cfg(target_os = "android")]
diff --git a/library/std/src/sys/unsupported/args.rs b/library/std/src/sys/unsupported/args.rs
index 360bb65af69..c924a7d8a26 100644
--- a/library/std/src/sys/unsupported/args.rs
+++ b/library/std/src/sys/unsupported/args.rs
@@ -1,8 +1,5 @@
 use crate::ffi::OsString;
 
-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
-pub unsafe fn cleanup() {}
-
 pub struct Args {}
 
 pub fn args() -> Args {
diff --git a/library/std/src/sys/unsupported/common.rs b/library/std/src/sys/unsupported/common.rs
index 0ef84c84ee8..6e72a7c632e 100644
--- a/library/std/src/sys/unsupported/common.rs
+++ b/library/std/src/sys/unsupported/common.rs
@@ -10,8 +10,13 @@ pub use crate::sys_common::os_str_bytes as os_str;
 // spec definition?
 use crate::os::raw::c_char;
 
-#[cfg(not(test))]
-pub fn init() {}
+// SAFETY: must be called only once during runtime initialization.
+// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
+pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
+
+// SAFETY: must be called only once during runtime cleanup.
+// NOTE: this is not guaranteed to run, for example when the program aborts.
+pub unsafe fn cleanup() {}
 
 pub fn unsupported<T>() -> std_io::Result<T> {
     Err(unsupported_err())
diff --git a/library/std/src/sys/unsupported/mod.rs b/library/std/src/sys/unsupported/mod.rs
index d9efdec33d9..32ca68ef15b 100644
--- a/library/std/src/sys/unsupported/mod.rs
+++ b/library/std/src/sys/unsupported/mod.rs
@@ -15,7 +15,6 @@ pub mod path;
 pub mod pipe;
 pub mod process;
 pub mod rwlock;
-pub mod stack_overflow;
 pub mod stdio;
 pub mod thread;
 #[cfg(target_thread_local)]
diff --git a/library/std/src/sys/unsupported/stack_overflow.rs b/library/std/src/sys/unsupported/stack_overflow.rs
deleted file mode 100644
index 32555394cd5..00000000000
--- a/library/std/src/sys/unsupported/stack_overflow.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-pub unsafe fn init() {}
-
-pub unsafe fn cleanup() {}
diff --git a/library/std/src/sys/wasi/args.rs b/library/std/src/sys/wasi/args.rs
index 3c3e66985b3..c42c310e3a2 100644
--- a/library/std/src/sys/wasi/args.rs
+++ b/library/std/src/sys/wasi/args.rs
@@ -5,10 +5,6 @@ use crate::fmt;
 use crate::os::wasi::ffi::OsStrExt;
 use crate::vec;
 
-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
-
-pub unsafe fn cleanup() {}
-
 pub struct Args {
     iter: vec::IntoIter<OsString>,
 }
diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs
index b7b640b174f..2584d35b6ef 100644
--- a/library/std/src/sys/wasi/mod.rs
+++ b/library/std/src/sys/wasi/mod.rs
@@ -42,8 +42,6 @@ pub mod pipe;
 pub mod process;
 #[path = "../unsupported/rwlock.rs"]
 pub mod rwlock;
-#[path = "../unsupported/stack_overflow.rs"]
-pub mod stack_overflow;
 pub mod stdio;
 pub mod thread;
 #[path = "../unsupported/thread_local_dtor.rs"]
diff --git a/library/std/src/sys/wasm/args.rs b/library/std/src/sys/wasm/args.rs
index 99161ee056a..fde1ab79e1f 100644
--- a/library/std/src/sys/wasm/args.rs
+++ b/library/std/src/sys/wasm/args.rs
@@ -2,12 +2,6 @@ use crate::ffi::OsString;
 use crate::fmt;
 use crate::vec;
 
-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
-    // On wasm these should always be null, so there's nothing for us to do here
-}
-
-pub unsafe fn cleanup() {}
-
 pub fn args() -> Args {
     Args { iter: Vec::new().into_iter() }
 }
diff --git a/library/std/src/sys/wasm/mod.rs b/library/std/src/sys/wasm/mod.rs
index 82683c0f624..8705910c73a 100644
--- a/library/std/src/sys/wasm/mod.rs
+++ b/library/std/src/sys/wasm/mod.rs
@@ -35,8 +35,6 @@ pub mod path;
 pub mod pipe;
 #[path = "../unsupported/process.rs"]
 pub mod process;
-#[path = "../unsupported/stack_overflow.rs"]
-pub mod stack_overflow;
 #[path = "../unsupported/stdio.rs"]
 pub mod stdio;
 pub mod thread;
diff --git a/library/std/src/sys/windows/args.rs b/library/std/src/sys/windows/args.rs
index 31197e4accc..f1264130faf 100644
--- a/library/std/src/sys/windows/args.rs
+++ b/library/std/src/sys/windows/args.rs
@@ -14,10 +14,6 @@ use crate::vec;
 
 use core::iter;
 
-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
-
-pub unsafe fn cleanup() {}
-
 pub fn args() -> Args {
     unsafe {
         let lp_cmd_line = c::GetCommandLineW();
diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs
index 973301af2d9..ddb6ac5f55c 100644
--- a/library/std/src/sys/windows/mod.rs
+++ b/library/std/src/sys/windows/mod.rs
@@ -49,8 +49,17 @@ cfg_if::cfg_if! {
     }
 }
 
-#[cfg(not(test))]
-pub fn init() {}
+// SAFETY: must be called only once during runtime initialization.
+// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
+pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
+    stack_overflow::init();
+}
+
+// SAFETY: must be called only once during runtime cleanup.
+// NOTE: this is not guaranteed to run, for example when the program aborts.
+pub unsafe fn cleanup() {
+    net::cleanup();
+}
 
 pub fn decode_error_kind(errno: i32) -> ErrorKind {
     match errno as c::DWORD {
diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs
index ad04afc0b6d..1ad13254c08 100644
--- a/library/std/src/sys/windows/net.rs
+++ b/library/std/src/sys/windows/net.rs
@@ -9,7 +9,7 @@ use crate::sync::Once;
 use crate::sys;
 use crate::sys::c;
 use crate::sys_common::net;
-use crate::sys_common::{self, AsInner, FromInner, IntoInner};
+use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::time::Duration;
 
 use libc::{c_int, c_long, c_ulong, c_void};
@@ -26,23 +26,28 @@ pub mod netc {
 
 pub struct Socket(c::SOCKET);
 
+static INIT: Once = Once::new();
+
 /// Checks whether the Windows socket interface has been started already, and
 /// if not, starts it.
 pub fn init() {
-    static START: Once = Once::new();
-
-    START.call_once(|| unsafe {
+    INIT.call_once(|| unsafe {
         let mut data: c::WSADATA = mem::zeroed();
         let ret = c::WSAStartup(
             0x202, // version 2.2
             &mut data,
         );
         assert_eq!(ret, 0);
+    });
+}
 
-        let _ = sys_common::at_exit(|| {
+pub fn cleanup() {
+    if INIT.is_completed() {
+        // only close the socket interface if it has actually been started
+        unsafe {
             c::WSACleanup();
-        });
-    });
+        }
+    }
 }
 
 /// Returns the last error from the Windows socket interface.
diff --git a/library/std/src/sys/windows/stack_overflow.rs b/library/std/src/sys/windows/stack_overflow.rs
index 187ad4e66c3..39efb778207 100644
--- a/library/std/src/sys/windows/stack_overflow.rs
+++ b/library/std/src/sys/windows/stack_overflow.rs
@@ -37,5 +37,3 @@ pub unsafe fn init() {
     // Set the thread stack guarantee for the main thread.
     let _h = Handler::new();
 }
-
-pub unsafe fn cleanup() {}
diff --git a/library/std/src/sys/windows/stack_overflow_uwp.rs b/library/std/src/sys/windows/stack_overflow_uwp.rs
index e7236cf359c..afdf7f566ae 100644
--- a/library/std/src/sys/windows/stack_overflow_uwp.rs
+++ b/library/std/src/sys/windows/stack_overflow_uwp.rs
@@ -9,5 +9,3 @@ impl Handler {
 }
 
 pub unsafe fn init() {}
-
-pub unsafe fn cleanup() {}