Skip to content

Commit cc12918

Browse files
authored
Try to fix finalizer-based async tests (#56384)
A dump from a failure showed the finalizable object we're relying on was unrooted and waiting for finalization. Issue more Collects to see if that helps.
1 parent 392ff31 commit cc12918

File tree

2 files changed

+10
-18
lines changed

2 files changed

+10
-18
lines changed

src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/AsyncTaskMethodBuilderTests.cs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ public static async Task AsyncMethodsDropsStateMachineAndExecutionContextUponCom
532532
// We want to make sure that holding on to the resulting Task doesn't keep
533533
// that finalizable object alive.
534534

535-
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
535+
bool finalized = false;
536536

537537
Task t = null;
538538

@@ -544,7 +544,7 @@ async Task YieldOnceAsync(object s)
544544
GC.KeepAlive(s); // keep s referenced by the state machine
545545
}
546546

547-
var state = new InvokeActionOnFinalization { Action = () => tcs.SetResult() };
547+
var state = new InvokeActionOnFinalization { Action = () => Volatile.Write(ref finalized, true) };
548548
var al = new AsyncLocal<object>() { Value = state }; // ensure the object is stored in ExecutionContext
549549
t = YieldOnceAsync(state); // ensure the object is stored in the state machine
550550
al.Value = null;
@@ -556,19 +556,15 @@ async Task YieldOnceAsync(object s)
556556
await t; // wait for the async method to complete and clear out its state
557557
await Task.Yield(); // ensure associated state is not still on the stack as part of the antecedent's execution
558558

559-
for (int i = 0; i < 2; i++)
559+
for (int i = 0; i < 10 && !Volatile.Read(ref finalized); i++)
560560
{
561561
GC.Collect();
562562
GC.WaitForPendingFinalizers();
563563
}
564564

565-
try
566-
{
567-
await tcs.Task.WaitAsync(TimeSpan.FromSeconds(60));
568-
}
569-
catch (Exception e)
565+
if (!Volatile.Read(ref finalized))
570566
{
571-
Environment.FailFast("Look at the created dump", e);
567+
Environment.FailFast("Look at the created dump");
572568
}
573569

574570
GC.KeepAlive(t); // ensure the object is stored in the state machine

src/libraries/System.Threading.Tasks/tests/Task/ExecutionContextFlowTest.cs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ public static async Task TaskDropsExecutionContextUponCompletion()
3737
// We want to make sure that holding on to the resulting Task doesn't keep
3838
// that finalizable object alive.
3939

40-
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
40+
bool finalized = false;
4141

4242
Task t = null;
4343

4444
Thread runner = new Thread(() =>
4545
{
46-
var state = new InvokeActionOnFinalization { Action = () => tcs.SetResult() };
46+
var state = new InvokeActionOnFinalization { Action = () => Volatile.Write(ref finalized, true) };
4747
var al = new AsyncLocal<object>(){ Value = state }; // ensure the object is stored in ExecutionContext
4848
t = Task.Run(() => { }); // run a task that'll capture EC
4949
al.Value = null;
@@ -54,19 +54,15 @@ public static async Task TaskDropsExecutionContextUponCompletion()
5454

5555
await t; // wait for the task method to complete and clear out its state
5656

57-
for (int i = 0; i < 2; i++)
57+
for (int i = 0; i < 10 && !Volatile.Read(ref finalized); i++)
5858
{
5959
GC.Collect();
6060
GC.WaitForPendingFinalizers();
6161
}
6262

63-
try
64-
{
65-
await tcs.Task.WaitAsync(TimeSpan.FromSeconds(60)); // finalizable object should have been collected and finalized
66-
}
67-
catch (Exception e)
63+
if (!Volatile.Read(ref finalized))
6864
{
69-
Environment.FailFast("Look at the created dump", e);
65+
Environment.FailFast("Look at the created dump");
7066
}
7167

7268
GC.KeepAlive(t); // ensure the object is stored in the state machine

0 commit comments

Comments
 (0)