4#include "Stroika/Frameworks/StroikaPreComp.h"
11#if qStroika_Foundation_Common_Platform_POSIX
18#if qStroika_Foundation_Common_Platform_Windows
19#include "Stroika/Foundation/Execution/Platform/Windows/Exception.h"
23#include "Stroika/Foundation/Characters/SDKString.h"
25#include "Stroika/Foundation/Containers/Common.h"
28#include "Stroika/Foundation/Execution/CommandLine.h"
29#include "Stroika/Foundation/Execution/Exceptions.h"
31#include "Stroika/Foundation/Execution/Module.h"
32#include "Stroika/Foundation/Execution/OperationNotSupportedException.h"
33#include "Stroika/Foundation/Execution/Process.h"
34#include "Stroika/Foundation/Execution/ProcessRunner.h"
35#include "Stroika/Foundation/Execution/SignalHandlers.h"
38#include "Stroika/Foundation/Execution/Throw.h"
39#include "Stroika/Foundation/Execution/TimeOutException.h"
41#include "Stroika/Foundation/Streams/iostream/FStreamSupport.h"
49using namespace Stroika::Foundation::Memory;
51using namespace Stroika::Frameworks;
59 const String kServiceRunThreadName_ =
"Service 'Run' thread"sv;
67Main::CommandArgs::CommandArgs (
const CommandLine& cmdLine)
70 {CommandOptions::kInstall, MajorOperation::eInstall},
71 {CommandOptions::kUnInstall, MajorOperation::eUnInstall},
72 {CommandOptions::kRunAsService, MajorOperation::eRunServiceMain},
73 {CommandOptions::kRunDirectly, MajorOperation::eRunDirectly},
74 {CommandOptions::kStart, MajorOperation::eStart},
75 {CommandOptions::kStop, MajorOperation::eStop},
76 {CommandOptions::kForcedStop, MajorOperation::eForcedStop},
77 {CommandOptions::kRestart, MajorOperation::eRestart},
78 {CommandOptions::kForcedRestart, MajorOperation::eForcedRestart},
79 {CommandOptions::kReloadConfiguration, MajorOperation::eReloadConfiguration},
80 {CommandOptions::kPause, MajorOperation::ePause},
81 {CommandOptions::kContinue, MajorOperation::eContinue},
85 switch (allMajorsSet.
size ()) {
89 fMajorOperation = kMap2Major_[Memory::ValueOf (allMajorsSet.
First ())];
94 if (
auto o = cmdLine.
GetArgument (CommandOptions::kRunFor)) {
109void Main::IApplicationRep::OnReReadConfigurationRequest ()
114String Main::IApplicationRep::GetServiceStatusMessage ()
const
126 return _GetAttachedAppRep ()->HandleCommandLineArgument (s);
136#if qStroika_Foundation_Common_Platform_POSIX
137 return make_shared<BasicUNIXServiceImpl> ();
138#elif qStroika_Foundation_Common_Platform_Windows
139 return make_shared<WindowsService> ();
141 return make_shared<RunNoFrillsService> ();
145Main::Main (
const shared_ptr<IApplicationRep>& rep,
const shared_ptr<IServiceIntegrationRep>& serviceIntegrationRep)
146 : fServiceRep_{serviceIntegrationRep}
150 serviceIntegrationRep->_Attach (rep);
155 fServiceRep_->_Attach (
nullptr);
160 for (
const String& i : args.fUnusedArguments) {
161 fServiceRep_->HandleCommandLineArgument (i);
163 if (not args.fMajorOperation.has_value ()) {
166 switch (*args.fMajorOperation) {
167 case CommandArgs::MajorOperation::eInstall: {
168 if (out !=
nullptr) {
169 out.
Write (
"Installing..."sv);
172 if (out !=
nullptr) {
173 out.
Write (
"done\n"sv);
176 case CommandArgs::MajorOperation::eUnInstall: {
177 if (out !=
nullptr) {
178 out.
Write (
"UnInstalling..."sv);
181 if (out !=
nullptr) {
182 out.
Write (
"done\n"sv);
185 case CommandArgs::MajorOperation::eRunServiceMain: {
188 case CommandArgs::MajorOperation::eRunDirectly: {
191 case CommandArgs::MajorOperation::eStart: {
192 if (out !=
nullptr) {
193 out.
Write (
"Starting..."sv);
197 if (out !=
nullptr) {
198 out.
Write (
"done\n"sv);
201 case CommandArgs::MajorOperation::eStop: {
202 if (out !=
nullptr) {
203 out.
Write (
"Stopping..."sv);
207 if (out !=
nullptr) {
208 out.
Write (
"done\n"sv);
211 case CommandArgs::MajorOperation::eForcedStop: {
215 case CommandArgs::MajorOperation::eRestart: {
216 if (out !=
nullptr) {
217 out.
Write (
"Restarting..."sv);
221 if (out !=
nullptr) {
222 out.
Write (
"done\n"sv);
225 case CommandArgs::MajorOperation::eForcedRestart: {
228 case CommandArgs::MajorOperation::eReloadConfiguration: {
229 ReReadConfiguration ();
231 case CommandArgs::MajorOperation::ePause: {
234 case CommandArgs::MajorOperation::eContinue: {
246 const wchar_t kTAB[] = L
" ";
247 ServiceDescription svd = GetServiceDescription ();
249 tmp << L
"Service '" << svd.fPrettyName.As<wstring> () <<
"'" << endl;
250 switch (GetState ()) {
251 case State::eStopped:
252 tmp << kTAB << L
"State: " << kTAB << kTAB << kTAB << kTAB <<
"STOPPED" << endl;
254 case State::eRunning:
255 tmp << kTAB << L
"State: " << kTAB << kTAB << kTAB << kTAB <<
"Running" << endl;
257 tmp << kTAB << L
"PID: " << kTAB << kTAB << kTAB << kTAB <<
GetServicePID () << endl;
261 tmp << kTAB << L
"State: " << kTAB << kTAB << kTAB << kTAB <<
"PAUSED" << endl;
263 tmp << kTAB << L
"PID: " << kTAB << kTAB << kTAB << kTAB <<
GetServicePID () << endl;
269 DbgTrace (
"returning status: ({})"_f, tmp.str ());
276 GetServiceRep_ ()._RunAsService ();
282 GetServiceRep_ ()._RunDirectly (runFor);
290void Main::ReReadConfiguration ()
293#if qStroika_Foundation_Common_Platform_Windows
295#elif qStroika_Foundation_Common_Platform_POSIX
309void Main::Continue ()
314Main::ServiceDescription Main::GetServiceDescription ()
const
316 return GetAppRep_ ().GetServiceDescription ();
328 IgnoreExceptionsForCall (Stop (timeout));
329#if qStroika_Foundation_Common_Platform_POSIX
331 unlink (_sAppRep->_GetPIDFileName ().AsSDKString ().c_str ());
333 Start (endAt - Time::GetTickCount ());
342Main::LoggerServiceWrapper::LoggerServiceWrapper (
const shared_ptr<Main::IServiceIntegrationRep>& delegateTo)
343 : fDelegateTo_{delegateTo}
350 fDelegateTo_->_Attach (appRep);
353shared_ptr<Main::IApplicationRep> Main::LoggerServiceWrapper::_GetAttachedAppRep ()
const
355 return fDelegateTo_->_GetAttachedAppRep ();
360 return fDelegateTo_->_GetSupportedFeatures ();
363Main::State Main::LoggerServiceWrapper::_GetState ()
const
365 return fDelegateTo_->_GetState ();
372 fDelegateTo_->_Install ();
375 Logger::sThe.
Log (Logger::eError,
"Failed to install - {} - aborting..."_f, current_exception ());
384 fDelegateTo_->_UnInstall ();
387 Logger::sThe.
Log (Logger::eError,
"Failed to uninstall - {} - aborting..."_f, current_exception ());
392void Main::LoggerServiceWrapper::_RunAsService ()
396 fDelegateTo_->_RunAsService ();
399 Logger::sThe.
Log (Logger::eError, L
"Exception running service - {} - aborting..."_f, current_exception ());
405void Main::LoggerServiceWrapper::_RunDirectly (
const optional<Time::Duration>& runFor)
407 Logger::sThe.
Log (Logger::eNotice,
"Service starting in Run-Direct (non service) mode."_f);
409 fDelegateTo_->_RunDirectly (runFor);
412 Logger::sThe.
Log (Logger::eError,
"Exception running service in direct mode - {} - aborting..."_f, current_exception ());
420 fDelegateTo_->_Start (timeout);
425 fDelegateTo_->_Stop (timeout);
430 fDelegateTo_->_ForcedStop (timeout);
433pid_t Main::LoggerServiceWrapper::_GetServicePID ()
const
435 return fDelegateTo_->_GetServicePID ();
438#if qStroika_Foundation_Common_Platform_POSIX
444Main::BasicUNIXServiceImpl::BasicUNIXServiceImpl ()
445 : fOurSignalHandler_{[this] (SignalID signum) { SignalHandler_ (signum); }}
447#if USE_NOISY_TRACE_IN_THIS_MODULE_
448 DbgTrace (
"Main::BasicUNIXServiceImpl::BasicUNIXServiceImpl: this={}"_f,
static_cast<const void*
> (
this));
452Main::BasicUNIXServiceImpl::~BasicUNIXServiceImpl ()
454#if USE_NOISY_TRACE_IN_THIS_MODULE_
455 DbgTrace (
"Main::BasicUNIXServiceImpl::~BasicUNIXServiceImpl: this={}"_f,
static_cast<const void*
> (
this));
457 Require (fAppRep_.load () ==
nullptr);
460void Main::BasicUNIXServiceImpl::_Attach (
const shared_ptr<IApplicationRep>& appRep)
462#if USE_NOISY_TRACE_IN_THIS_MODULE_
466 Require ((appRep ==
nullptr and fAppRep_.load () !=
nullptr) or (fAppRep_.load () ==
nullptr and fAppRep_.load () != appRep));
470 fRunThread_.store (
nullptr);
475shared_ptr<Main::IApplicationRep> Main::BasicUNIXServiceImpl::_GetAttachedAppRep ()
const
483 result.
Add (Main::ServiceIntegrationFeatures::eGetServicePID);
487Main::State Main::BasicUNIXServiceImpl::_GetState ()
const
489#if USE_NOISY_TRACE_IN_THIS_MODULE_
493 if (_GetServicePID () > 0) {
494#if USE_NOISY_TRACE_IN_THIS_MODULE_
497 return State::eRunning;
499#if USE_NOISY_TRACE_IN_THIS_MODULE_
502 return State::eStopped;
505void Main::BasicUNIXServiceImpl::_Install ()
510void Main::BasicUNIXServiceImpl::_UnInstall ()
515void Main::BasicUNIXServiceImpl::_RunAsService ()
518 if (_GetServicePID () > 0) {
522 shared_ptr<IApplicationRep> appRep = fAppRep_;
527 SetupSignalHanlders_ (
false);
529 SetupSignalHanlders_ (
true);
532 fRunThread_.store (
Thread::New ([appRep] () { appRep->MainLoop ([] () {}); }, Thread::eAutoStart, kServiceRunThreadName_));
533 [[maybe_unused]]
auto&& cleanup =
Finally ([
this] ()
noexcept {
535 (void)::unlink (_GetPIDFileName ().c_str ());
539 Streams::iostream::OpenOutputFileStream (&out, _GetPIDFileName ());
540 out << GetCurrentProcessID () << endl;
542 if (_GetServicePID () <= 0) {
543 Throw (
Exception{
"Unable to create process ID tracking file {}"_f(_GetPIDFileName ())});
545 if (_GetServicePID () != GetCurrentProcessID ()) {
546 Throw (
Exception{
"Unable to create process ID tracking file {} (race?)"_f(_GetPIDFileName ())});
548 fRunThread_.load ().Join ();
551void Main::BasicUNIXServiceImpl::_RunDirectly (
const optional<Time::Duration>& runFor)
553 shared_ptr<IApplicationRep> appRep = fAppRep_;
555 fRunThread_.store (
Thread::New ([appRep] () { appRep->MainLoop ([] () {}); }, Thread::eAutoStart, kServiceRunThreadName_));
576 if (_GetServicePID () > 0) {
577 Throw (
Exception{
"Cannot Start service because its already running"sv});
588 while (_GetServicePID () <= 0) {
596#if USE_NOISY_TRACE_IN_THIS_MODULE_
597 Debug::TraceContextBumper traceCtx{L
"Stroika::Frameworks::Service::Main::BasicUNIXServiceImpl::_Stop", L
"timeout=%e", timeout};
599 bool kInProc_ =
false;
606 if (_GetServicePID () > 0) {
607#if USE_NOISY_TRACE_IN_THIS_MODULE_
608 DbgTrace (
"Service running - so sending SIGTERM signal");
613 while (_GetServicePID () > 0) {
615 if (waitFor < timeout and waitFor < 5s) {
618#if USE_NOISY_TRACE_IN_THIS_MODULE_
619 DbgTrace (
"still waiting for timeout/completion");
626 (void)::unlink (_GetPIDFileName ().c_str ());
634 pid_t svcPID = _GetServicePID ();
639 (void)::unlink (_GetPIDFileName ().c_str ());
642pid_t Main::BasicUNIXServiceImpl::_GetServicePID ()
const
644 ifstream in (_GetPIDFileName ().c_str ());
655void Main::BasicUNIXServiceImpl::SetupSignalHanlders_ (
bool install)
669filesystem::path Main::BasicUNIXServiceImpl::_GetPIDFileName ()
const
672 (fAppRep_.load ()->GetServiceDescription ().fRegistrationName +
".pid"sv).As<filesystem::path> ();
675void Main::BasicUNIXServiceImpl::_CleanupDeadService ()
679 (void)::unlink (_GetPIDFileName ().c_str ());
682void Main::BasicUNIXServiceImpl::SignalHandler_ (SignalID signum)
686 "Stroika::Frameworks::Service::Main::BasicUNIXServiceImpl::SignalHandler_",
"signal = {}"_f, SignalToName (signum))};
691 DbgTrace (
"Calling sigHandlerThread2Abort (thread: {}).Abort ()"_f, fRunThread_.load ().ToString ());
692 fRunThread_.load ().Abort ();
694 case kSIG_ReReadConfiguration: {
695 DbgTrace (
"Invoking fAppRep->OnReReadConfigurationRequest ()"_f);
696 fAppRep_.load ()->OnReReadConfigurationRequest ();
702#if qStroika_Foundation_Common_Platform_Windows
708Main::WindowsService* Main::WindowsService::s_SvcRunningTHIS_ =
nullptr;
710Main::WindowsService::WindowsService ()
713 fServiceStatus_.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
714 fServiceStatus_.dwCurrentState = SERVICE_STOPPED;
715 fServiceStatus_.dwControlsAccepted = SERVICE_ACCEPT_STOP;
718void Main::WindowsService::_Attach (
const shared_ptr<IApplicationRep>& appRep)
720 Require ((appRep ==
nullptr and fAppRep_ !=
nullptr) or (fAppRep_ ==
nullptr and fAppRep_ != appRep));
724shared_ptr<Main::IApplicationRep> Main::WindowsService::_GetAttachedAppRep ()
const
732 result.
Add (Main::ServiceIntegrationFeatures::eGetServicePID);
733 result.
Add (Main::ServiceIntegrationFeatures::eInstall);
737Main::State Main::WindowsService::_GetState ()
const
740 const DWORD kServiceMgrAccessPrivs = SERVICE_QUERY_STATUS;
741 SC_HANDLE hSCM = ::OpenSCManager (NULL, NULL, kServiceMgrAccessPrivs);
743 [[maybe_unused]]
auto&& cleanup1 =
Finally ([hSCM] ()
noexcept {
745 ::CloseServiceHandle (hSCM);
747 SC_HANDLE hService = ::OpenService (hSCM, GetSvcName_ ().c_str (), kServiceMgrAccessPrivs);
749 [[maybe_unused]]
auto&& cleanup2 =
Finally ([hService] ()
noexcept {
751 ::CloseServiceHandle (hService);
754 const bool kUseQueryServiceStatusEx_ =
false;
755 if (kUseQueryServiceStatusEx_) {
756 SERVICE_STATUS_PROCESS serviceProcess{};
759 hService, SC_STATUS_PROCESS_INFO,
reinterpret_cast<LPBYTE
> (&serviceProcess),
sizeof (serviceProcess), &ignored));
760 switch (serviceProcess.dwCurrentState) {
761 case SERVICE_RUNNING:
762 return Main::State::eRunning;
764 return Main::State::ePaused;
768 SERVICE_STATUS serviceStatus{};
770 switch (serviceStatus.dwCurrentState) {
771 case SERVICE_RUNNING:
772 return Main::State::eRunning;
774 return Main::State::ePaused;
777 return Main::State::eStopped;
780void Main::WindowsService::_Install ()
784 const DWORD kServiceMgrAccessPrivs = SC_MANAGER_CREATE_SERVICE;
786 SC_HANDLE hSCM = ::OpenSCManager (NULL, NULL, kServiceMgrAccessPrivs);
790 ::CloseServiceHandle (hSCM);
793 DbgTrace (L
"registering with command-line: '{}', serviceName: '{}'"_f, cmdLineForRunSvc, GetSvcName_ ());
794 SC_HANDLE hService = ::CreateService (hSCM, GetSvcName_ ().c_str (), fAppRep_->GetServiceDescription ().fPrettyName.AsSDKString ().c_str (),
795 kServiceMgrAccessPrivs, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
796 cmdLineForRunSvc.
AsSDKString ().c_str (), NULL, NULL, _T(
"RPCSS\0"), NULL, NULL);
800void Main::WindowsService::_UnInstall ()
804 const DWORD kServiceMgrAccessPrivs = SERVICE_STOP | DELETE;
805 SC_HANDLE hSCM = ::OpenSCManager (NULL, NULL, kServiceMgrAccessPrivs);
809 ::CloseServiceHandle (hSCM);
812 SC_HANDLE hService = ::OpenService (hSCM, GetSvcName_ ().c_str (), kServiceMgrAccessPrivs);
816 ::CloseServiceHandle (hService);
820 SERVICE_STATUS status;
821 if (not::ControlService (hService, SERVICE_CONTROL_STOP, &status)) {
822 DWORD e = ::GetLastError ();
823 if (e != ERROR_SERVICE_NOT_ACTIVE) {
824 Execution::ThrowSystemErrNo (e);
832void Main::WindowsService::_RunAsService ()
835 Assert (s_SvcRunningTHIS_ ==
nullptr);
836 s_SvcRunningTHIS_ =
this;
840 SERVICE_TABLE_ENTRY st[] = {{
const_cast<TCHAR*
> (svcName.c_str ()), StaticServiceMain_}, {
nullptr,
nullptr}};
841 if (::StartServiceCtrlDispatcher (st) == FALSE) {
842 fServiceStatus_.dwWin32ExitCode = ::GetLastError ();
843 if (fServiceStatus_.dwWin32ExitCode == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
844 DbgTrace (
"fServiceStatus_.dwWin32ExitCode = ERROR_FAILED_SERVICE_CONTROLLER_CONNECT"_f);
846 Execution::ThrowSystemErrNo (fServiceStatus_.dwWin32ExitCode);
850void Main::WindowsService::_RunDirectly (
const optional<Time::Duration>& runFor)
852 shared_ptr<IApplicationRep> appRep = fAppRep_;
853 fRunThread_ =
Execution::Thread::New ([appRep] () { appRep->MainLoop ([] () {}); }, Execution::Thread::eAutoStart, kServiceRunThreadName_);
859 fRunThread_.Abort ();
861 Execution::Thread::eAutoStart);
869 Debug::TraceContextBumper traceCtx{
"Stroika::Frameworks::Service::Main::WindowsService::Start",
"timeout = {}"_f, timeout};
871 const DWORD kServiceMgrAccessPrivs = SERVICE_START;
872 SC_HANDLE hSCM = ::OpenSCManager (
nullptr,
nullptr, kServiceMgrAccessPrivs);
876 ::CloseServiceHandle (hSCM);
878 SC_HANDLE hService = ::OpenService (hSCM, GetSvcName_ ().c_str (), kServiceMgrAccessPrivs);
882 ::CloseServiceHandle (hService);
885 DWORD dwNumServiceArgs = 0;
886 LPCTSTR* lpServiceArgVectors =
nullptr;
894 const DWORD kServiceMgrAccessPrivs = SERVICE_STOP;
895 SC_HANDLE hSCM = ::OpenSCManager (NULL, NULL, kServiceMgrAccessPrivs);
899 ::CloseServiceHandle (hSCM);
902 SC_HANDLE hService = ::OpenService (hSCM, GetSvcName_ ().c_str (), kServiceMgrAccessPrivs);
906 ::CloseServiceHandle (hService);
910 SERVICE_STATUS status;
911 if (not::ControlService (hService, SERVICE_CONTROL_STOP, &status)) {
912 DWORD e = ::GetLastError ();
913 if (e != ERROR_SERVICE_NOT_ACTIVE) {
914 Execution::ThrowSystemErrNo (e);
925pid_t Main::WindowsService::_GetServicePID ()
const
927 const DWORD kServiceMgrAccessPrivs = SERVICE_QUERY_STATUS;
928 SC_HANDLE hSCM = ::OpenSCManager (NULL, NULL, kServiceMgrAccessPrivs);
932 ::CloseServiceHandle (hSCM);
934 SC_HANDLE hService = ::OpenService (hSCM, GetSvcName_ ().c_str (), kServiceMgrAccessPrivs);
938 ::CloseServiceHandle (hService);
941 SERVICE_STATUS_PROCESS serviceProcess{};
944 ::QueryServiceStatusEx (hService, SC_STATUS_PROCESS_INFO,
reinterpret_cast<LPBYTE
> (&serviceProcess),
sizeof (serviceProcess), &ignored));
945 return serviceProcess.dwProcessId;
948SDKString Main::WindowsService::GetSvcName_ ()
const
951 return fAppRep_->GetServiceDescription ().fRegistrationName.AsSDKString ();
954bool Main::WindowsService::IsInstalled_ () const noexcept
957 const DWORD kServiceMgrAccessPrivs = SERVICE_QUERY_CONFIG;
958 SC_HANDLE hSCM = ::OpenSCManager (NULL, NULL, kServiceMgrAccessPrivs);
962 ::CloseServiceHandle (hSCM);
965 SC_HANDLE hService = ::OpenService (hSCM, GetSvcName_ ().c_str (), kServiceMgrAccessPrivs);
969 ::CloseServiceHandle (hService);
971 return hService != NULL;
974void Main::WindowsService::SetServiceStatus_ (DWORD dwState)
noexcept
976 DbgTrace (
"SetServiceStatus_ ({})"_f, dwState);
977 Assert (fServiceStatusHandle_ !=
nullptr);
978 fServiceStatus_.dwCurrentState = dwState;
979 ::SetServiceStatus (fServiceStatusHandle_, &fServiceStatus_);
982void Main::WindowsService::ServiceMain_ ([[maybe_unused]] DWORD dwArgc, [[maybe_unused]] LPTSTR* lpszArgv)
noexcept
991 fServiceStatus_.dwCurrentState = SERVICE_START_PENDING;
992 fServiceStatusHandle_ = ::RegisterServiceCtrlHandler (GetSvcName_ ().c_str (), StaticHandler_);
994 SetServiceStatus_ (SERVICE_START_PENDING);
996 fServiceStatus_.dwWin32ExitCode = S_OK;
997 fServiceStatus_.dwCheckPoint = 0;
998 fServiceStatus_.dwWaitHint = 0;
1002 shared_ptr<IApplicationRep> appRep = fAppRep_;
1003 fRunThread_ =
Execution::Thread::New ([appRep] () { appRep->MainLoop ([] () {}); }, Execution::Thread::eAutoStart, kServiceRunThreadName_);
1005 SetServiceStatus_ (SERVICE_RUNNING);
1008 fRunThread_.Join ();
1011 DbgTrace (
"mapping run-thread.Join () exception {} to dwWin32ExitCode=1"_f, current_exception ());
1012 fServiceStatus_.dwWin32ExitCode = 1;
1014 SetServiceStatus_ (SERVICE_STOPPED);
1017void WINAPI Main::WindowsService::StaticServiceMain_ (DWORD dwArgc, LPTSTR* lpszArgv)
noexcept
1020 s_SvcRunningTHIS_->ServiceMain_ (dwArgc, lpszArgv);
1023void Main::WindowsService::OnStopRequest_ () noexcept
1029 if (fServiceStatus_.dwCurrentState == SERVICE_RUNNING) {
1030 SetServiceStatus_ (SERVICE_STOP_PENDING);
1031 fRunThread_.Abort ();
1035void Main::WindowsService::Handler_ (DWORD dwOpcode)
noexcept
1038 case SERVICE_CONTROL_STOP:
1047void WINAPI Main::WindowsService::StaticHandler_ (DWORD dwOpcode)
noexcept
1050 s_SvcRunningTHIS_->Handler_ (dwOpcode);
#define AssertNotImplemented()
#define RequireNotNull(p)
#define AssertNotReached()
time_point< RealtimeClock, DurationSeconds > TimePointSeconds
TimePointSeconds is a simpler approach to chrono::time_point, which doesn't require using templates e...
chrono::duration< double > DurationSeconds
chrono::duration<double> - a time span (length of time) measured in seconds, but high precision.
#define Stroika_Foundation_Debug_OptionalizeTraceArgs(...)
String is like std::u32string, except it is much easier to use, often much more space efficient,...
nonvirtual SDKString AsSDKString() const
A generalization of a vector: a container whose elements are keyed by the natural numbers.
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
nonvirtual void Add(ArgByValueType< value_type > item)
nonvirtual optional< String > GetArgument(const Option &o) const
Exception<> is a replacement (subclass) for any std c++ exception class (e.g. the default 'std::excep...
void Log(Priority logLevel, const wchar_t *format,...)
Run the given command, and optionally support stdin/stdout/stderr as streams (either sync with Run,...
nonvirtual void AddSignalHandler(SignalID signal, const SignalHandler &handler)
nonvirtual void RemoveSignalHandler(SignalID signal, const SignalHandler &handler)
static SignalHandlerRegistry & Get()
Thread::Ptr is a (unsynchronized) smart pointer referencing an internally synchronized std::thread ob...
nonvirtual void Join(Time::DurationSeconds timeout=Time::kInfinity) const
Wait for the pointed-to thread to be done. If the thread completed with an exception (other than thre...
nonvirtual void Abort() const
Abort gracefully shuts down and terminates the given thread (using cooperative multitasking).
nonvirtual void AbortAndWaitForDone(Time::DurationSeconds timeout=Time::kInfinity) const
Abort () the thread, and then WaitForDone () - but if doesn't finish fast enough, send extra aborts (...
OutputStream<>::Ptr is Smart pointer to a stream-based sink of data.
nonvirtual void Write(span< ELEMENT_TYPE2, EXTENT_2 > elts) const
Duration is a chrono::duration<double> (=.
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
nonvirtual optional< T > First() const
return first element in iterable, or if 'that' specified, first where 'that' is true,...
nonvirtual size_t size() const
Returns the number of items contained.
nonvirtual RESULT_CONTAINER Where(INCLUDE_PREDICATE &&includeIfTrue) const
produce a subset of this iterable where argument function returns true
virtual bool HandleCommandLineArgument(const String &s)
virtual bool HandleCommandLineArgument(const String &s)
virtual void _Install() override
virtual void _UnInstall() override
virtual void _Attach(const shared_ptr< IApplicationRep > &appRep) override
static shared_ptr< IServiceIntegrationRep > mkDefaultServiceIntegrationRep()
nonvirtual Containers::Set< ServiceIntegrationFeatures > GetServiceIntegrationFeatures() const
nonvirtual pid_t GetServicePID() const
nonvirtual void RunDirectly(const optional< Time::Duration > &runFor={})
nonvirtual void RunAsService()
nonvirtual void ForcedRestart(Time::DurationSeconds timeout=Time::kInfinity, Time::DurationSeconds unforcedStopTimeout=Time::kInfinity)
nonvirtual void Run(const CommandArgs &args, const Streams::OutputStream::Ptr< Characters::Character > &out=nullptr)
nonvirtual String GetServiceStatusMessage() const
basic_string< SDKChar > SDKString
Ptr New(const function< void()> &fun2CallOnce, const optional< Characters::String > &name, const optional< Configuration > &configuration)
void Sleep(Time::Duration seconds2Wait)
void ThrowTimeoutExceptionAfter(Time::TimePointSeconds afterTickCount, EXCEPTION &&exception2Throw)
Throw TimeOutException if the @Time::GetTickCount () is >= the given value.
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
auto Finally(FUNCTION &&f) -> Private_::FinallySentry< FUNCTION >
int pid_t
TODO - maybe move this to configuraiotn module???
INT_TYPE ThrowPOSIXErrNoIfNegative(INT_TYPE returnCode)
filesystem::path GetEXEPath()
pid_t DetachedProcessRunner(const filesystem::path &executable, const Containers::Sequence< String > &args)
DEPRECATED.
bool IsProcessRunning(pid_t pid)
filesystem::path GetRuntimeVariableData()
optional< Time::Duration > fRunFor