Skip to content

test: keep observer alive through callback completion in GrainObserverWithGenericMethods - #11439

Merged
ReubenBond merged 1 commit into
dotnet:mainfrom
ReubenBond:rb-issue-11427-grainobserver-generic-hang
Oct 8, 2026
Merged

ReubenBond merged 1 commit into
dotnet:mainfrom
ReubenBond:rb-issue-11427-grainobserver-generic-hang

Conversation

@ReubenBond

@ReubenBond ReubenBond commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

Problem

GrainObserverWithGenericMethods awaits a callback task after its final use of the observer object. Orleans object references track observer targets weakly, so the test must keep the observer strongly reachable through callback completion.

The Linux net10.0 hang in #11427 exposed this lifetime gap (run 37592539156, job 112697233952, head 3c27db51 on #11420). The retained dump contains the pending callback task and observer registration, but no surviving ObserverWithGenericMethods instance. Runtime dispatch for the matching SetValue("ToastedEnchiladas") message had completed; that establishes completion of dispatch handling rather than successful invocation of the observer method.

Solution

Add GC.KeepAlive(localObject) after callback completion and the result assertion. This retains the observer for the entire operation and follows the existing pattern in GrainCallFilterTests and ObserverCancellationTokenTests, preserving the runtime's established weak-reference lifetime contract.

Rationale

The observer-lifetime requirement predates the recent networking changes. A contribution from #10074's delivery timing remains an unmeasured hypothesis; no recent introducing change has been established. The patch fixes the test's lifetime guarantee directly.

Closes #11427.

…rWithGenericMethods

Fixes a latent GC-lifetime race in a client-side observer test that
produced a 10-minute CI hang (dotnet#11427). CreateObjectReference
tracks its target via a WeakReference; once ValueTask is read, the test's
local observer field is no longer used by the method body, so a GC running
while the one-way SetValue call is still in flight could collect the
observer before it is invoked. The dispatched message is processed to
completion normally (admission gates open, no runtime deadlock), but the
invocation silently finds a collected target, leaving the awaited
TaskCompletionSource uncompleted forever. Add GC.KeepAlive, matching the
existing pattern used elsewhere in the test suite for this exact hazard
(GrainCallFilterTests, ObserverCancellationTokenTests).
Copilot AI balanced review requested due to automatic review settings October 8, 2026 09:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The focused test-only fix addresses the lifetime hazard while preserving the existing callback assertion.

0 open findings

What changed in this PR

Fixes the observer-lifetime race behind #11427 without changing Orleans runtime behavior or callback verification.

Changes:

  • Adds GC.KeepAlive(localObject) after the callback assertion.
  • Documents why the observer must remain strongly reachable.
File Description
test/​Orleans.DefaultCluster.Tests/​CodeGenTests/​GeneratorGrainTest.cs Keeps the observer alive through callback completion to prevent premature collection and hangs.

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Code coverage

Metric Pull request Current main Variance
Lines 83.27% (117,950 / 141,644) 83.28% (117,956 / 141,644) -0.0042 pp
Branches 72.79% (34,998 / 48,080) 72.79% (34,998 / 48,080) 0.0000 pp

Report-only conclusion: regressed.

The current-main baseline is commit 165acd0d33 and uses the same reviewed coverage matrix.

Coverage combines every CI test matrix job, including providers, CodeGen, .NET 8/10, Linux, Windows, and macOS, using canonical physical source and branch identities.

The comparison remains report-only while normal line and branch variance is calibrated.

Coverage details

@ReubenBond
ReubenBond merged commit 6211bea into dotnet:main Oct 8, 2026
91 of 92 checks passed
@ReubenBond
ReubenBond deleted the rb-issue-11427-grainobserver-generic-hang branch October 8, 2026 15:50
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.

test(codegen): investigate GrainObserverWithGenericMethods hang on Linux net10

2 participants