diff --git a/src/windows/wslc/services/ContainerService.cpp b/src/windows/wslc/services/ContainerService.cpp index ed248a0f1..9d39c5174 100644 --- a/src/windows/wslc/services/ContainerService.cpp +++ b/src/windows/wslc/services/ContainerService.cpp @@ -287,7 +287,6 @@ int ContainerService::Run(Session& session, const std::string& image, ContainerO { // Create the container auto runningContainer = CreateInternal(session, image, runOptions); - runningContainer.SetDeleteOnClose(false); auto& container = runningContainer.Get(); // Start the created container @@ -295,6 +294,9 @@ int ContainerService::Run(Session& session, const std::string& image, ContainerO WI_SetFlagIf(startFlags, WSLCContainerStartFlagsAttach, !runOptions.Detach); THROW_IF_FAILED(container.Start(startFlags, nullptr)); // TODO: Error message, detach keys + // Disable auto-delete only after successful start + runningContainer.SetDeleteOnClose(false); + // Handle attach if requested if (WI_IsFlagSet(startFlags, WSLCContainerStartFlagsAttach)) { diff --git a/src/windows/wslcsession/WSLCContainer.cpp b/src/windows/wslcsession/WSLCContainer.cpp index 35d3000a0..9ea93e496 100644 --- a/src/windows/wslcsession/WSLCContainer.cpp +++ b/src/windows/wslcsession/WSLCContainer.cpp @@ -1274,12 +1274,10 @@ std::unique_ptr WSLCContainerImpl::Open( { auto allocation = virtualMachine.TryAllocatePort(e.VmPort, e.Family, e.Protocol); - THROW_HR_IF_MSG( + THROW_HR_WITH_USER_ERROR_IF( HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS), - !allocation, - "Port %hu is in use, cannot open container %hs", - e.VmPort, - dockerContainer.Id.c_str()); + std::format(L"Port {} is already in use, cannot open container {}", e.VmPort, dockerContainer.Id), + !allocation); inserted.VmMapping.AssignVmPort(allocation); } @@ -1443,12 +1441,10 @@ void WSLCContainerImpl::MapPorts() auto allocatedPort = m_virtualMachine.TryAllocatePort(e.ContainerPort, e.VmMapping.BindAddress.si_family, e.VmMapping.Protocol); - THROW_HR_IF_MSG( + THROW_HR_WITH_USER_ERROR_IF( HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS), - !allocatedPort, - "Port %hu is in use, cannot start container %hs", - e.ContainerPort, - m_id.c_str()); + std::format(L"Port {} is already in use, cannot start container {}", e.VmMapping.HostPort(), m_id), + !allocatedPort); e.VmMapping.AssignVmPort(allocatedPort); @@ -1456,7 +1452,20 @@ void WSLCContainerImpl::MapPorts() } } - m_virtualMachine.MapPort(e.VmMapping); + try + { + m_virtualMachine.MapPort(e.VmMapping); + } + catch (const wil::ResultException& ex) + { + if (ex.GetErrorCode() == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) || ex.GetErrorCode() == HRESULT_FROM_WIN32(WSAEADDRINUSE)) + { + THROW_HR_WITH_USER_ERROR( + HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS), + std::format(L"Port {} is already in use, cannot start container {}", e.VmMapping.HostPort(), m_id)); + } + throw; + } } } diff --git a/test/windows/wslc/e2e/WSLCE2EContainerCreateTests.cpp b/test/windows/wslc/e2e/WSLCE2EContainerCreateTests.cpp index d1cc2e2ea..e6bfdcff7 100644 --- a/test/windows/wslc/e2e/WSLCE2EContainerCreateTests.cpp +++ b/test/windows/wslc/e2e/WSLCE2EContainerCreateTests.cpp @@ -988,8 +988,6 @@ class WSLCE2EContainerCreateTests TEST_METHOD(WSLCE2E_Container_Run_PortAlreadyInUse) { // Bug: https://github.com/microsoft/WSL/issues/14448 - SKIP_TEST_NOT_IMPL(); - WSL2_TEST_ONLY(); // Start a container with a simple server listening on a port @@ -1002,9 +1000,16 @@ class WSLCE2EContainerCreateTests GetPythonHttpServerScript(ContainerTestPort))); result1.Verify({.Stderr = L"", .ExitCode = 0}); + auto containersBefore = ListAllContainers().size(); + // Attempt to start another container mapping the same host port auto result2 = RunWslc(std::format(L"container run -p {}:{} {}", HostTestPort1, ContainerTestPort, DebianImage.NameAndTag())); result2.Verify({.ExitCode = 1}); + VERIFY_IS_TRUE(result2.Stderr.has_value() && result2.Stderr.value().find(L"is already in use") != std::wstring::npos); + + // Verify the failed container was not left behind + auto containersAfter = ListAllContainers().size(); + VERIFY_ARE_EQUAL(containersBefore, containersAfter); } // https://github.com/microsoft/WSL/issues/14433