Skip to content

Commit 7683f12

Browse files
ayeteadoeADKaster
authored andcommitted
AK: Expose helpers to invoke Windows runtime config directly in main()
When shutting down helper processes, PosixSocketHelper::close() in SocketWindows when trying to close the socket fd with WSANOTINITIALISED. This was due to us initiating WinSock2 during static initialization and presumably also not terminating WinSock2 properly. Similar to WinSock2 initiation, calling CRT during static initialization is considered dangerous given the CRT DLL itself may not yet be initialized. Because of the above, we move to perform this Windows-specific runtime setup/teardown calls into the main() functions.
1 parent 643f0de commit 7683f12

File tree

4 files changed

+60
-18
lines changed

4 files changed

+60
-18
lines changed

AK/Windows.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2024, stasoid <stasoid@yahoo.com>
3+
* Copyright (c) 2025, ayeteadoe <ayeteadoe@gmail.com>
34
*
45
* SPDX-License-Identifier: BSD-2-Clause
56
*/
@@ -9,6 +10,7 @@
910

1011
#pragma once
1112

13+
#include <AK/Assertions.h>
1214
#include <AK/Platform.h>
1315

1416
#ifdef AK_OS_WINDOWS // needed for Swift
@@ -18,4 +20,40 @@
1820
# undef IN
1921
# pragma comment(lib, "ws2_32.lib")
2022
# include <io.h>
23+
# include <stdlib.h>
24+
25+
inline void initiate_wsa()
26+
{
27+
WSADATA wsa;
28+
WORD version = MAKEWORD(2, 2);
29+
int rc = WSAStartup(version, &wsa);
30+
VERIFY(rc == 0 && wsa.wVersion == version);
31+
}
32+
33+
inline void terminate_wsa()
34+
{
35+
int rc = WSACleanup();
36+
VERIFY(rc == 0);
37+
}
38+
39+
static void invalid_parameter_handler(wchar_t const*, wchar_t const*, wchar_t const*, unsigned int, uintptr_t)
40+
{
41+
}
42+
43+
inline void override_crt_invalid_parameter_handler()
44+
{
45+
// Make _get_osfhandle return -1 instead of crashing on invalid fd in release (debug still __debugbreak's)
46+
_set_invalid_parameter_handler(invalid_parameter_handler);
47+
}
48+
49+
inline void windows_init()
50+
{
51+
initiate_wsa();
52+
override_crt_invalid_parameter_handler();
53+
}
54+
55+
inline void windows_shutdown()
56+
{
57+
terminate_wsa();
58+
}
2159
#endif

Libraries/LibCore/SystemWindows.cpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,6 @@ namespace Core::System {
2323

2424
int windows_socketpair(SOCKET socks[2], int make_overlapped);
2525

26-
static void invalid_parameter_handler(wchar_t const*, wchar_t const*, wchar_t const*, unsigned int, uintptr_t)
27-
{
28-
}
29-
30-
static int init_crt_and_wsa()
31-
{
32-
WSADATA wsa;
33-
WORD version = MAKEWORD(2, 2);
34-
int rc = WSAStartup(version, &wsa);
35-
VERIFY(!rc && wsa.wVersion == version);
36-
37-
// Make _get_osfhandle return -1 instead of crashing on invalid fd in release (debug still __debugbreak's)
38-
_set_invalid_parameter_handler(invalid_parameter_handler);
39-
return 0;
40-
}
41-
42-
static auto dummy = init_crt_and_wsa();
43-
4426
ErrorOr<int> open(StringView path, int options, mode_t mode)
4527
{
4628
ByteString str = path;

Libraries/LibMain/Main.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
#include <LibMain/Main.h>
1111
#include <string.h>
1212
#include <time.h>
13+
#if defined(AK_OS_WINDOWS)
14+
# include <AK/Windows.h>
15+
#endif
1316

1417
namespace Main {
1518

@@ -31,6 +34,10 @@ int main(int argc, char** argv)
3134
{
3235
tzset();
3336

37+
#if defined(AK_OS_WINDOWS)
38+
windows_init();
39+
#endif
40+
3441
Vector<StringView> arguments;
3542
arguments.ensure_capacity(argc);
3643
for (int i = 0; i < argc; ++i)
@@ -41,6 +48,11 @@ int main(int argc, char** argv)
4148
.argv = argv,
4249
.strings = arguments.span(),
4350
});
51+
52+
#if defined(AK_OS_WINDOWS)
53+
windows_shutdown();
54+
#endif
55+
4456
if (result.is_error()) {
4557
auto error = result.release_error();
4658
warnln("\033[31;1mRuntime error\033[0m: {}", error);

Libraries/LibTest/TestMain.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
#include <AK/Format.h>
99
#include <AK/Vector.h>
1010
#include <LibTest/TestSuite.h>
11+
#if defined(AK_OS_WINDOWS)
12+
# include <AK/Windows.h>
13+
#endif
1114

1215
#define TEST_MAIN main
1316

@@ -18,13 +21,20 @@ int TEST_MAIN(int argc, char** argv)
1821
return 1;
1922
}
2023

24+
#if defined(AK_OS_WINDOWS)
25+
windows_init();
26+
#endif
27+
2128
Vector<StringView> arguments;
2229
arguments.ensure_capacity(argc);
2330
for (auto i = 0; i < argc; ++i)
2431
arguments.append({ argv[i], strlen(argv[i]) });
2532

2633
int ret = ::Test::TestSuite::the().main(argv[0], arguments);
2734
::Test::TestSuite::release();
35+
#if defined(AK_OS_WINDOWS)
36+
windows_shutdown();
37+
#endif
2838
// As TestSuite::main() returns the number of test cases that did not pass,
2939
// ret can be >=256 which cannot be returned as an exit status directly.
3040
// Return 0 if all of the test cases pass and return 1 otherwise.

0 commit comments

Comments
 (0)