Skip to content

Run GC.GetGeneration test in its own process - #135657

Merged
janvorli merged 1 commit into
dotnet:mainfrom
pcshrosbree:fix/gc-getgeneration-process-isolation
Oct 15, 2026
Merged

janvorli merged 1 commit into
dotnet:mainfrom
pcshrosbree:fix/gc-getgeneration-process-isolation

Conversation

@pcshrosbree

Copy link
Copy Markdown
Contributor

GC/API/GC/GetGeneration fails intermittently on CoreCLR legs because an object allocated just before GC.Collect() is still in generation 0 afterwards:

Running test: GC/API/GC/GetGeneration/GetGeneration.dll
ObjectTest Passed!
0 0
arrayTest Failed!
failTest Passed!

Test for GetGeneration() FAILED!

#126108 removed this test's RequiresProcessIsolation, which had been there for GCStressIncompatible; that skip became a [SkipOnCoreClr] attribute. Since then the test has run in-process in the merged GC runner, after other tests. #132076 restored isolation for Collect, Collect0 and Collect1, whose generation assertions had started failing after the same change. It did not include GetGeneration. In #132291, janvorli said the most likely reason is the same as for the Collect tests and that the fix would be the same as #132076. This PR adds that change to GetGeneration.csproj: the same property group, with the same comment.

I chose not to make the test tolerate an object that stays in gen0. objectTest and arrayTest exist to check that a full collection promotes a live, newly allocated object, so accepting "0 0" would remove the check rather than fix it. The other tests in the directory that call GetGeneration (GetGenerationWR, GetGenerationWR2, GetGeneration_box, GetGeneration_fail) do not assert promotion, so I left them in the merged runner.

Validation used one existing local linux-x64 Checked runtime, with the priority-0 GC test tree built at this PR's parent and at this commit. The runtime was the control build from the earlier #135520 investigation, not an unmodified main build; it was not rebuilt at either of these commits, since this change touches only a test project.

  • Before the change, the merged runner runs GC/API/GC/GetGeneration/GetGeneration.dll in-process. After it, the runner reports GC/API/GC/GetGeneration/GetGeneration.cmd and runs the generated GetGeneration.sh in a child process, as it already does for Collect0 and Collect1. The test's result name in CI changes accordingly, from .dll to .cmd.
  • I ran the full merged GC runner from each tree 200 times, interleaved, with 12 runs in parallel and the same corerun arguments as the plain CI work item reported in GC.GetGeneration test fails under R2R with JitStressRegs=2 #132291. All 53 tests passed in every run of both sets. Isolation adds one test process per invocation. The median runner time was 98.25 s with the change and 97.65 s without; these concurrent local timings do not establish its CI cost. These runs do not demonstrate a reduction in failures. The earlier investigation described in my comment on GC.GetGeneration test fails under R2R with JitStressRegs=2 #132291 recorded one GetGeneration failure in 400 full merged-runner runs, 200 on each of two runtime builds used to investigate [Interpreter] Raise a pending thread abort again after a catch handler #135520, both without this isolation change.
  • To check the mechanism, I loaded the merged-runner GetGeneration.dll into a host process and called TestEntryPoint 30,000 times (three runs of 10,000), resetting the test's static counter between calls. Before each call, the host pinned 200 arrays of 1,000 bytes, ran one collection while they were held, released them, and pinned 200 new ones. 56 of the calls failed, and the first failure in each run printed ObjectTest Passed!, 0 0, arrayTest Failed!, as in CI. The same host without the pins had no failures in 30,000 calls, and pinning only right before each call had none in 6,000. This shows one way that pins and prior collections in the same process can produce this failure; it does not establish whether pinned objects caused the CI failures or where they came from. With the change, the test runs in its own process, which pins held by the runner process cannot affect.

Fixes #132291

cc @kkokosa, since #132291 is assigned to you.

Note

This change was prepared with AI assistance (Anthropic Claude, checked by OpenAI Codex) at my request. I reviewed the change and the measurements before opening.

GetGeneration checks that a freshly allocated object moves out of
gen0 after GC.Collect(). Since dotnet#126108 it runs inside the merged GC
runner after other tests, and pinned gen0 objects left by earlier
work can make the GC keep the fresh object in gen0 ("0 0").
Restore process isolation, as dotnet#132076 did for the Collect tests.

Fixes dotnet#132291
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Oct 13, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @anicka-net, @dotnet/gc
See info in area-owners.md if you want to be subscribed.

@janvorli janvorli left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you!

@janvorli
janvorli merged commit acd4c1a into dotnet:main Oct 15, 2026
87 of 89 checks passed
@pcshrosbree

Copy link
Copy Markdown
Contributor Author

Thanks @janvorli for the review and the merge!

@pcshrosbree
pcshrosbree deleted the fix/gc-getgeneration-process-isolation branch October 15, 2026 21:52
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 12.0-preview1 milestone Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-GC-coreclr community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GC.GetGeneration test fails under R2R with JitStressRegs=2

2 participants