diff --git a/IntelPresentMon/PMInstallerLib/Library.wxs b/IntelPresentMon/PMInstallerLib/Library.wxs index 4edfcbfa6..d938573e1 100644 --- a/IntelPresentMon/PMInstallerLib/Library.wxs +++ b/IntelPresentMon/PMInstallerLib/Library.wxs @@ -74,7 +74,33 @@ Impersonate="no" Return="ignore" /> + + + + + + NOT REMOVE + NOT REMOVE 1 diff --git a/IntelPresentMon/PresentMonService/CliOptions.h b/IntelPresentMon/PresentMonService/CliOptions.h index 7665a3a90..79a3bb92a 100644 --- a/IntelPresentMon/PresentMonService/CliOptions.h +++ b/IntelPresentMon/PresentMonService/CliOptions.h @@ -26,6 +26,7 @@ namespace clio private: Group gd_{ this, "Debugging", "Aids in debugging this tool" }; public: Flag debug{ this, "--debug,-d", "Stall service by running in a loop after startup waiting for debugger to connect" }; Option timedStop{ this, "--timed-stop", -1, "Signal stop event after specified number of milliseconds" }; + Option recoveryFailCount{ this, "--recovery-fail-count", 0, "Failure count SCM passes when it starts the service on recovery" }; private: Group gr_{ this, "Playback", "Playback of recorded ETL files" }; public: Option etlTestFile{ this, "--etl-test-file", "", "Etl test file including necessary path", CLI::ExistingFile }; diff --git a/IntelPresentMon/PresentMonService/Service.cpp b/IntelPresentMon/PresentMonService/Service.cpp index 8cf103424..6f58f7f0b 100644 --- a/IntelPresentMon/PresentMonService/Service.cpp +++ b/IntelPresentMon/PresentMonService/Service.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include "PMMainThread.h" #include #include @@ -134,7 +133,7 @@ void ConcreteService::ServiceInit() FALSE, // auto reset event FALSE, // not signaled NULL); // no name - if (mServiceStopEventHandle == nullptr) { + if (mResetPowerTelemetryEventHandle == nullptr) { ReportServiceStatus(SERVICE_STOPPED, GetLastError(), 0); return; } diff --git a/IntelPresentMon/PresentMonService/ServiceMain.cpp b/IntelPresentMon/PresentMonService/ServiceMain.cpp index c9e79006f..7ba4e80a3 100644 --- a/IntelPresentMon/PresentMonService/ServiceMain.cpp +++ b/IntelPresentMon/PresentMonService/ServiceMain.cpp @@ -50,6 +50,10 @@ int CommonEntry(DWORD argc, LPTSTR* argv, bool asApp) log::GetLevelName(log::GlobalPolicy::Get().GetLogLevel()), log::GetLevelName(PMLOG_BUILD_LEVEL_))); + if (const auto failCount = clio::Options::Get().recoveryFailCount.AsOptional()) { + pmlog_warn(std::format("SCM recovery start, fail count {}.", *failCount)).no_trace(); + } + if (asApp) { auto& svc = ConsoleDebugMockService::Get(); svc.Run(); diff --git a/README-Service.md b/README-Service.md index 8317544c6..dfa359487 100644 --- a/README-Service.md +++ b/README-Service.md @@ -18,4 +18,22 @@ PresentMonAPI.h, PresentMonAPI2Loader.lib, and PresentMonAPI2Loader.dll are opti ## Diagnostics -All of the PresentMonAPI functions return an enum type PM_STATUS that indicates success/failure and can give a hint as to the cause of any failure. For more detailed diagnostic messages, refer to PresentMonDiagnostics.h found in the PresentMonAPI2 project directory. \ No newline at end of file +All of the PresentMonAPI functions return an enum type PM_STATUS that indicates success/failure and can give a hint as to the cause of any failure. For more detailed diagnostic messages, refer to PresentMonDiagnostics.h found in the PresentMonAPI2 project directory. + +# Failure recovery + +The installer configures `PresentMonSharedService` so Windows starts it again after an abnormal process exit, then stops trying. The Recovery action is "Run a program", not "Restart the Service". Restart does not take a command line. The program is `sc.exe start PresentMonSharedService --recovery-fail-count %1%`. `%1%` is the failure-count placeholder SCM substitutes when it runs the command (the same placeholder the Recovery tab checkbox documents as `/fail=%1%`). `sc.exe start` passes `--recovery-fail-count N` through to the service. The command string is fixed at install time. The service does not register or rewrite it. + +| Failure in the window | Action | Holdoff | +| --- | --- | --- | +| 1st | start with `--recovery-fail-count 1` | 2 seconds | +| 2nd | start with `--recovery-fail-count 2` | 15 seconds | +| 3rd | start with `--recovery-fail-count 3` | 60 seconds | +| 4th | start with `--recovery-fail-count 4` | 5 minutes | +| 5th and later | stay stopped | | + +The failure count resets after 30 minutes with no failure. That reset does not start the service. A later start gets a fresh budget only after those 30 minutes have elapsed. A clean stop (`sc.exe stop`) does not count as a failure. + +On a recovery start the service log contains `SCM recovery start, fail count N`. A normal start has no `--recovery-fail-count` argument and does not log that line. + +An existing client session is not reconnected. The next API call on that handle returns `PM_STATUS_SESSION_NOT_OPEN`. Opening a new session after the service is back is the caller's responsibility.