Skip to content

Commit 5b30662

Browse files
committed
Rework at_exit to cleanup
1 parent 71965ab commit 5b30662

File tree

13 files changed

+134
-196
lines changed

13 files changed

+134
-196
lines changed

library/std/src/io/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,10 @@ mod util;
293293

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

296+
pub(crate) fn cleanup() {
297+
stdio::cleanup()
298+
}
299+
296300
struct Guard<'a> {
297301
buf: &'a mut Vec<u8>,
298302
len: usize,

library/std/src/io/stdio.rs

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ use crate::pin::Pin;
1313
use crate::sync::atomic::{AtomicBool, Ordering};
1414
use crate::sync::{Arc, Mutex, MutexGuard};
1515
use crate::sys::stdio;
16-
use crate::sys_common;
1716
use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
1817

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

510+
static STDOUT: SyncOnceCell<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = SyncOnceCell::new();
511+
511512
/// Constructs a new handle to the standard output of the current process.
512513
///
513514
/// Each handle returned is a reference to a shared global buffer whose access
@@ -549,34 +550,28 @@ pub struct StdoutLock<'a> {
549550
/// ```
550551
#[stable(feature = "rust1", since = "1.0.0")]
551552
pub fn stdout() -> Stdout {
552-
static INSTANCE: SyncOnceCell<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> =
553-
SyncOnceCell::new();
554-
555-
fn cleanup() {
556-
if let Some(instance) = INSTANCE.get() {
557-
// Flush the data and disable buffering during shutdown
558-
// by replacing the line writer by one with zero
559-
// buffering capacity.
560-
// We use try_lock() instead of lock(), because someone
561-
// might have leaked a StdoutLock, which would
562-
// otherwise cause a deadlock here.
563-
if let Some(lock) = Pin::static_ref(instance).try_lock() {
564-
*lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
565-
}
566-
}
567-
}
568-
569553
Stdout {
570-
inner: Pin::static_ref(&INSTANCE).get_or_init_pin(
571-
|| unsafe {
572-
let _ = sys_common::at_exit(cleanup);
573-
ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())))
574-
},
554+
inner: Pin::static_ref(&STDOUT).get_or_init_pin(
555+
|| unsafe { ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw()))) },
575556
|mutex| unsafe { mutex.init() },
576557
),
577558
}
578559
}
579560

561+
pub fn cleanup() {
562+
if let Some(instance) = STDOUT.get() {
563+
// Flush the data and disable buffering during shutdown
564+
// by replacing the line writer by one with zero
565+
// buffering capacity.
566+
// We use try_lock() instead of lock(), because someone
567+
// might have leaked a StdoutLock, which would
568+
// otherwise cause a deadlock here.
569+
if let Some(lock) = Pin::static_ref(instance).try_lock() {
570+
*lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
571+
}
572+
}
573+
}
574+
580575
impl Stdout {
581576
/// Locks this handle to the standard output stream, returning a writable
582577
/// guard.

library/std/src/process.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1749,7 +1749,7 @@ impl Child {
17491749
/// [platform-specific behavior]: #platform-specific-behavior
17501750
#[stable(feature = "rust1", since = "1.0.0")]
17511751
pub fn exit(code: i32) -> ! {
1752-
crate::sys_common::cleanup();
1752+
crate::sys_common::rt::cleanup();
17531753
crate::sys::os::exit(code)
17541754
}
17551755

library/std/src/rt.rs

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,33 +26,13 @@ fn lang_start_internal(
2626
argv: *const *const u8,
2727
) -> isize {
2828
use crate::panic;
29-
use crate::sys;
3029
use crate::sys_common;
31-
use crate::sys_common::thread_info;
32-
use crate::thread::Thread;
3330

34-
sys::init();
31+
sys_common::rt::init(argc, argv);
32+
let exit_code = panic::catch_unwind(main);
33+
sys_common::rt::cleanup();
3534

36-
unsafe {
37-
let main_guard = sys::thread::guard::init();
38-
sys::stack_overflow::init();
39-
40-
// Next, set up the current Thread with the guard information we just
41-
// created. Note that this isn't necessary in general for new threads,
42-
// but we just do this to name the main thread and to give it correct
43-
// info about the stack bounds.
44-
let thread = Thread::new(Some("main".to_owned()));
45-
thread_info::set(main_guard, thread);
46-
47-
// Store our args if necessary in a squirreled away location
48-
sys::args::init(argc, argv);
49-
50-
// Let's run some code!
51-
let exit_code = panic::catch_unwind(main);
52-
53-
sys_common::cleanup();
54-
exit_code.unwrap_or(101) as isize
55-
}
35+
exit_code.unwrap_or(101) as isize
5636
}
5737

5838
#[cfg(not(test))]

library/std/src/sys/hermit/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,14 @@ pub extern "C" fn __rust_abort() {
9696
abort_internal();
9797
}
9898

99-
#[cfg(not(test))]
100-
pub fn init() {
99+
// SAFETY: must be called only once during runtime initialization.
100+
pub unsafe fn init() {
101101
let _ = net::init();
102102
}
103103

104+
// SAFETY: must be called only once during runtime cleanup.
105+
pub unsafe fn cleanup() {}
106+
104107
#[cfg(not(test))]
105108
#[no_mangle]
106109
pub unsafe extern "C" fn runtime_entry(

library/std/src/sys/sgx/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,11 @@ pub mod time;
4040

4141
pub use crate::sys_common::os_str_bytes as os_str;
4242

43-
#[cfg(not(test))]
44-
pub fn init() {}
43+
// SAFETY: must be called only once during runtime initialization.
44+
pub unsafe fn init() {}
45+
46+
// SAFETY: must be called only once during runtime cleanup.
47+
pub unsafe fn cleanup() {}
4548

4649
/// This function is used to implement functionality that simply doesn't exist.
4750
/// Programs relying on this functionality will need to deal with the error.

library/std/src/sys/unix/mod.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,12 @@ pub mod time;
4444

4545
pub use crate::sys_common::os_str_bytes as os_str;
4646

47-
#[cfg(not(test))]
48-
pub fn init() {
47+
// SAFETY: must be called only once during runtime initialization.
48+
pub unsafe fn init() {
4949
// The standard streams might be closed on application startup. To prevent
5050
// std::io::{stdin, stdout,stderr} objects from using other unrelated file
5151
// resources opened later, we reopen standards streams when they are closed.
52-
unsafe {
53-
sanitize_standard_fds();
54-
}
52+
sanitize_standard_fds();
5553

5654
// By default, some platforms will send a *signal* when an EPIPE error
5755
// would otherwise be delivered. This runtime doesn't install a SIGPIPE
@@ -60,9 +58,7 @@ pub fn init() {
6058
//
6159
// Hence, we set SIGPIPE to ignore when the program starts up in order
6260
// to prevent this problem.
63-
unsafe {
64-
reset_sigpipe();
65-
}
61+
reset_sigpipe();
6662

6763
cfg_if::cfg_if! {
6864
if #[cfg(miri)] {
@@ -129,6 +125,9 @@ pub fn init() {
129125
unsafe fn reset_sigpipe() {}
130126
}
131127

128+
// SAFETY: must be called only once during runtime cleanup.
129+
pub unsafe fn cleanup() {}
130+
132131
#[cfg(target_os = "android")]
133132
pub use crate::sys::android::signal;
134133
#[cfg(not(target_os = "android"))]

library/std/src/sys/unsupported/common.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ pub use crate::sys_common::os_str_bytes as os_str;
1010
// spec definition?
1111
use crate::os::raw::c_char;
1212

13-
#[cfg(not(test))]
14-
pub fn init() {}
13+
// SAFETY: must be called only once during runtime initialization.
14+
pub unsafe fn init() {}
15+
16+
// SAFETY: must be called only once during runtime cleanup.
17+
pub unsafe fn cleanup() {}
1518

1619
pub fn unsupported<T>() -> std_io::Result<T> {
1720
Err(unsupported_err())

library/std/src/sys/windows/mod.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,13 @@ cfg_if::cfg_if! {
4949
}
5050
}
5151

52-
#[cfg(not(test))]
53-
pub fn init() {}
52+
// SAFETY: must be called only once during runtime initialization.
53+
pub unsafe fn init() {}
54+
55+
// SAFETY: must be called only once during runtime cleanup.
56+
pub unsafe fn cleanup() {
57+
net::cleanup();
58+
}
5459

5560
pub fn decode_error_kind(errno: i32) -> ErrorKind {
5661
match errno as c::DWORD {

library/std/src/sys/windows/net.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::sync::Once;
99
use crate::sys;
1010
use crate::sys::c;
1111
use crate::sys_common::net;
12-
use crate::sys_common::{self, AsInner, FromInner, IntoInner};
12+
use crate::sys_common::{AsInner, FromInner, IntoInner};
1313
use crate::time::Duration;
1414

1515
use libc::{c_int, c_long, c_ulong, c_void};
@@ -38,13 +38,15 @@ pub fn init() {
3838
&mut data,
3939
);
4040
assert_eq!(ret, 0);
41-
42-
let _ = sys_common::at_exit(|| {
43-
c::WSACleanup();
44-
});
4541
});
4642
}
4743

44+
pub fn cleanup() {
45+
unsafe {
46+
c::WSACleanup();
47+
}
48+
}
49+
4850
/// Returns the last error from the Windows socket interface.
4951
fn last_error() -> io::Error {
5052
io::Error::from_raw_os_error(unsafe { c::WSAGetLastError() })

library/std/src/sys_common/at_exit_imp.rs

Lines changed: 0 additions & 74 deletions
This file was deleted.

0 commit comments

Comments
 (0)