Implement clean instance terminate when using systemd (#13552)

* Implement clean instance terminate when using systemd

* pr feedback

* more pr feedback

---------

Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
This commit is contained in:
Ben Hillis 2025-10-07 15:37:41 -07:00 committed by GitHub
parent 491d8d5707
commit 05d6129c4f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 57 additions and 16 deletions

View File

@ -129,6 +129,8 @@ void InitEntryUtilityVm(wsl::linux::WslDistributionConfig& Config);
void InitTerminateInstance(gsl::span<gsl::byte> Buffer, wsl::shared::SocketChannel& Channel, wsl::linux::WslDistributionConfig& Config);
void InitTerminateInstanceInternal(const wsl::linux::WslDistributionConfig& Config);
void InstallSystemdUnit(const char* Path, const std::string& Name, const char* Content);
int GenerateSystemdUnits(int Argc, char** Argv);
@ -2507,18 +2509,7 @@ Return Value:
}
}
//
// If the distro init process was booted, use the shutdown command to terminate the instance.
//
if (Config.BootInit && !Config.BootStartWriteSocket)
{
UtilExecCommandLine("systemctl reboot", nullptr);
}
reboot(RB_POWER_OFF);
FATAL_ERROR("reboot(RB_POWER_OFF) failed {}", errno);
InitTerminateInstanceInternal(Config);
return;
}
@ -2661,10 +2652,56 @@ try
}
//
// Respond to the instance termination request.
// Attempt to stop the plan9 server, if it is not able to be stopped because of an
// in-use file, reply to the service that the instance could not be terminated.
//
Channel.SendResultMessage<bool>(StopPlan9Server(Message->Force, Config));
if (!StopPlan9Server(Message->Force, Config))
{
Channel.SendResultMessage<bool>(false);
return;
}
InitTerminateInstanceInternal(Config);
}
CATCH_LOG();
void InitTerminateInstanceInternal(const wsl::linux::WslDistributionConfig& Config)
/*++
Routine Description:
This routine attempts to cleanly terminate the instance.
Arguments:
Config - Supplies the distribution config.
Return Value:
None.
--*/
try
{
//
// If systemd is enabled, attempt to poweroff the instance via systemctl.
//
if (Config.BootInit && !Config.BootStartWriteSocket)
{
THROW_LAST_ERROR_IF(UtilSetSignalHandlers(g_SavedSignalActions, false) < 0);
if (UtilExecCommandLine("systemctl poweroff", nullptr) == 0)
{
std::this_thread::sleep_for(std::chrono::milliseconds(Config.BootInitTimeout));
LOG_ERROR("systemctl poweroff did not terminate the instance in {} ms, calling reboot(RB_POWER_OFF)", Config.BootInitTimeout);
}
}
reboot(RB_POWER_OFF);
FATAL_ERROR("reboot(RB_POWER_OFF) failed {}", errno);
}
CATCH_LOG();

View File

@ -477,8 +477,12 @@ bool WslCoreInstance::RequestStop(_In_ bool Force)
terminateMessage.Header.MessageSize = sizeof(terminateMessage);
terminateMessage.Force = Force;
const auto& terminateResponse = m_initChannel->GetChannel().Transaction(terminateMessage, nullptr, m_socketTimeout);
shutdown = terminateResponse.Result;
m_initChannel->GetChannel().SendMessage(terminateMessage);
auto [message, span] = m_initChannel->GetChannel().ReceiveMessageOrClosed<RESULT_MESSAGE<bool>>(m_socketTimeout);
if (message)
{
shutdown = message->Result;
}
}
CATCH_LOG()