Skip to content

Commit 05e1ff6

Browse files
committed
Windows: Run compat_fn init before C++ init
1 parent 792bc5a commit 05e1ff6

File tree

1 file changed

+13
-5
lines changed

1 file changed

+13
-5
lines changed

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

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,16 @@
3131
//! The mechanism of registering a static initializer with the CRT is
3232
//! documented in
3333
//! [CRT Initialization](https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-initialization?view=msvc-160).
34-
//! It works by contributing a global symbol to the `.CRT$XCU` section.
34+
//! It works by contributing a global symbol to the `.CRT$XIU` section.
3535
//! The linker builds a table of all static initializer functions.
3636
//! The CRT startup code then iterates that table, calling each
3737
//! initializer function.
3838
//!
39+
//! This originally used the C++ initializer section `.CRT$XCU`. However, this
40+
//! risks being run after user code that inserts their own initializers.
41+
//! Instead the C initializer section `CRT$XIU` is used. Function placed here
42+
//! are run earlier than the C++ initializers.
43+
//!
3944
//! # **WARNING!!*
4045
//! The environment that a static initializer function runs in is highly
4146
//! constrained. There are **many** restrictions on what static initializers
@@ -49,7 +54,7 @@
4954
//! * call any Rust function or CRT function that touches any static
5055
//! (global) state.
5156
52-
use crate::ffi::{c_void, CStr};
57+
use crate::ffi::{c_int, c_void, CStr};
5358
use crate::ptr::NonNull;
5459
use crate::sys::c;
5560

@@ -86,8 +91,8 @@ pub(crate) const fn const_cstr_from_bytes(bytes: &'static [u8]) -> &'static CStr
8691
}
8792

8893
#[used]
89-
#[link_section = ".CRT$XCU"]
90-
static INIT_TABLE_ENTRY: unsafe extern "C" fn() = init;
94+
#[link_section = ".CRT$XIU"]
95+
static INIT_TABLE_ENTRY: unsafe extern "C" fn() -> c_int = init;
9196

9297
/// This is where the magic preloading of symbols happens.
9398
///
@@ -96,7 +101,7 @@ static INIT_TABLE_ENTRY: unsafe extern "C" fn() = init;
96101
///
97102
/// Therefore, this is limited to `compat_fn_optional` functions which must be
98103
/// preloaded and any functions which may be more time sensitive, even for the first call.
99-
unsafe extern "C" fn init() {
104+
unsafe extern "C" fn init() -> c_int {
100105
// There is no locking here. This code is executed before main() is entered, and
101106
// is guaranteed to be single-threaded.
102107
//
@@ -116,6 +121,9 @@ unsafe extern "C" fn init() {
116121
// Preloading this means getting a precise time will be as fast as possible.
117122
c::GetSystemTimePreciseAsFileTime::preload(kernel32);
118123
}
124+
125+
// Returns zero for success and non-zero for error.
126+
0
119127
}
120128

121129
/// Represents a loaded module.

0 commit comments

Comments
 (0)