@@ -8,7 +8,8 @@ use crate::net::{Shutdown, SocketAddr};
88use crate :: os:: windows:: io:: {
99 AsRawSocket , AsSocket , BorrowedSocket , FromRawSocket , IntoRawSocket , OwnedSocket , RawSocket ,
1010} ;
11- use crate :: sync:: OnceLock ;
11+ use crate :: sync:: atomic:: Atomic ;
12+ use crate :: sync:: atomic:: Ordering :: { AcqRel , Relaxed } ;
1213use crate :: sys:: c;
1314use crate :: sys_common:: { AsInner , FromInner , IntoInner } ;
1415use crate :: time:: Duration ;
@@ -114,35 +115,36 @@ pub(super) mod netc {
114115#[ expect( missing_debug_implementations) ]
115116pub struct Socket ( OwnedSocket ) ;
116117
117- static WSA_CLEANUP : OnceLock < unsafe extern "system" fn ( ) -> i32 > = OnceLock :: new ( ) ;
118+ static WSA_INITIALIZED : Atomic < bool > = Atomic :: < bool > :: new ( false ) ;
118119
119120/// Checks whether the Windows socket interface has been started already, and
120121/// if not, starts it.
122+ #[ inline]
121123pub fn init ( ) {
122- let _ = WSA_CLEANUP . get_or_init ( || unsafe {
124+ if !WSA_INITIALIZED . load ( Relaxed ) {
125+ wsa_startup ( ) ;
126+ }
127+ }
128+
129+ #[ cold]
130+ fn wsa_startup ( ) {
131+ unsafe {
123132 let mut data: c:: WSADATA = mem:: zeroed ( ) ;
124133 let ret = c:: WSAStartup (
125134 0x202 , // version 2.2
126135 & mut data,
127136 ) ;
128137 assert_eq ! ( ret, 0 ) ;
129-
130- // Only register `WSACleanup` if `WSAStartup` is actually ever called.
131- // Workaround to prevent linking to `WS2_32.dll` when no network functionality is used.
132- // See issue #85441.
133- c:: WSACleanup
134- } ) ;
135- }
136-
137- pub fn cleanup ( ) {
138- // only perform cleanup if network functionality was actually initialized
139- if let Some ( cleanup) = WSA_CLEANUP . get ( ) {
140- unsafe {
141- cleanup ( ) ;
138+ if WSA_INITIALIZED . swap ( true , AcqRel ) {
139+ // If another thread raced with us and called WSAStartup first then call
140+ // WSACleanup so it's as though WSAStartup was only called once.
141+ c:: WSACleanup ( ) ;
142142 }
143143 }
144144}
145145
146+ pub fn cleanup ( ) { }
147+
146148/// Returns the last error from the Windows socket interface.
147149fn last_error ( ) -> io:: Error {
148150 io:: Error :: from_raw_os_error ( unsafe { c:: WSAGetLastError ( ) } )
0 commit comments