mirror of
https://github.com/wu736139669/hapi.git
synced 2026-10-24 22:10:59 +00:00
* fix(cli): identify the Windows runner process through CIM isHapiRunnerProcess() checks that the PID persisted in runner state still belongs to a HAPI runner. On Windows it read the command line through wmic and returned true for any live PID when that spawn failed. wmic is absent on current Windows 11 builds, so that branch is the only one those hosts take and the check degrades to a liveness test. When a reboot hands the stale runner PID to another process, runner start adopts it and exits without starting a runner. Query the command line through PowerShell Get-CimInstance Win32_Process first and keep wmic as the fallback, matching getProcessStartMarker() in this file. A probe that succeeds without reporting a command line falls through to the next one, and an unreadable identity still preserves the live state, so a real runner is never discarded on a probe that came back empty. * fix(cli): keep an unverifiable runner pid out of destructive paths The identity check answered a boolean, so "alive but unidentifiable" had to collapse into one of the two verdicts. It collapsed into "this is the runner", and runner start acts on that by calling stopRunner(), which force kills the persisted pid once the HTTP stop times out. A reused pid that no probe can read was therefore still reachable by a kill. Report the identity as runner, foreign, unknown or dead instead. Only a confirmed runner is reported as running. An unknown pid is neither signalled nor cleaned up, because clearing the state would also drop the lock that keeps a second runner from starting, and the pid may still be a healthy runner behind a probe that failed transiently. The posix branch had the same fail-open through isProcessAlive and now takes the shared unknown path. * fix(cli): gate the runner force kill on a confirmed identity Two paths reach stopRunner() with a boolean that cannot carry "unverified". runner start stops an existing runner, and the spawned start-sync child reads the same answer through isRunnerRunningCurrentlyInstalledHappyVersion(), where a false result is read as a version mismatch and also calls stopRunner(). Propagating the unknown state to each caller would leave the next path open, so check the identity where the process is actually signalled: only a confirmed runner is force killed. Also stop reading WMIC's column header as a command line. wmic get CommandLine prints the header even when the property is empty or unreadable, so trimmed stdout was never empty on success and an unreadable process was classified as foreign, which cleared the state and the lock instead of preserving them. * fix(cli): gate the whole runner stop on a confirmed identity The identity check sat in front of the force kill, but stopRunner() first sends an unauthenticated POST /stop to the port recorded in runner state. An http request is a signal too: if the pid and its port were both reused, an unrelated local service receives that request before the check runs. Move the check to the start of stopRunner() so a pid that is not a confirmed runner is never contacted at all. The later force-kill check is redundant once the whole sequence is gated, so it goes away.