aboutsummaryrefslogtreecommitdiff
path: root/src/zenutil/service.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2025-01-08 14:21:11 +0100
committerDan Engelbrecht <[email protected]>2025-01-08 14:21:11 +0100
commit2696ea2322dfdd7b7a5b08843b6d8aca9aedd741 (patch)
treec4aee88cf1b3d707a6e0e7b6a427db2d735b9898 /src/zenutil/service.cpp
parentadd ServiceLevel for service processes: User, AllUsers and Service (diff)
downloadzen-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.cpp83
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);