Skip to content

Compare the stored StartTime before treating a PID as another instance [patch] - #185

Merged
matt-edmondson merged 3 commits into
mainfrom
fix/180-compare-start-time
Sep 28, 2026
Merged

matt-edmondson merged 3 commits into
mainfrom
fix/180-compare-start-time

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #180

What was wrong

WritePidFile records StartTime, but IsStoredProcessRunning and IsStoredProcessRunningByName never read it. An app launched through the shared dotnet host has the process name dotnet and the host's path as its main module, and so does every other dotnet process. A stale PID file whose PID was later reused by an MSBuild node or a dotnet tool therefore looked like another instance, and ExitIfAlreadyRunning() quietly exited until that process ended.

Change

  • New HasStoredStartTime check, used by both identity checks. The running process's StartTime must be within 1 s of the stored value. Both values are compared in UTC, and the tolerance covers the JSON round trip and clock granularity.
  • The comparison is skipped, so the existing name and module check alone decides, when:
    • the stored StartTime is default, which is how PID files written before the field existed deserialize
    • the running process's start time can't be read (InvalidOperationException / Win32Exception)
  • The README already listed start time among the attributes it verifies. This change makes that statement true.

Tests

  • IsAlreadyRunning_WithMatchingProcessButDifferentStartTime_ShouldReturnFalse covers the acceptance criterion. The PID file describes a live helper process by PID, name and main module, with a start time an hour earlier. It fails with the fix reverted and passes with it.
  • IsAlreadyRunning_WithMatchingProcessAndStartTime_ShouldReturnTrue confirms that a genuine match is still detected.
  • IsAlreadyRunning_WithMatchingProcessAndNoStoredStartTime_ShouldReturnTrue covers the fallback for older PID files.
  • dotnet test: 29/29 passed on Linux (net10.0). The Release build had no warnings.

This PR is independent of the separate fixes for #181 and #182 (PID-file write/read races), which touch different methods in the same file.

🤖 Generated with Claude Code

https://claude.ai/code/session_018x3sGQTDEmvXP1cRdbmmkx


Generated by Claude Code

…e [patch]

WritePidFile records the process start time, but nothing read it back. For an
app run through the shared dotnet host, the process name and main module match
every other dotnet process, so a stale PID recycled onto an MSBuild node or a
dotnet tool blocked the app from launching. Both identity checks now also
require the running process's start time to match the stored one within one
second. PID files without a start time, and processes whose start time cannot
be read, keep the previous check.

Fixes #180

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018x3sGQTDEmvXP1cRdbmmkx
On Windows a freshly started process reports no main module until the loader
has finished, so the tests recorded a null module path and then compared it
against the loaded one. The helper now waits until its main module is readable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018x3sGQTDEmvXP1cRdbmmkx
The fallbacks for an unreadable start time only run when the OS denies access,
which no live process in the test suite triggers. The comparison now takes the
running start time as a delegate so its tolerance, UTC round trip and fallbacks
are tested directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018x3sGQTDEmvXP1cRdbmmkx
@sonarqubecloud

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit aded9e9 into main Sep 28, 2026
12 checks passed
@matt-edmondson
matt-edmondson deleted the fix/180-compare-start-time branch September 28, 2026 13:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stored StartTime is never compared, so apps launched via the dotnet host are blocked by any unrelated dotnet process that reuses a stale PID

2 participants