Repository navigation
Run GC.GetGeneration test in its own process - #135657
Merged
janvorli merged 1 commit intoOct 15, 2026
Merged
Conversation
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
|
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. |
Contributor
|
Tagging subscribers to this area: @anicka-net, @dotnet/gc |
Contributor
Author
|
Thanks @janvorli for the review and the merge! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
GC/API/GC/GetGenerationfails intermittently on CoreCLR legs because an object allocated just beforeGC.Collect()is still in generation 0 afterwards:#126108 removed this test's
RequiresProcessIsolation, which had been there forGCStressIncompatible; that skip became a[SkipOnCoreClr]attribute. Since then the test has run in-process in the mergedGCrunner, after other tests. #132076 restored isolation forCollect,Collect0andCollect1, whose generation assertions had started failing after the same change. It did not includeGetGeneration. 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 toGetGeneration.csproj: the same property group, with the same comment.I chose not to make the test tolerate an object that stays in gen0.
objectTestandarrayTestexist 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 callGetGeneration(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.
GC/API/GC/GetGeneration/GetGeneration.dllin-process. After it, the runner reportsGC/API/GC/GetGeneration/GetGeneration.cmdand runs the generatedGetGeneration.shin a child process, as it already does forCollect0andCollect1. The test's result name in CI changes accordingly, from.dllto.cmd.GCrunner 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 oneGetGenerationfailure 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.GetGeneration.dllinto a host process and calledTestEntryPoint30,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 printedObjectTest 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.