about summary refs log tree commit diff
path: root/library
diff options
context:
space:
mode:
authorChris Denton <chris@chrisdenton.dev>2025-05-31 10:39:09 +0000
committerChris Denton <chris@chrisdenton.dev>2025-07-14 14:27:49 +0000
commitc8fb37a521b1f8cf13ddf1ffb81b0a30b05e0706 (patch)
tree0f38e622f4eeb9e8b56db10eb942d5ec26377e3c /library
parent64b185eddaa1d7ddf5e0c024be23b9cbba6c1722 (diff)
downloadrust-c8fb37a521b1f8cf13ddf1ffb81b0a30b05e0706.tar.gz
rust-c8fb37a521b1f8cf13ddf1ffb81b0a30b05e0706.zip
Don't call WSACleanup on process exit
Diffstat (limited to 'library')
-rw-r--r--library/std/src/sys/net/connection/socket/windows.rs36
1 files changed, 21 insertions, 15 deletions
diff --git a/library/std/src/sys/net/connection/socket/windows.rs b/library/std/src/sys/net/connection/socket/windows.rs
index ce975bb2289..b71d8b1357b 100644
--- a/library/std/src/sys/net/connection/socket/windows.rs
+++ b/library/std/src/sys/net/connection/socket/windows.rs
@@ -8,7 +8,8 @@ use crate::net::{Shutdown, SocketAddr};
 use crate::os::windows::io::{
     AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, RawSocket,
 };
-use crate::sync::OnceLock;
+use crate::sync::atomic::Atomic;
+use crate::sync::atomic::Ordering::{AcqRel, Relaxed};
 use crate::sys::c;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::time::Duration;
@@ -114,33 +115,38 @@ pub(super) mod netc {
 #[expect(missing_debug_implementations)]
 pub struct Socket(OwnedSocket);
 
-static WSA_CLEANUP: OnceLock<unsafe extern "system" fn() -> i32> = OnceLock::new();
+static WSA_INITIALIZED: Atomic<bool> = Atomic::<bool>::new(false);
 
 /// Checks whether the Windows socket interface has been started already, and
 /// if not, starts it.
+#[inline]
 pub fn init() {
-    let _ = WSA_CLEANUP.get_or_init(|| unsafe {
+    if !WSA_INITIALIZED.load(Relaxed) {
+        wsa_startup();
+    }
+}
+
+#[cold]
+fn wsa_startup() {
+    unsafe {
         let mut data: c::WSADATA = mem::zeroed();
         let ret = c::WSAStartup(
             0x202, // version 2.2
             &mut data,
         );
         assert_eq!(ret, 0);
-
-        // Only register `WSACleanup` if `WSAStartup` is actually ever called.
-        // Workaround to prevent linking to `WS2_32.dll` when no network functionality is used.
-        // See issue #85441.
-        c::WSACleanup
-    });
+        if WSA_INITIALIZED.swap(true, AcqRel) {
+            // If another thread raced with us and called WSAStartup first then call
+            // WSACleanup so it's as though WSAStartup was only called once.
+            c::WSACleanup();
+        }
+    }
 }
 
 pub fn cleanup() {
-    // only perform cleanup if network functionality was actually initialized
-    if let Some(cleanup) = WSA_CLEANUP.get() {
-        unsafe {
-            cleanup();
-        }
-    }
+    // We don't need to call WSACleanup here because exiting the process will cause
+    // the OS to clean everything for us, which is faster than doing it manually.
+    // See #141799.
 }
 
 /// Returns the last error from the Windows socket interface.