diff options
| author | Dan Engelbrecht <[email protected]> | 2025-01-08 14:21:11 +0100 |
|---|---|---|
| committer | Dan Engelbrecht <[email protected]> | 2025-01-08 14:21:11 +0100 |
| commit | 2696ea2322dfdd7b7a5b08843b6d8aca9aedd741 (patch) | |
| tree | c4aee88cf1b3d707a6e0e7b6a427db2d735b9898 /src/zenutil/service.cpp | |
| parent | add ServiceLevel for service processes: User, AllUsers and Service (diff) | |
| download | zen-2696ea2322dfdd7b7a5b08843b6d8aca9aedd741.tar.xz zen-2696ea2322dfdd7b7a5b08843b6d8aca9aedd741.zip | |
use attachconsole to send ctrl+c to running process
Diffstat (limited to 'src/zenutil/service.cpp')
| -rw-r--r-- | src/zenutil/service.cpp | 83 |
1 files changed, 41 insertions, 42 deletions
diff --git a/src/zenutil/service.cpp b/src/zenutil/service.cpp index 44aa50494..3d7808bba 100644 --- a/src/zenutil/service.cpp +++ b/src/zenutil/service.cpp @@ -6,11 +6,6 @@ #include <zencore/process.h> #include <zencore/scopeguard.h> #include <zencore/zencore.h> -#include <zenutil/zenserverprocess.h> - -ZEN_THIRD_PARTY_INCLUDES_START -#include <gsl/gsl-lite.hpp> -ZEN_THIRD_PARTY_INCLUDES_END #if ZEN_PLATFORM_WINDOWS # include <zencore/windows.h> @@ -751,6 +746,46 @@ StartService(std::string_view ServiceName, ServiceLevel Level) } std::error_code +SendSignalToProcess(DWORD dwProcessId, DWORD dwCtrlEvent) +{ + std::error_code Ec = {}; + DWORD ConsoleId = GetCurrentProcessId(); + // Leave current console if it exists + // (otherwise AttachConsole will return ERROR_ACCESS_DENIED) + bool ConsoleDetached = FreeConsole() != FALSE; + + if (AttachConsole(dwProcessId) != FALSE) + { + // Add a fake Ctrl-C handler for avoid instant kill is this console + // WARNING: do not revert it or current program will be also killed + SetConsoleCtrlHandler(nullptr, true); + if (GenerateConsoleCtrlEvent(dwCtrlEvent, 0) == FALSE) + { + Ec = MakeErrorCodeFromLastError(); + } + FreeConsole(); + } + else + { + Ec = MakeErrorCodeFromLastError(); + } + + if (ConsoleDetached) + { + // Create a new console if previous was deleted by OS + if (AttachConsole(ConsoleId) == FALSE) + { + int errorCode = GetLastError(); + if (errorCode == 31) // 31=ERROR_GEN_FAILURE + { + AllocConsole(); + } + } + } + return Ec; +} + +std::error_code StopRunService(bool AllUsers, std::string_view ServiceName) { HKEY RegKey = NULL; @@ -777,43 +812,7 @@ StopRunService(bool AllUsers, std::string_view ServiceName) } else { - // This is hacky and checks if the running service is a zenserver instance and tries to shut down using the shutdown - // event - ExtendableStringBuilder<32> ChildShutdownEventName; - ZenServerState State; - if (State.InitializeReadOnly()) - { - State.Snapshot([&](const ZenServerState::ZenServerEntry& Entry) { - if (Entry.Pid == gsl::narrow<uint32_t>(Proc.Pid())) - { - ChildShutdownEventName << "Zen_" << Entry.EffectiveListenPort; - ChildShutdownEventName << "_Shutdown"; - } - }); - if (ChildShutdownEventName.Size() > 0) - { - NamedEvent Event(ChildShutdownEventName); - Ec = Event.Set(); - if (Ec) - { - return Ec; - } - return {}; - } - } - // This only works for a running process that does not already have a console attached - zenserver does have one - // hence the attempt to shut down using event above - if (AttachConsole(Proc.Pid())) - { - if (SetConsoleCtrlHandler(NULL, TRUE)) - { - if (GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0)) - { - return {}; - } - } - } - return MakeErrorCodeFromLastError(); + return SendSignalToProcess(Proc.Pid(), CTRL_C_EVENT); } } return MakeErrorCode(ERROR_INVALID_PARAMETER); |