From 1b47d73587a21a8f548839e4335937e2ac155bc0 Mon Sep 17 00:00:00 2001 From: Aleksandar Fabijanic Date: Mon, 14 Oct 2024 13:09:22 +0200 Subject: [PATCH 1/3] feat(ServerApplication): termination callback #4643 --- Util/include/Poco/Util/ServerApplication.h | 24 +++++++++++++++++++++ Util/src/ServerApplication.cpp | 25 ++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/Util/include/Poco/Util/ServerApplication.h b/Util/include/Poco/Util/ServerApplication.h index f575963da6..c420bd9856 100644 --- a/Util/include/Poco/Util/ServerApplication.h +++ b/Util/include/Poco/Util/ServerApplication.h @@ -24,6 +24,7 @@ #if defined(POCO_OS_FAMILY_WINDOWS) #include "Poco/NamedEvent.h" #endif +#include namespace Poco { @@ -122,8 +123,21 @@ class Util_API ServerApplication: public Application /// --pidfile=/var/run/sample.pid) may be useful to record the process ID of /// the daemon in a file. The PID file will be removed when the daemon process /// terminates (but not, if it crashes). + /// + /// An aplication can register a callback to be called at termination time. + /// An example of the termination callback registration at some point + /// during the ServerApplication initialization time: + /// + /// static const std::string cbMsg = "Termination custom message"s; + /// auto tCB = [](const std::string& message) + /// { + /// std::cout << message << std::endl; + /// }; + /// ServerApplication::registerTerminateCallback(tCB, cbMsg); { public: + using TerminateCallback = std::function; + ServerApplication(); /// Creates the ServerApplication. @@ -158,6 +172,11 @@ class Util_API ServerApplication: public Application /// waitForTerminationRequest(), this method will return /// and the application can shut down. + static void registerTerminateCallback(TerminateCallback tCB, + const std::string& message = _terminateMessage); + /// Registers a termination callback. + /// Used to notify all interested users about system shutdown. + protected: int run(); void waitForTerminationRequest(); @@ -207,6 +226,11 @@ class Util_API ServerApplication: public Application static SERVICE_STATUS_HANDLE _serviceStatusHandle; static Poco::NamedEvent _terminate; #endif + + static void terminateCallback(); + inline static std::atomic _terminationGuard = false; + inline static TerminateCallback _terminateCallback = nullptr; + inline static std::string _terminateMessage = "System terminating now!"; }; diff --git a/Util/src/ServerApplication.cpp b/Util/src/ServerApplication.cpp index e7d72c99d1..1a20db58b1 100644 --- a/Util/src/ServerApplication.cpp +++ b/Util/src/ServerApplication.cpp @@ -91,8 +91,22 @@ int ServerApplication::run() } +void ServerApplication::terminateCallback() +{ + if (!_terminationGuard.exchange(true)) + { + if (_terminateCallback) + { + _terminateCallback(_terminateMessage); + _terminateCallback = nullptr; + } + } +} + + void ServerApplication::terminate() { + terminateCallback(); #if defined(POCO_OS_FAMILY_WINDOWS) _terminate.set(); #elif defined(POCO_VXWORKS) || POCO_OS == POCO_OS_ANDROID @@ -103,6 +117,13 @@ void ServerApplication::terminate() } +void ServerApplication::registerTerminateCallback(TerminateCallback tCB, const std::string& message) +{ + _terminateCallback = tCB; + _terminateMessage = message; +} + + #if defined(POCO_OS_FAMILY_WINDOWS) @@ -196,6 +217,7 @@ void ServerApplication::waitForTerminationRequest() { SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE); _terminate.wait(); + terminateCallback(); _terminated.set(); } @@ -444,6 +466,7 @@ void ServerApplication::handleStartup(const std::string& name, const std::string void ServerApplication::waitForTerminationRequest() { _terminate.wait(); + terminateCallback(); } @@ -503,8 +526,10 @@ void ServerApplication::waitForTerminationRequest() sigprocmask(SIG_BLOCK, &sset, NULL); int sig; sigwait(&sset, &sig); + terminateCallback(); #else // POCO_OS != POCO_OS_ANDROID _terminate.wait(); + terminateCallback(); #endif } From afa38a393a43929dbfab7efa2c8c9be9ff327db3 Mon Sep 17 00:00:00 2001 From: Aleksandar Fabijanic Date: Mon, 14 Oct 2024 13:12:26 +0200 Subject: [PATCH 2/3] chore(ServerApplication): spelling fix #4643 --- Util/include/Poco/Util/ServerApplication.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Util/include/Poco/Util/ServerApplication.h b/Util/include/Poco/Util/ServerApplication.h index c420bd9856..fb88faa457 100644 --- a/Util/include/Poco/Util/ServerApplication.h +++ b/Util/include/Poco/Util/ServerApplication.h @@ -124,7 +124,7 @@ class Util_API ServerApplication: public Application /// the daemon in a file. The PID file will be removed when the daemon process /// terminates (but not, if it crashes). /// - /// An aplication can register a callback to be called at termination time. + /// An application can register a callback to be called at termination time. /// An example of the termination callback registration at some point /// during the ServerApplication initialization time: /// From f85e9dbb2158d7cb7472d6772788470fc8c3f897 Mon Sep 17 00:00:00 2001 From: Aleksandar Fabijanic Date: Tue, 15 Oct 2024 13:42:32 +0200 Subject: [PATCH 3/3] chore(ServerApplication): correct documentation #4643 --- Util/include/Poco/Util/ServerApplication.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Util/include/Poco/Util/ServerApplication.h b/Util/include/Poco/Util/ServerApplication.h index fb88faa457..16fdfb6fc3 100644 --- a/Util/include/Poco/Util/ServerApplication.h +++ b/Util/include/Poco/Util/ServerApplication.h @@ -127,13 +127,12 @@ class Util_API ServerApplication: public Application /// An application can register a callback to be called at termination time. /// An example of the termination callback registration at some point /// during the ServerApplication initialization time: - /// - /// static const std::string cbMsg = "Termination custom message"s; + /// /// auto tCB = [](const std::string& message) /// { /// std::cout << message << std::endl; /// }; - /// ServerApplication::registerTerminateCallback(tCB, cbMsg); + /// ServerApplication::registerTerminateCallback(tCB, "custom termination message"s); { public: using TerminateCallback = std::function; @@ -175,7 +174,8 @@ class Util_API ServerApplication: public Application static void registerTerminateCallback(TerminateCallback tCB, const std::string& message = _terminateMessage); /// Registers a termination callback. - /// Used to notify all interested users about system shutdown. + /// Used to register a function to be executed when the system + /// shutdown starts. protected: int run();