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>

Ben Hillis committed Oct 7, 2025 at 15:37 UTC 05d6129c4fca74b29132fb7c78fe7e4d3b4d37c1
2 files changed +57 -16
src/linux/init/init.cpp
+51 -14
@@ -129,6 +129,8 @@ void InitEntryUtilityVm(wsl::linux::WslDistributionConfig& Config);
129
130 void InitTerminateInstance(gsl::span<gsl::byte> Buffer, wsl::shared::SocketChannel& Channel, wsl::linux::WslDistributionConfig& Config);
131
132 +void InitTerminateInstanceInternal(const wsl::linux::WslDistributionConfig& Config);
133 +
134 void InstallSystemdUnit(const char* Path, const std::string& Name, const char* Content);
135
136 int GenerateSystemdUnits(int Argc, char** Argv);
@@ -2507,18 +2509,7 @@ Return Value:
2509 }
2510 }
2511
2510 - //
2511 - // If the distro init process was booted, use the shutdown command to terminate the instance.
2512 - //
2513 -
2514 - if (Config.BootInit && !Config.BootStartWriteSocket)
2515 - {
2516 - UtilExecCommandLine("systemctl reboot", nullptr);
2517 - }
2518 -
2519 - reboot(RB_POWER_OFF);
2520 - FATAL_ERROR("reboot(RB_POWER_OFF) failed {}", errno);
2521 -
2512 + InitTerminateInstanceInternal(Config);
2513 return;
2514 }
2515
@@ -2661,10 +2652,56 @@ try
2652 }
2653
2654 //
2664 - // Respond to the instance termination request.
2655 + // Attempt to stop the plan9 server, if it is not able to be stopped because of an
2656 + // in-use file, reply to the service that the instance could not be terminated.
2657 //
2658
2667 - Channel.SendResultMessage<bool>(StopPlan9Server(Message->Force, Config));
2659 + if (!StopPlan9Server(Message->Force, Config))
2660 + {
2661 + Channel.SendResultMessage<bool>(false);
2662 + return;
2663 + }
2664 +
2665 + InitTerminateInstanceInternal(Config);
2666 +}
2667 +CATCH_LOG();
2668 +
2669 +void InitTerminateInstanceInternal(const wsl::linux::WslDistributionConfig& Config)
2670 +
2671 +/*++
2672 +
2673 +Routine Description:
2674 +
2675 + This routine attempts to cleanly terminate the instance.
2676 +
2677 +Arguments:
2678 +
2679 + Config - Supplies the distribution config.
2680 +
2681 +Return Value:
2682 +
2683 + None.
2684 +
2685 +--*/
2686 +try
2687 +{
2688 + //
2689 + // If systemd is enabled, attempt to poweroff the instance via systemctl.
2690 + //
2691 +
2692 + if (Config.BootInit && !Config.BootStartWriteSocket)
2693 + {
2694 + THROW_LAST_ERROR_IF(UtilSetSignalHandlers(g_SavedSignalActions, false) < 0);
2695 +
2696 + if (UtilExecCommandLine("systemctl poweroff", nullptr) == 0)
2697 + {
2698 + std::this_thread::sleep_for(std::chrono::milliseconds(Config.BootInitTimeout));
2699 + LOG_ERROR("systemctl poweroff did not terminate the instance in {} ms, calling reboot(RB_POWER_OFF)", Config.BootInitTimeout);
2700 + }
2701 + }
2702 +
2703 + reboot(RB_POWER_OFF);
2704 + FATAL_ERROR("reboot(RB_POWER_OFF) failed {}", errno);
2705 }
2706 CATCH_LOG();
2707
src/windows/service/exe/WslCoreInstance.cpp
+6 -2
@@ -477,8 +477,12 @@ bool WslCoreInstance::RequestStop(_In_ bool Force)
477 terminateMessage.Header.MessageSize = sizeof(terminateMessage);
478 terminateMessage.Force = Force;
479
480 - const auto& terminateResponse = m_initChannel->GetChannel().Transaction(terminateMessage, nullptr, m_socketTimeout);
481 - shutdown = terminateResponse.Result;
480 + m_initChannel->GetChannel().SendMessage(terminateMessage);
481 + auto [message, span] = m_initChannel->GetChannel().ReceiveMessageOrClosed<RESULT_MESSAGE<bool>>(m_socketTimeout);
482 + if (message)
483 + {
484 + shutdown = message->Result;
485 + }
486 }
487 CATCH_LOG()
488