From 05d6129c4fca74b29132fb7c78fe7e4d3b4d37c1 Mon Sep 17 00:00:00 2001 From: Ben Hillis Date: Tue, 7 Oct 2025 15:37:41 -0700 Subject: [PATCH] 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 --- src/linux/init/init.cpp | 65 ++++++++++++++++----- src/windows/service/exe/WslCoreInstance.cpp | 8 ++- 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/src/linux/init/init.cpp b/src/linux/init/init.cpp index 8a48195..77495eb 100644 --- a/src/linux/init/init.cpp +++ b/src/linux/init/init.cpp @@ -129,6 +129,8 @@ void InitEntryUtilityVm(wsl::linux::WslDistributionConfig& Config); void InitTerminateInstance(gsl::span 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(StopPlan9Server(Message->Force, Config)); + if (!StopPlan9Server(Message->Force, Config)) + { + Channel.SendResultMessage(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(); diff --git a/src/windows/service/exe/WslCoreInstance.cpp b/src/windows/service/exe/WslCoreInstance.cpp index 1765c55..7dec7f5 100644 --- a/src/windows/service/exe/WslCoreInstance.cpp +++ b/src/windows/service/exe/WslCoreInstance.cpp @@ -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>(m_socketTimeout); + if (message) + { + shutdown = message->Result; + } } CATCH_LOG()