Fix timeout, state, etc.

This commit is contained in:
Pooja Trivedi 2025-12-09 00:22:07 -05:00
parent 38d53f6f6d
commit c614d36fc9
5 changed files with 23 additions and 9 deletions

View File

@ -118,6 +118,11 @@ std::string WSLAProcessLauncher::FormatResult(const RunningWSLAProcess::ProcessR
stdErr != result.Output.end() ? stdErr->second : "<none>");
}
std::string WSLAProcessLauncher::FormatResult(const int code)
{
return std::format("{} [{}] exited with: {}.", m_executable, wsl::shared::string::Join(m_arguments, ','), code);
}
std::pair<int, bool> RunningWSLAProcess::Wait(DWORD TimeoutMs)
{
THROW_HR_IF(HRESULT_FROM_WIN32(ERROR_TIMEOUT), !GetExitEvent().wait(TimeoutMs));

View File

@ -95,6 +95,7 @@ public:
ClientRunningWSLAProcess Launch(IWSLASession& Session);
std::tuple<HRESULT, int, std::optional<ClientRunningWSLAProcess>> LaunchNoThrow(IWSLASession& Session);
std::string FormatResult(const RunningWSLAProcess::ProcessResult& result);
std::string FormatResult(const int code);
protected:
std::tuple<WSLA_PROCESS_OPTIONS, std::vector<const char*>, std::vector<const char*>> CreateProcessOptions();

View File

@ -73,6 +73,11 @@ try
{
std::lock_guard lock{m_lock};
if (StateNoLock() == WslaContainerStateExited)
{
return S_OK;
}
/* 'nerdctl stop ...'
* returns success and <containerId> on stdout if the container is running or already stopped
* returns error "No such container: <containerId>" on stderr if the container is in 'Created' state or does not exist
@ -82,10 +87,6 @@ try
* TODO: Discuss and return stdout/stderr or corresponding HRESULT from nerdctl stop for better diagnostics.
*/
if (m_state == WslaContainerStateExited)
{
return S_OK;
}
// Validate that the container is in the running state.
RETURN_HR_IF_MSG(
HRESULT_FROM_WIN32(ERROR_INVALID_STATE),
@ -97,8 +98,8 @@ try
// TODO: Figure out how we want to handle custom signals and timeout values.
// nerdctl stop has a --time and a --signal option that can be used
// By default, it uses SIGTERM and a default timeout of 10 seconds.
auto result = launcher.Launch(*m_parentVM).Wait();
THROW_HR_IF(E_FAIL, result.first != 0);
auto result = launcher.Launch(*m_parentVM).Wait(TimeoutMs);
THROW_HR_IF_MSG(E_FAIL, result.first != 0, "%hs", launcher.FormatResult(result.first).c_str());
m_state = WslaContainerStateExited;
return S_OK;
@ -131,6 +132,12 @@ WSLA_CONTAINER_STATE WSLAContainer::State() noexcept
{
std::lock_guard lock{m_lock};
// If the container is running, refresh the init process state before returning.
return StateNoLock();
}
WSLA_CONTAINER_STATE WSLAContainer::StateNoLock() noexcept
{
// If the container is running, refresh the init process state before returning.
if (m_state == WslaContainerStateRunning && m_containerProcess.State() != WSLAProcessStateRunning)
{

View File

@ -50,6 +50,7 @@ private:
WSLAVirtualMachine* m_parentVM = nullptr;
std::mutex m_lock;
WSLA_CONTAINER_STATE StateNoLock() noexcept;
static std::vector<std::string> PrepareNerdctlRunCommand(const WSLA_CONTAINER_OPTIONS& options, std::vector<std::string>&& inputOptions);
};
} // namespace wsl::windows::service::wsla

View File

@ -1244,7 +1244,7 @@ class WSLATests
// Verify that the container is in running state.
VERIFY_ARE_EQUAL(container.State(), WslaContainerStateRunning);
VERIFY_SUCCEEDED(container.Get().Stop(9, 10000));
VERIFY_SUCCEEDED(container.Get().Stop(15, 50000));
// TODO: Once 'container run' is split into 'container create' + 'container start',
// validate that Stop() on a container in 'Created' state returns ERROR_INVALID_STATE.
@ -1304,14 +1304,14 @@ class WSLATests
{"test-unique-name", "debian:latest", WslaContainerStateExited}});
// Verify that calling Stop() on exited containers is a no-op and state remains as WslaContainerStateExited.
VERIFY_SUCCEEDED(container.Get().Stop(15, 1000));
VERIFY_SUCCEEDED(container.Get().Stop(15, 50000));
VERIFY_ARE_EQUAL(container.State(), WslaContainerStateExited);
// Verify that stopped containers can be deleted.
VERIFY_SUCCEEDED(container.Get().Delete());
// Verify that stopping a deleted container returns ERROR_INVALID_STATE.
VERIFY_ARE_EQUAL(container.Get().Stop(15, 1000), HRESULT_FROM_WIN32(ERROR_INVALID_STATE));
VERIFY_ARE_EQUAL(container.Get().Stop(15, 50000), HRESULT_FROM_WIN32(ERROR_INVALID_STATE));
// Verify that deleted containers can't be deleted again.
VERIFY_ARE_EQUAL(container.Get().Delete(), HRESULT_FROM_WIN32(ERROR_INVALID_STATE));