Fix race condition when starting a local registry (#40797)
Blue committed
Jun 15, 2026 at 01:26 UTC
5b3faba836484eca3eeb4e2aa97cbde4a82fde50
3 files changed
+11
-47
test/windows/WslcSdkTests.cpp
+3
-23
@@ -19,6 +19,7 @@ Abstract:
19
#include "WSLCContainerLauncher.h"
20
#include "WSLCProcessLauncher.h"
21
#include "wslc_schema.h"
22
+#include "wslc/e2e/WSLCE2EHelpers.h"
23
#include <optional>
24
25
extern std::wstring g_testDataPath;
@@ -2225,30 +2226,9 @@ class WslcSdkTests
2226
std::pair<wsl::windows::common::RunningWSLCContainer, std::string> StartLocalRegistry(
2227
const std::string& username = {}, const std::string& password = {}, uint16_t port = 5000)
2228
{
2228
- VERIFY_IS_TRUE(HasImage("wslc-registry:latest"));
2229
-
2230
- std::vector<std::string> env = {std::format("REGISTRY_HTTP_ADDR=0.0.0.0:{}", port)};
2231
- if (!username.empty())
2232
- {
2233
- env.push_back(std::format("USERNAME={}", username));
2234
- env.push_back(std::format("PASSWORD={}", password));
2235
- }
2236
-
2237
- wsl::windows::common::WSLCContainerLauncher launcher("wslc-registry:latest", {}, {}, env);
2238
- launcher.SetEntrypoint({"/entrypoint.sh"});
2239
- launcher.AddPort(port, port, AF_INET);
2240
-
2241
- // Get the IWSLCSession COM object from the SDK session handle.
2229
+ // Get the IWSLCSession COM object from the SDK session handle and delegate to the shared helper.
2230
auto& session = *reinterpret_cast<WslcSessionImpl*>(m_defaultSession)->session;
2243
- auto container = launcher.Launch(session, WSLCContainerStartFlagsNone);
2244
-
2245
- auto registryAddress = std::format("127.0.0.1:{}", port);
2246
-
2247
- // Wait for the registry to be ready by probing from the host.
2248
- auto hostUrl = std::format(L"http://{}", registryAddress);
2249
- ExpectHttpResponse(hostUrl.c_str(), 200, true);
2250
-
2251
- return {std::move(container), registryAddress};
2231
+ return WSLCE2ETests::StartLocalRegistry(session, username, password, port);
2232
}
2233
2234
// Tags and pushes an image to a local registry via the SDK APIs.
test/windows/WslcSdkWinRTTests.cpp
+3
-23
@@ -18,6 +18,7 @@ Abstract:
18
#include "WslcsdkPrivate.h"
19
#include "WSLCContainerLauncher.h"
20
#include "wslutil.h"
21
+#include "wslc/e2e/WSLCE2EHelpers.h"
22
23
#include "winrt/Session.h"
24
#include "winrt/Helpers.h"
@@ -171,30 +172,9 @@ class WslcSdkWinRtTests
172
std::pair<wsl::windows::common::RunningWSLCContainer, std::string> StartLocalRegistry(
173
const std::string& username = {}, const std::string& password = {}, uint16_t port = 5000)
174
{
174
- VERIFY_IS_TRUE(HasImage(L"wslc-registry:latest"));
175
-
176
- std::vector<std::string> env = {std::format("REGISTRY_HTTP_ADDR=0.0.0.0:{}", port)};
177
- if (!username.empty())
178
- {
179
- env.push_back(std::format("USERNAME={}", username));
180
- env.push_back(std::format("PASSWORD={}", password));
181
- }
182
-
183
- wsl::windows::common::WSLCContainerLauncher launcher("wslc-registry:latest", {}, {}, env);
184
- launcher.SetEntrypoint({"/entrypoint.sh"});
185
- launcher.AddPort(port, port, AF_INET);
186
-
187
- // Get the IWSLCSession COM object from the SDK session handle.
175
+ // Get the IWSLCSession COM object from the SDK session handle and delegate to the shared helper.
176
auto& comSession = *reinterpret_cast<WslcSessionImpl*>(WSLCSDK::implementation::GetHandle(m_defaultSession))->session;
189
- auto container = launcher.Launch(comSession, WSLCContainerStartFlagsNone);
190
-
191
- auto registryAddress = std::format("127.0.0.1:{}", port);
192
-
193
- // Wait for the registry to be ready by probing from the host.
194
- auto hostUrl = std::format(L"http://{}", registryAddress);
195
- ExpectHttpResponse(hostUrl.c_str(), 200, true);
196
-
197
- return {std::move(container), registryAddress};
177
+ return WSLCE2ETests::StartLocalRegistry(comSession, username, password, port);
178
}
179
180
// Tags and pushes an image to a local registry via the SDK APIs.
test/windows/wslc/e2e/WSLCE2EHelpers.cpp
+5
-1
@@ -519,7 +519,11 @@ std::pair<RunningWSLCContainer, std::string> StartLocalRegistry(IWSLCSession& se
519
launcher.SetEntrypoint({"/entrypoint.sh"});
520
launcher.AddPort(port, port, AF_INET);
521
522
- auto container = launcher.Launch(session, WSLCContainerStartFlagsNone);
522
+ auto container = launcher.Launch(session);
523
+
524
+ // Wait for the registry to bind the port before continuing.
525
+ auto initProcess = container.GetInitProcess();
526
+ WaitForOutput(initProcess.GetStdHandle(2), std::format("listening on [::]:{}", port));
527
528
auto address = std::format("127.0.0.1:{}", port);
529
auto url = std::format(L"http://{}/v2/", wsl::shared::string::MultiByteToWide(address));