From cebe0be2cd9dadf6d87086620114f1de1289b940 Mon Sep 17 00:00:00 2001 From: Blue Date: Mon, 21 Sep 2026 14:34:35 -0700 Subject: [PATCH 1/3] Save state --- src/windows/service/exe/LxssUserSession.cpp | 81 +++++++++++++++++++-- src/windows/service/exe/LxssUserSession.h | 17 ++++- test/windows/UnitTests.cpp | 3 + 3 files changed, 92 insertions(+), 9 deletions(-) diff --git a/src/windows/service/exe/LxssUserSession.cpp b/src/windows/service/exe/LxssUserSession.cpp index 5b31400193..e825a46584 100644 --- a/src/windows/service/exe/LxssUserSession.cpp +++ b/src/windows/service/exe/LxssUserSession.cpp @@ -1066,6 +1066,7 @@ HRESULT LxssUserSessionImpl::ExportDistribution(_In_opt_ LPCGUID DistroGuid, _In RETURN_HR_IF(E_INVALIDARG, (WI_IsAnyFlagSet(Flags, ~LXSS_EXPORT_DISTRO_FLAGS_ALL))); LXSS_DISTRO_CONFIGURATION configuration; + std::optional pidTermination; wil::unique_hkey distroKey; try { @@ -1086,12 +1087,13 @@ HRESULT LxssUserSessionImpl::ExportDistribution(_In_opt_ LPCGUID DistroGuid, _In RETURN_HR_IF(WSL_E_WSL1_NOT_SUPPORTED, WI_IsFlagClear(configuration.Flags, LXSS_DISTRO_FLAGS_VM_MODE) && !g_lxcoreInitialized); // Add the distribution to the list of converting distributions. - _ConversionBegin(configuration.DistroId, LxssDistributionStateExporting); + pidTermination = _ConversionBegin(configuration.DistroId, LxssDistributionStateExporting); } CATCH_RETURN() // Set up a scope exit member to remove the distribution from the converting list. auto exportComplete = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&] { _ConversionComplete(configuration.DistroId); }); + RETURN_IF_FAILED(_WaitForPidTermination(pidTermination)); // Log telemetry to track how long exporting the distribution takes. WSL_LOG_TELEMETRY( @@ -1472,6 +1474,7 @@ HRESULT LxssUserSessionImpl::RegisterDistribution( DistributionRegistration registration; LXSS_DISTRO_CONFIGURATION configuration; + std::optional pidTermination; std::filesystem::path distributionPath; auto config = _GetResultantConfig(userToken.get()); @@ -1537,11 +1540,12 @@ HRESULT LxssUserSessionImpl::RegisterDistribution( configuration = s_GetDistributionConfiguration(registration, DistributionName == nullptr); // Add the distribution to the list of converting distributions. - _ConversionBegin(configuration.DistroId, LxssDistributionStateInstalling); + pidTermination = _ConversionBegin(configuration.DistroId, LxssDistributionStateInstalling); } // Set up a scope exit member to remove the distribution from the converting list. auto installComplete = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&] { _ConversionComplete(configuration.DistroId); }); + THROW_IF_FAILED(_WaitForPidTermination(pidTermination)); // Declare a scope exit variable to clean up on failure. ULONG deleteFlags = 0; @@ -1872,10 +1876,11 @@ try auto runAsUser = wil::CoImpersonateClient(); std::filesystem::path vhdPath; LXSS_DISTRO_CONFIGURATION configuration{}; + std::optional pidTermination; + const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation); { std::lock_guard lock(m_instanceLock); - const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation); const wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get()); const auto registration = DistributionRegistration::Open(lxssKey.get(), *DistroGuid); configuration = s_GetDistributionConfiguration(registration); @@ -1887,8 +1892,14 @@ try THROW_HR_WITH_USER_ERROR(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), wsl::shared::Localization::MessageCompactVhdNotSupported()); } - _ConversionBegin(configuration.DistroId, LxssDistributionStateCompacting); + pidTermination = _ConversionBegin(configuration.DistroId, LxssDistributionStateCompacting); + } + + auto compactionComplete = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&] { _ConversionComplete(configuration.DistroId); }); + THROW_IF_FAILED(_WaitForPidTermination(pidTermination)); + { + std::lock_guard lock(m_instanceLock); // Trim the filesystem before compaction so the host can reclaim the freed blocks. // // WSL2 does not mount ext4 with 'discard' and does not run fsck at boot, so blocks freed @@ -1908,8 +1919,6 @@ try CATCH_LOG(); } - auto compactionComplete = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&] { _ConversionComplete(configuration.DistroId); }); - THROW_IF_FAILED_MSG( wil::ResultFromException([&] { wsl::core::filesystem::CompactVhd(vhdPath.c_str()); }), "Failed to compact VHD: %ls", @@ -1924,6 +1933,7 @@ HRESULT LxssUserSessionImpl::SetVersion(_In_ LPCGUID DistroGuid, _In_ ULONG Vers DistributionRegistration registration; LXSS_DISTRO_CONFIGURATION configuration; + std::optional pidTermination; const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation); wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get()); try @@ -1953,7 +1963,7 @@ HRESULT LxssUserSessionImpl::SetVersion(_In_ LPCGUID DistroGuid, _In_ ULONG Vers RETURN_HR_IF(WSL_E_WSL1_NOT_SUPPORTED, !g_lxcoreInitialized); // Add the distribution to the list of converting distributions. - _ConversionBegin(configuration.DistroId, LxssDistributionStateConverting); + pidTermination = _ConversionBegin(configuration.DistroId, LxssDistributionStateConverting); // Remove the distribution ID from m_updatedInitDistros so init is updated on the next launch (in the case of a conversion to WSL1). m_updatedInitDistros.erase( @@ -1963,6 +1973,7 @@ HRESULT LxssUserSessionImpl::SetVersion(_In_ LPCGUID DistroGuid, _In_ ULONG Vers // Set up a scope exit member to remove the distribution from the converting list. auto conversionComplete = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&] { _ConversionComplete(configuration.DistroId); }); + RETURN_IF_FAILED(_WaitForPidTermination(pidTermination)); // Log telemetry to track how long enabling VM mode takes. WSL_LOG_TELEMETRY( @@ -2513,11 +2524,29 @@ HRESULT LxssUserSessionImpl::UnregisterDistribution(_In_ LPCGUID DistroGuid) } _Requires_lock_held_(m_instanceLock) -void LxssUserSessionImpl::_ConversionBegin(_In_ GUID DistroGuid, _In_ LxssDistributionState State) +std::optional LxssUserSessionImpl::_ConversionBegin(_In_ GUID DistroGuid, _In_ LxssDistributionState State) { _EnsureNotLocked(&DistroGuid); + + std::optional pidTermination; + const auto instance = m_runningInstances.find(DistroGuid); + if (instance != m_runningInstances.end()) + { + if (const auto* wslcoreInstance = dynamic_cast(instance->second.get()); wslcoreInstance != nullptr) + { + PidTermination termination; + termination.ClientId = wslcoreInstance->GetClientId(); + termination.Timeout = gsl::narrow_cast(m_utilityVm->GetConfig().DistributionStartTimeout); + + const auto [_, inserted] = m_pidTerminations.emplace(termination.ClientId, termination.Event); + THROW_HR_IF(E_UNEXPECTED, !inserted); + pidTermination.emplace(std::move(termination)); + } + } + _TerminateInstanceInternal(&DistroGuid); m_lockedDistributions.emplace_back(DistroGuid, State); + return pidTermination; } _Requires_lock_not_held_(m_instanceLock) @@ -2529,6 +2558,36 @@ void LxssUserSessionImpl::_ConversionComplete(_In_ GUID DistroGuid) _VmCheckIdle(); } +_Requires_lock_not_held_(m_instanceLock) +HRESULT LxssUserSessionImpl::_WaitForPidTermination(_In_ const std::optional& PidTermination) +try +{ + if (!PidTermination.has_value()) + { + return S_OK; + } + + SlowOperationWatcher slowOperation{"WaitForPidTermination"}; + const bool terminated = PidTermination->Event.wait(PidTermination->Timeout); + slowOperation.Reset(); + + { + std::lock_guard lock(m_instanceLock); + m_pidTerminations.erase(PidTermination->ClientId); + } + + if (!terminated) + { + WSL_LOG( + "PidTerminationTimeout", + TraceLoggingValue(PidTermination->ClientId, "pid"), + TraceLoggingValue(PidTermination->Timeout, "timeout")); + } + + return S_OK; +} +CATCH_RETURN() + _Requires_exclusive_lock_held_(m_instanceLock) void LxssUserSessionImpl::_CreateLegacyRegistration(_In_ HKEY LxssKey, _In_ HANDLE UserToken) { @@ -3037,6 +3096,12 @@ void LxssUserSessionImpl::_CreateVm() } auto unlock = wil::scope_exit([&]() { m_instanceLock.unlock(); }); + if (const auto termination = m_pidTerminations.find(Pid); termination != m_pidTerminations.end()) + { + termination->second.SetEvent(); + m_pidTerminations.erase(termination); + } + TerminateByClientIdLockHeld(Pid); }; diff --git a/src/windows/service/exe/LxssUserSession.h b/src/windows/service/exe/LxssUserSession.h index 67908c4a6e..55dcfd9307 100644 --- a/src/windows/service/exe/LxssUserSession.h +++ b/src/windows/service/exe/LxssUserSession.h @@ -544,11 +544,18 @@ class LxssUserSessionImpl : public std::enable_shared_from_this /// Adds a distro to the list of converting distros. /// _Requires_lock_held_(m_instanceLock) - void _ConversionBegin(_In_ GUID DistroGuid, _In_ LxssDistributionState State); + std::optional _ConversionBegin(_In_ GUID DistroGuid, _In_ LxssDistributionState State); /// /// Removes a distro from the list of converting distros and checks if the @@ -557,6 +564,9 @@ class LxssUserSessionImpl : public std::enable_shared_from_this& PidTermination); + /// /// Creates a distribution registration for legacy installs. /// @@ -822,6 +832,11 @@ class LxssUserSessionImpl : public std::enable_shared_from_this _Guarded_by_(m_instanceLock) std::list> m_lockedDistributions; + /// + /// Contains waiters for processes that must fully exit before their VHD can be reused. + /// + _Guarded_by_(m_instanceLock) std::map m_pidTerminations; + /// /// The running utility vm for WSL2 distributions. /// diff --git a/test/windows/UnitTests.cpp b/test/windows/UnitTests.cpp index 7969437552..75b9a14816 100644 --- a/test/windows/UnitTests.cpp +++ b/test/windows/UnitTests.cpp @@ -112,6 +112,9 @@ class UnitTests LOG_IF_WIN32_BOOL_FALSE(DeleteFile(vhdPath)); }); + // Export must wait for the running distribution to fully exit before reusing its VHD. + VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"true"), 0L); + { auto [out, err] = LxsstuLaunchWslAndCaptureOutput(std::format(L"--export {} {}", LXSS_DISTRO_NAME_TEST_L, tarPath)); From 1df7fe318c4eb27060407b4a07d5963777bf7d32 Mon Sep 17 00:00:00 2001 From: Blue Date: Mon, 21 Sep 2026 16:43:19 -0700 Subject: [PATCH 2/3] Cover all code paths --- src/windows/service/exe/LxssUserSession.cpp | 98 +++++++++++---------- src/windows/service/exe/LxssUserSession.h | 9 +- 2 files changed, 55 insertions(+), 52 deletions(-) diff --git a/src/windows/service/exe/LxssUserSession.cpp b/src/windows/service/exe/LxssUserSession.cpp index e825a46584..36e5d13e82 100644 --- a/src/windows/service/exe/LxssUserSession.cpp +++ b/src/windows/service/exe/LxssUserSession.cpp @@ -1066,7 +1066,7 @@ HRESULT LxssUserSessionImpl::ExportDistribution(_In_opt_ LPCGUID DistroGuid, _In RETURN_HR_IF(E_INVALIDARG, (WI_IsAnyFlagSet(Flags, ~LXSS_EXPORT_DISTRO_FLAGS_ALL))); LXSS_DISTRO_CONFIGURATION configuration; - std::optional pidTermination; + std::vector pidTerminations; wil::unique_hkey distroKey; try { @@ -1087,13 +1087,13 @@ HRESULT LxssUserSessionImpl::ExportDistribution(_In_opt_ LPCGUID DistroGuid, _In RETURN_HR_IF(WSL_E_WSL1_NOT_SUPPORTED, WI_IsFlagClear(configuration.Flags, LXSS_DISTRO_FLAGS_VM_MODE) && !g_lxcoreInitialized); // Add the distribution to the list of converting distributions. - pidTermination = _ConversionBegin(configuration.DistroId, LxssDistributionStateExporting); + pidTerminations = _ConversionBegin(configuration.DistroId, LxssDistributionStateExporting); } CATCH_RETURN() // Set up a scope exit member to remove the distribution from the converting list. auto exportComplete = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&] { _ConversionComplete(configuration.DistroId); }); - RETURN_IF_FAILED(_WaitForPidTermination(pidTermination)); + RETURN_IF_FAILED(_WaitForPidTerminations(pidTerminations)); // Log telemetry to track how long exporting the distribution takes. WSL_LOG_TELEMETRY( @@ -1474,7 +1474,7 @@ HRESULT LxssUserSessionImpl::RegisterDistribution( DistributionRegistration registration; LXSS_DISTRO_CONFIGURATION configuration; - std::optional pidTermination; + std::vector pidTerminations; std::filesystem::path distributionPath; auto config = _GetResultantConfig(userToken.get()); @@ -1540,12 +1540,12 @@ HRESULT LxssUserSessionImpl::RegisterDistribution( configuration = s_GetDistributionConfiguration(registration, DistributionName == nullptr); // Add the distribution to the list of converting distributions. - pidTermination = _ConversionBegin(configuration.DistroId, LxssDistributionStateInstalling); + pidTerminations = _ConversionBegin(configuration.DistroId, LxssDistributionStateInstalling); } // Set up a scope exit member to remove the distribution from the converting list. auto installComplete = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&] { _ConversionComplete(configuration.DistroId); }); - THROW_IF_FAILED(_WaitForPidTermination(pidTermination)); + THROW_IF_FAILED(_WaitForPidTerminations(pidTerminations)); // Declare a scope exit variable to clean up on failure. ULONG deleteFlags = 0; @@ -1876,7 +1876,7 @@ try auto runAsUser = wil::CoImpersonateClient(); std::filesystem::path vhdPath; LXSS_DISTRO_CONFIGURATION configuration{}; - std::optional pidTermination; + std::vector pidTerminations; const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation); { @@ -1892,11 +1892,11 @@ try THROW_HR_WITH_USER_ERROR(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED), wsl::shared::Localization::MessageCompactVhdNotSupported()); } - pidTermination = _ConversionBegin(configuration.DistroId, LxssDistributionStateCompacting); + pidTerminations = _ConversionBegin(configuration.DistroId, LxssDistributionStateCompacting); } auto compactionComplete = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&] { _ConversionComplete(configuration.DistroId); }); - THROW_IF_FAILED(_WaitForPidTermination(pidTermination)); + THROW_IF_FAILED(_WaitForPidTerminations(pidTerminations)); { std::lock_guard lock(m_instanceLock); @@ -1933,7 +1933,7 @@ HRESULT LxssUserSessionImpl::SetVersion(_In_ LPCGUID DistroGuid, _In_ ULONG Vers DistributionRegistration registration; LXSS_DISTRO_CONFIGURATION configuration; - std::optional pidTermination; + std::vector pidTerminations; const auto userToken = wsl::windows::common::security::GetUserToken(TokenImpersonation); wil::unique_hkey lxssKey = s_OpenLxssUserKey(userToken.get()); try @@ -1963,7 +1963,7 @@ HRESULT LxssUserSessionImpl::SetVersion(_In_ LPCGUID DistroGuid, _In_ ULONG Vers RETURN_HR_IF(WSL_E_WSL1_NOT_SUPPORTED, !g_lxcoreInitialized); // Add the distribution to the list of converting distributions. - pidTermination = _ConversionBegin(configuration.DistroId, LxssDistributionStateConverting); + pidTerminations = _ConversionBegin(configuration.DistroId, LxssDistributionStateConverting); // Remove the distribution ID from m_updatedInitDistros so init is updated on the next launch (in the case of a conversion to WSL1). m_updatedInitDistros.erase( @@ -1973,7 +1973,7 @@ HRESULT LxssUserSessionImpl::SetVersion(_In_ LPCGUID DistroGuid, _In_ ULONG Vers // Set up a scope exit member to remove the distribution from the converting list. auto conversionComplete = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&] { _ConversionComplete(configuration.DistroId); }); - RETURN_IF_FAILED(_WaitForPidTermination(pidTermination)); + RETURN_IF_FAILED(_WaitForPidTerminations(pidTerminations)); // Log telemetry to track how long enabling VM mode takes. WSL_LOG_TELEMETRY( @@ -2524,29 +2524,22 @@ HRESULT LxssUserSessionImpl::UnregisterDistribution(_In_ LPCGUID DistroGuid) } _Requires_lock_held_(m_instanceLock) -std::optional LxssUserSessionImpl::_ConversionBegin(_In_ GUID DistroGuid, _In_ LxssDistributionState State) +std::vector LxssUserSessionImpl::_ConversionBegin(_In_ GUID DistroGuid, _In_ LxssDistributionState State) { _EnsureNotLocked(&DistroGuid); + _TerminateInstanceInternal(&DistroGuid); - std::optional pidTermination; - const auto instance = m_runningInstances.find(DistroGuid); - if (instance != m_runningInstances.end()) + std::vector pidTerminations; + for (const auto& termination : m_pidTerminations) { - if (const auto* wslcoreInstance = dynamic_cast(instance->second.get()); wslcoreInstance != nullptr) + if (IsEqualGUID(termination.second.DistroId, DistroGuid)) { - PidTermination termination; - termination.ClientId = wslcoreInstance->GetClientId(); - termination.Timeout = gsl::narrow_cast(m_utilityVm->GetConfig().DistributionStartTimeout); - - const auto [_, inserted] = m_pidTerminations.emplace(termination.ClientId, termination.Event); - THROW_HR_IF(E_UNEXPECTED, !inserted); - pidTermination.emplace(std::move(termination)); + pidTerminations.push_back(termination.second); } } - _TerminateInstanceInternal(&DistroGuid); m_lockedDistributions.emplace_back(DistroGuid, State); - return pidTermination; + return pidTerminations; } _Requires_lock_not_held_(m_instanceLock) @@ -2559,29 +2552,24 @@ void LxssUserSessionImpl::_ConversionComplete(_In_ GUID DistroGuid) } _Requires_lock_not_held_(m_instanceLock) -HRESULT LxssUserSessionImpl::_WaitForPidTermination(_In_ const std::optional& PidTermination) +HRESULT LxssUserSessionImpl::_WaitForPidTerminations(_In_ const std::vector& PidTerminations) try { - if (!PidTermination.has_value()) - { - return S_OK; - } - SlowOperationWatcher slowOperation{"WaitForPidTermination"}; - const bool terminated = PidTermination->Event.wait(PidTermination->Timeout); - slowOperation.Reset(); - - { - std::lock_guard lock(m_instanceLock); - m_pidTerminations.erase(PidTermination->ClientId); - } - - if (!terminated) + const auto startTime = GetTickCount64(); + for (const auto& termination : PidTerminations) { - WSL_LOG( - "PidTerminationTimeout", - TraceLoggingValue(PidTermination->ClientId, "pid"), - TraceLoggingValue(PidTermination->Timeout, "timeout")); + const auto elapsed = GetTickCount64() - startTime; + const auto timeout = termination.Timeout == INFINITE ? INFINITE + : elapsed >= termination.Timeout ? 0 + : termination.Timeout - gsl::narrow_cast(elapsed); + if (!termination.Event.wait(timeout)) + { + WSL_LOG( + "PidTerminationTimeout", + TraceLoggingValue(termination.ClientId, "pid"), + TraceLoggingValue(termination.Timeout, "timeout")); + } } return S_OK; @@ -3096,13 +3084,13 @@ void LxssUserSessionImpl::_CreateVm() } auto unlock = wil::scope_exit([&]() { m_instanceLock.unlock(); }); + TerminateByClientIdLockHeld(Pid); + if (const auto termination = m_pidTerminations.find(Pid); termination != m_pidTerminations.end()) { - termination->second.SetEvent(); + termination->second.Event.SetEvent(); m_pidTerminations.erase(termination); } - - TerminateByClientIdLockHeld(Pid); }; // N.B. The callbacks must be registered outside of the above try/catch. @@ -3801,6 +3789,13 @@ bool LxssUserSessionImpl::_TerminateInstanceInternal(_In_ LPCGUID DistroGuid, _I { if (const auto* wslcoreInstance = dynamic_cast(instance->second.get()); wslcoreInstance != nullptr) { + // Stop releases the system distro, so capture its PID while it is still available. + PidTermination termination; + termination.DistroId = *DistroGuid; + termination.ClientId = wslcoreInstance->GetClientId(); + termination.Timeout = gsl::narrow_cast(m_utilityVm->GetConfig().DistributionStartTimeout); + m_pidTerminations.try_emplace(termination.ClientId, std::move(termination)); + m_pluginManager.OnDistributionStopping(&m_session, wslcoreInstance->DistributionInformation()); } @@ -4103,6 +4098,13 @@ void LxssUserSessionImpl::_VmTerminate() m_utilityVm.reset(); m_vmId.store(GUID_NULL); + // VM teardown cancels exit callbacks, so complete any remaining waiters after the VM has released its resources. + for (const auto& termination : m_pidTerminations) + { + termination.second.Event.SetEvent(); + } + m_pidTerminations.clear(); + // Reset the user's token since its lifetime is tied to the VM. m_userToken.reset(); m_session.UserToken = nullptr; diff --git a/src/windows/service/exe/LxssUserSession.h b/src/windows/service/exe/LxssUserSession.h index 55dcfd9307..4466ba6a8b 100644 --- a/src/windows/service/exe/LxssUserSession.h +++ b/src/windows/service/exe/LxssUserSession.h @@ -546,6 +546,7 @@ class LxssUserSessionImpl : public std::enable_shared_from_this _Requires_lock_held_(m_instanceLock) - std::optional _ConversionBegin(_In_ GUID DistroGuid, _In_ LxssDistributionState State); + std::vector _ConversionBegin(_In_ GUID DistroGuid, _In_ LxssDistributionState State); /// /// Removes a distro from the list of converting distros and checks if the @@ -565,7 +566,7 @@ class LxssUserSessionImpl : public std::enable_shared_from_this& PidTermination); + HRESULT _WaitForPidTerminations(_In_ const std::vector& PidTerminations); /// /// Creates a distribution registration for legacy installs. @@ -833,9 +834,9 @@ class LxssUserSessionImpl : public std::enable_shared_from_this> m_lockedDistributions; /// - /// Contains waiters for processes that must fully exit before their VHD can be reused. + /// Contains pending WSL2 exits until their exit notification or VM teardown, even if a conversion wait times out. /// - _Guarded_by_(m_instanceLock) std::map m_pidTerminations; + _Guarded_by_(m_instanceLock) std::map m_pidTerminations; /// /// The running utility vm for WSL2 distributions. From 83e8fb76618c1cc7740fd7a738aea78804b18cc3 Mon Sep 17 00:00:00 2001 From: Blue Date: Mon, 21 Sep 2026 16:44:23 -0700 Subject: [PATCH 3/3] Cleanup diff --- test/windows/UnitTests.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/windows/UnitTests.cpp b/test/windows/UnitTests.cpp index 75b9a14816..7969437552 100644 --- a/test/windows/UnitTests.cpp +++ b/test/windows/UnitTests.cpp @@ -112,9 +112,6 @@ class UnitTests LOG_IF_WIN32_BOOL_FALSE(DeleteFile(vhdPath)); }); - // Export must wait for the running distribution to fully exit before reusing its VHD. - VERIFY_ARE_EQUAL(LxsstuLaunchWsl(L"true"), 0L); - { auto [out, err] = LxsstuLaunchWslAndCaptureOutput(std::format(L"--export {} {}", LXSS_DISTRO_NAME_TEST_L, tarPath));