Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

server: Add Windows console control handler #945

Merged
merged 13 commits into from
Jun 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,10 @@ if(CMAKE_SYSTEM_NAME STREQUAL Linux)
PRIVATE "source/server/linux/syslog_logging.cpp"
PRIVATE "source/server/linux/daemonize.cpp")
endif()
if(CMAKE_SYSTEM_NAME STREQUAL Windows)
target_sources(ni_grpc_device_server
PRIVATE "source/server/windows/console_ctrl_handler.cpp")
endif()

target_link_libraries(ni_grpc_device_server
${_REFLECTION}
Expand Down
8 changes: 8 additions & 0 deletions source/server/core_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#include "linux/daemonize.h"
#include "linux/syslog_logging.h"
#endif
#if defined(_WIN32)
#include "windows/console_ctrl_handler.h"
#endif

using FeatureState = nidevice_grpc::FeatureToggles::FeatureState;

Expand Down Expand Up @@ -117,6 +120,8 @@ static void RunServer(const ServerConfiguration& config)
while (!services->empty()) {
services->pop_back();
}

nidevice_grpc::logging::log(nidevice_grpc::logging::Level_Info, "Server stopped.");
}

struct Options {
Expand Down Expand Up @@ -208,6 +213,9 @@ int main(int argc, char** argv)
nidevice_grpc::daemonize(&StopServer, options.identity);
}
#endif
#if defined(_WIN32)
nidevice_grpc::set_console_ctrl_handler(&StopServer);
#endif

RunServer(config);
return EXIT_SUCCESS;
Expand Down
66 changes: 66 additions & 0 deletions source/server/windows/console_ctrl_handler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include "console_ctrl_handler.h"

#include "../logging.h"

#include <string>
#include <Windows.h>

namespace nidevice_grpc {

static stop_callback signal_stop = nullptr;

static BOOL WINAPI console_ctrl_handler(DWORD dwCtrlType)
{
const char* signal_description = "?";
switch (dwCtrlType)
{
case CTRL_C_EVENT:
signal_description = "ctrl-c";
break;
case CTRL_BREAK_EVENT:
signal_description = "ctrl-break";
break;
case CTRL_CLOSE_EVENT:
signal_description = "close";
break;
case CTRL_LOGOFF_EVENT:
signal_description = "logoff";
break;
case CTRL_SHUTDOWN_EVENT:
signal_description = "shutdown";
break;
default:
break;
}

logging::log(logging::Level_Info, "Received %s signal, stopping server.", signal_description);
if (signal_stop) {
signal_stop();

// Wait up to 10 seconds for the server to stop. When either main() or this handler returns,
// the process will exit.
Sleep(10000);
}
return TRUE;
}

static std::string get_error_message(DWORD error)
{
char buffer[1024] = "";
if (!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, error, 0, buffer, sizeof(buffer), nullptr)) {
return "unknown Win32 error " + std::to_string(error);
}
return buffer;
}

void set_console_ctrl_handler(stop_callback signal_stop_)
{
signal_stop = signal_stop_;
if (!SetConsoleCtrlHandler(&console_ctrl_handler, TRUE /*Add*/)) {
DWORD error = GetLastError();
logging::log(logging::Level_Error, "Failed to register console control handler: %s",
get_error_message(error).c_str());
}
}

} // namespace nidevice_grpc
13 changes: 13 additions & 0 deletions source/server/windows/console_ctrl_handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef NIDEVICE_GRPC_WINDOWS_SET_CONSOLE_CTRL_HANDLER_H
#define NIDEVICE_GRPC_WINDOWS_SET_CONSOLE_CTRL_HANDLER_H

namespace nidevice_grpc {

typedef void (*stop_callback)();

void set_console_ctrl_handler(stop_callback stop);

} // namespace nidevice_grpc

#endif // NIDEVICE_GRPC_WINDOWS_SET_CONSOLE_CTRL_HANDLER_H