| 48 | }; |
| 49 | |
| 50 | void RunAsServiceIfNeeded() { |
| 51 | static const int WAIT_TIME_EXE_TERMINATION = 5000; |
| 52 | static const int WAIT_TIME_EXE_RESTART = 60000; |
| 53 | |
| 54 | static SERVICE_STATUS s_serviceStatus; |
| 55 | static SERVICE_STATUS_HANDLE s_statusHandle; |
| 56 | static HANDLE s_hProcess; |
| 57 | static HANDLE s_hEvent; |
| 58 | |
| 59 | static auto Log = []() { |
| 60 | static std::shared_ptr<logging::Logger> s_logger = logging::LoggerConfiguration::getConfiguration().getLogger("service"); |
| 61 | return s_logger; |
| 62 | }; |
| 63 | |
| 64 | SERVICE_TABLE_ENTRY serviceTable[] = { |
| 65 | { |
| 66 | SERVICE_NAME, |
| 67 | [](DWORD argc, LPTSTR *argv) { |
| 68 | setSyslogLogger(); |
| 69 | |
| 70 | Log()->log_trace("ServiceCtrlDispatcher"); |
| 71 | |
| 72 | s_hEvent = CreateEvent(0, TRUE, FALSE, SERVICE_TERMINATION_EVENT_NAME); |
| 73 | if (!s_hEvent) { |
| 74 | Log()->log_error("!CreateEvent lastError %x", GetLastError()); |
| 75 | return; |
| 76 | } |
| 77 | |
| 78 | s_statusHandle = RegisterServiceCtrlHandler( |
| 79 | SERVICE_NAME, |
| 80 | [](DWORD ctrlCode) { |
| 81 | Log()->log_trace("ServiceCtrlHandler ctrlCode %d", ctrlCode); |
| 82 | |
| 83 | if (SERVICE_CONTROL_STOP == ctrlCode) { |
| 84 | Log()->log_trace("ServiceCtrlHandler ctrlCode = SERVICE_CONTROL_STOP"); |
| 85 | |
| 86 | // Set service status SERVICE_STOP_PENDING. |
| 87 | s_serviceStatus.dwControlsAccepted = 0; |
| 88 | s_serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; |
| 89 | s_serviceStatus.dwWin32ExitCode = 0; |
| 90 | |
| 91 | if (!SetServiceStatus(s_statusHandle, &s_serviceStatus)) { |
| 92 | Log()->log_error("!SetServiceStatus SERVICE_STOP_PENDING lastError %x", GetLastError()); |
| 93 | } |
| 94 | |
| 95 | bool exeTerminated = false; |
| 96 | |
| 97 | SetEvent(s_hEvent); |
| 98 | |
| 99 | Log()->log_info("Wait for exe termination"); |
| 100 | switch (auto res = WaitForSingleObject(s_hProcess, WAIT_TIME_EXE_TERMINATION)) { |
| 101 | case WAIT_OBJECT_0: |
| 102 | Log()->log_info("Exe terminated"); |
| 103 | exeTerminated = true; |
| 104 | break; |
| 105 | |
| 106 | case WAIT_TIMEOUT: |
| 107 | Log()->log_error("WaitForSingleObject timeout %d", WAIT_TIME_EXE_TERMINATION); |