Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework init and cleanup #84115

Merged
merged 6 commits into from
Apr 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions library/std/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,10 @@ mod util;

const DEFAULT_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;

pub(crate) fn cleanup() {
stdio::cleanup()
}

struct Guard<'a> {
buf: &'a mut Vec<u8>,
len: usize,
Expand Down
41 changes: 18 additions & 23 deletions library/std/src/io/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use crate::pin::Pin;
use crate::sync::atomic::{AtomicBool, Ordering};
use crate::sync::{Arc, Mutex, MutexGuard};
use crate::sys::stdio;
use crate::sys_common;
use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};

type LocalStream = Arc<Mutex<Vec<u8>>>;
Expand Down Expand Up @@ -508,6 +507,8 @@ pub struct StdoutLock<'a> {
inner: ReentrantMutexGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
}

static STDOUT: SyncOnceCell<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = SyncOnceCell::new();

/// Constructs a new handle to the standard output of the current process.
///
/// Each handle returned is a reference to a shared global buffer whose access
Expand Down Expand Up @@ -549,34 +550,28 @@ pub struct StdoutLock<'a> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn stdout() -> Stdout {
static INSTANCE: SyncOnceCell<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> =
SyncOnceCell::new();

fn cleanup() {
if let Some(instance) = INSTANCE.get() {
// Flush the data and disable buffering during shutdown
// by replacing the line writer by one with zero
// buffering capacity.
// We use try_lock() instead of lock(), because someone
// might have leaked a StdoutLock, which would
// otherwise cause a deadlock here.
if let Some(lock) = Pin::static_ref(instance).try_lock() {
*lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
}
}
}

Stdout {
inner: Pin::static_ref(&INSTANCE).get_or_init_pin(
|| unsafe {
let _ = sys_common::at_exit(cleanup);
ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())))
},
inner: Pin::static_ref(&STDOUT).get_or_init_pin(
|| unsafe { ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw()))) },
|mutex| unsafe { mutex.init() },
),
}
}

pub fn cleanup() {
if let Some(instance) = STDOUT.get() {
// Flush the data and disable buffering during shutdown
// by replacing the line writer by one with zero
// buffering capacity.
// We use try_lock() instead of lock(), because someone
// might have leaked a StdoutLock, which would
// otherwise cause a deadlock here.
if let Some(lock) = Pin::static_ref(instance).try_lock() {
*lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
}
}
}

impl Stdout {
/// Locks this handle to the standard output stream, returning a writable
/// guard.
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1749,7 +1749,7 @@ impl Child {
/// [platform-specific behavior]: #platform-specific-behavior
#[stable(feature = "rust1", since = "1.0.0")]
pub fn exit(code: i32) -> ! {
crate::sys_common::cleanup();
crate::sys_common::rt::cleanup();
crate::sys::os::exit(code)
}

Expand Down
27 changes: 5 additions & 22 deletions library/std/src/rt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,33 +26,16 @@ fn lang_start_internal(
argv: *const *const u8,
) -> isize {
use crate::panic;
use crate::sys;
use crate::sys_common;
use crate::sys_common::thread_info;
use crate::thread::Thread;

sys::init();
// SAFETY: Only called once during runtime initialization.
unsafe { sys_common::rt::init(argc, argv) };

unsafe {
let main_guard = sys::thread::guard::init();
sys::stack_overflow::init();
let exit_code = panic::catch_unwind(main);

// Next, set up the current Thread with the guard information we just
// created. Note that this isn't necessary in general for new threads,
// but we just do this to name the main thread and to give it correct
// info about the stack bounds.
let thread = Thread::new(Some("main".to_owned()));
thread_info::set(main_guard, thread);
sys_common::rt::cleanup();

// Store our args if necessary in a squirreled away location
sys::args::init(argc, argv);

// Let's run some code!
let exit_code = panic::catch_unwind(main);

sys_common::cleanup();
exit_code.unwrap_or(101) as isize
}
exit_code.unwrap_or(101) as isize
}

#[cfg(not(test))]
Expand Down
13 changes: 10 additions & 3 deletions library/std/src/sys/hermit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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))]
Expand Down
5 changes: 0 additions & 5 deletions library/std/src/sys/hermit/stack_overflow.rs

This file was deleted.

2 changes: 0 additions & 2 deletions library/std/src/sys/sgx/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,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()) }
Expand Down
14 changes: 11 additions & 3 deletions library/std/src/sys/sgx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,24 @@ 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;
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.
Expand Down
4 changes: 0 additions & 4 deletions library/std/src/sys/sgx/stack_overflow.rs

This file was deleted.

62 changes: 30 additions & 32 deletions library/std/src/sys/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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! {
CDirkx marked this conversation as resolved.
Show resolved Hide resolved
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 },
Expand All @@ -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 {
Expand All @@ -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")]
Expand Down
3 changes: 0 additions & 3 deletions library/std/src/sys/unsupported/args.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
9 changes: 7 additions & 2 deletions library/std/src/sys/unsupported/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
1 change: 0 additions & 1 deletion library/std/src/sys/unsupported/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
3 changes: 0 additions & 3 deletions library/std/src/sys/unsupported/stack_overflow.rs

This file was deleted.

4 changes: 0 additions & 4 deletions library/std/src/sys/wasi/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ use crate::marker::PhantomData;
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>,
_dont_send_or_sync_me: PhantomData<*mut ()>,
Expand Down
2 changes: 0 additions & 2 deletions library/std/src/sys/wasi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
6 changes: 0 additions & 6 deletions library/std/src/sys/wasm/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@ use crate::ffi::OsString;
use crate::marker::PhantomData;
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(), _dont_send_or_sync_me: PhantomData }
}
Expand Down
2 changes: 0 additions & 2 deletions library/std/src/sys/wasm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 0 additions & 4 deletions library/std/src/sys/windows/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Loading