Skip to content

Commit a131d97

Browse files
committed
Don't call WSACleanup on process exit
1 parent ec28ae9 commit a131d97

File tree

1 file changed

+18
-16
lines changed
  • library/std/src/sys/net/connection/socket

1 file changed

+18
-16
lines changed

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

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ use crate::net::{Shutdown, SocketAddr};
88
use 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, Acquire, Relaxed};
1213
use crate::sys::c;
1314
use crate::sys_common::{AsInner, FromInner, IntoInner};
1415
use crate::time::Duration;
@@ -114,35 +115,36 @@ pub(super) mod netc {
114115
#[expect(missing_debug_implementations)]
115116
pub 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]
121123
pub 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.compare_exchange(false, true, AcqRel, Acquire).is_err() {
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.
147149
fn last_error() -> io::Error {
148150
io::Error::from_raw_os_error(unsafe { c::WSAGetLastError() })

0 commit comments

Comments
 (0)