Skip to content

Serialize the PID file with a source-generated context so trimmed and AOT apps launch [patch] - #212

Open
matt-edmondson wants to merge 1 commit into
mainfrom
claude/source-generated-pid-json
Open

matt-edmondson wants to merge 1 commit into
mainfrom
claude/source-generated-pid-json

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #210

What was wrong

CheckPidFileContents and WritePidFile called the reflection overloads of JsonSerializer. Apps published with PublishTrimmed or PublishAot run with JsonSerializer.IsReflectionEnabledByDefault=false, so both calls throw InvalidOperationException. Neither call site catches it, so it escaped ShouldLaunch() / ExitIfAlreadyRunning() and the app crashed on every launch.

Change

  • Added ProcessInfoJsonContext, a [JsonSerializable(typeof(ProcessInfo))] source-generated context. Both calls now go through ProcessInfoJsonContext.Default.ProcessInfo. The JSON shape is unchanged (same default options, PascalCase names), so PID files written by earlier versions still read.
  • Set IsAotCompatible on the net7.0+ targets. With it, reintroducing a reflection call fails the build: I checked by temporarily putting back JsonSerializer.Serialize(processInfo), which produced IL2026 and IL3050 errors. With the fix, the library builds with no warnings on any target.
  • The test project now sets JsonSerializerIsReflectionEnabledByDefault=false, the runtimeconfig setting a trimmed or AOT app gets. Its mirror ProcessInfo is read and written through a test-side TestJsonContext, so every existing test now exercises the library the way those apps run it.
  • Updated CLAUDE.md to describe all this.

The issue also mentions a separate trimmed-publish failure (TypeLoadException in ktsu.Semantics.Paths.AbsoluteFilePath). That lives in Semantics and is out of scope here. The JIT repro from the issue, with reflection disabled in the runtimeconfig, is what this PR fixes and tests.

Tests

  • Before the library change, with reflection disabled in the test project: 14 tests fail with Reflection-based serialization has been disabled for this application. Among them are ShouldLaunch_WithNoExistingInstance_ShouldReturnTrue, ShouldLaunch_WhenAlreadyRunning_ShouldReturnFalse and the WritePidFile_* tests.
  • After: 42/42 pass.
  • dotnet pack -c Release succeeds, so package validation is happy.

Generated by Claude Code

… AOT apps launch [patch]

ShouldLaunch() read and wrote the PID file through reflection-based
System.Text.Json, which an app published with PublishTrimmed or
PublishAot runs with disabled, so the InvalidOperationException escaped
and the app crashed on every launch. Both calls now use
ProcessInfoJsonContext; the JSON shape is unchanged. IsAotCompatible on
net7.0+ turns a future reflection call into a build error, and the test
project runs with JsonSerializerIsReflectionEnabledByDefault=false so
every test exercises that path.

Fixes #210

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

sonarqubecloud Bot commented Nov 4, 2026

Copy link
Copy Markdown

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.

An app published trimmed or Native AOT crashes on its first ShouldLaunch() with "Reflection-based serialization has been disabled"

2 participants