From 9a6f2e655aa15bd600fc55949b17bbc51fc1565d Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Mon, 24 May 2021 23:58:20 +0200 Subject: [PATCH 1/3] Only register `WSACleanup` if `WSAStartup` is actually ever called --- library/std/src/sys/windows/net.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs index 33152cc97abc0..84a5a389e0db3 100644 --- a/library/std/src/sys/windows/net.rs +++ b/library/std/src/sys/windows/net.rs @@ -2,13 +2,13 @@ use crate::cmp; use crate::io::{self, IoSlice, IoSliceMut, Read}; +use crate::lazy::SyncOnceCell; use crate::mem; use crate::net::{Shutdown, SocketAddr}; use crate::os::windows::io::{ AsRawSocket, AsSocket, BorrowedSocket, FromRawSocket, IntoRawSocket, OwnedSocket, RawSocket, }; use crate::ptr; -use crate::sync::Once; use crate::sys; use crate::sys::c; use crate::sys_common::net; @@ -29,26 +29,31 @@ pub mod netc { pub struct Socket(OwnedSocket); -static INIT: Once = Once::new(); +static WSA: SyncOnceCell i32> = SyncOnceCell::new(); /// Checks whether the Windows socket interface has been started already, and /// if not, starts it. pub fn init() { - INIT.call_once(|| unsafe { + let _ = WSA.get_or_init(|| 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 }); } pub fn cleanup() { - if INIT.is_completed() { - // only close the socket interface if it has actually been started + // only perform cleanup if network functionality was actually initialized + if let Some(cleanup) = WSA.get() { unsafe { - c::WSACleanup(); + cleanup(); } } } From b7d2b465b9a3d375ad3c1fbce75fa2ed47cc9e99 Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Tue, 25 May 2021 00:05:18 +0200 Subject: [PATCH 2/3] Add test for checking if WS2_32.dll is linked --- src/test/run-make/issue-85441/Makefile | 9 +++++++++ src/test/run-make/issue-85441/empty.rs | 1 + 2 files changed, 10 insertions(+) create mode 100644 src/test/run-make/issue-85441/Makefile create mode 100644 src/test/run-make/issue-85441/empty.rs diff --git a/src/test/run-make/issue-85441/Makefile b/src/test/run-make/issue-85441/Makefile new file mode 100644 index 0000000000000..0de956d3aee52 --- /dev/null +++ b/src/test/run-make/issue-85441/Makefile @@ -0,0 +1,9 @@ +# only-windows + +-include ../../run-make-fulldeps/tools.mk + +# Tests that WS2_32.dll is not unnecessarily linked, see issue #85441 + +all: + $(RUSTC) empty.rs + objdump -p $(TMPDIR)/empty.exe | $(CGREP) -v -i "WS2_32.dll" diff --git a/src/test/run-make/issue-85441/empty.rs b/src/test/run-make/issue-85441/empty.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/src/test/run-make/issue-85441/empty.rs @@ -0,0 +1 @@ +fn main() {} From 5b4873a7597648998285c191a7a7a05fdec15ad4 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sat, 2 Oct 2021 22:10:00 +0300 Subject: [PATCH 3/3] Run the #85441 regression test on MSVC only On MinGW toolchains the various features (such as function sections) necessary to eliminate dead function references are disabled due to various bugs. This means that the windows sockets library will most likely remain linked to any mingw toolchain built program that also utilizes libstd. That said, I made an attempt to also enable `function-sections` and `--gc-sections` during my experiments, but the symbol references remained, sadly. --- library/std/src/sys/windows/net.rs | 6 +++--- src/test/run-make/issue-85441/Makefile | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/windows/net.rs b/library/std/src/sys/windows/net.rs index 84a5a389e0db3..9c631e7e51c1d 100644 --- a/library/std/src/sys/windows/net.rs +++ b/library/std/src/sys/windows/net.rs @@ -29,12 +29,12 @@ pub mod netc { pub struct Socket(OwnedSocket); -static WSA: SyncOnceCell i32> = SyncOnceCell::new(); +static WSA_CLEANUP: SyncOnceCell i32> = SyncOnceCell::new(); /// Checks whether the Windows socket interface has been started already, and /// if not, starts it. pub fn init() { - let _ = WSA.get_or_init(|| unsafe { + let _ = WSA_CLEANUP.get_or_init(|| unsafe { let mut data: c::WSADATA = mem::zeroed(); let ret = c::WSAStartup( 0x202, // version 2.2 @@ -51,7 +51,7 @@ pub fn init() { pub fn cleanup() { // only perform cleanup if network functionality was actually initialized - if let Some(cleanup) = WSA.get() { + if let Some(cleanup) = WSA_CLEANUP.get() { unsafe { cleanup(); } diff --git a/src/test/run-make/issue-85441/Makefile b/src/test/run-make/issue-85441/Makefile index 0de956d3aee52..c7ae708c173c1 100644 --- a/src/test/run-make/issue-85441/Makefile +++ b/src/test/run-make/issue-85441/Makefile @@ -1,4 +1,4 @@ -# only-windows +# only-windows-msvc -include ../../run-make-fulldeps/tools.mk