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
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 } ;
5358use crate :: ptr:: NonNull ;
5459use 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