Try to fix finalizer-based async tests (#56384)
authorStephen Toub <stoub@microsoft.com>
Tue, 27 Jul 2021 21:17:03 +0000 (17:17 -0400)
committerGitHub <noreply@github.com>
Tue, 27 Jul 2021 21:17:03 +0000 (17:17 -0400)
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.

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

index 1babd5ea925ca163a472c41013b11e503c626ff1..d762f2b639fc9d29c02cbaef73901bdd73c3184a 100644 (file)
@@ -532,7 +532,7 @@ namespace System.Threading.Tasks.Tests
             // We want to make sure that holding on to the resulting Task doesn't keep
             // that finalizable object alive.
 
-            var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
+            bool finalized = false;
 
             Task t = null;
 
@@ -544,7 +544,7 @@ namespace System.Threading.Tasks.Tests
                     GC.KeepAlive(s); // keep s referenced by the state machine
                 }
 
-                var state = new InvokeActionOnFinalization { Action = () => tcs.SetResult() };
+                var state = new InvokeActionOnFinalization { Action = () => Volatile.Write(ref finalized, true) };
                 var al = new AsyncLocal<object>() { Value = state }; // ensure the object is stored in ExecutionContext
                 t = YieldOnceAsync(state); // ensure the object is stored in the state machine
                 al.Value = null;
@@ -556,19 +556,15 @@ namespace System.Threading.Tasks.Tests
             await t; // wait for the async method to complete and clear out its state
             await Task.Yield(); // ensure associated state is not still on the stack as part of the antecedent's execution
 
-            for (int i = 0; i < 2; i++)
+            for (int i = 0; i < 10 && !Volatile.Read(ref finalized); i++)
             {
                 GC.Collect();
                 GC.WaitForPendingFinalizers();
             }
 
-            try
-            {
-                await tcs.Task.WaitAsync(TimeSpan.FromSeconds(60));
-            }
-            catch (Exception e)
+            if (!Volatile.Read(ref finalized))
             {
-                Environment.FailFast("Look at the created dump", e);
+                Environment.FailFast("Look at the created dump");
             }
 
             GC.KeepAlive(t); // ensure the object is stored in the state machine
index 5b832f2af56cfbe2965883aa6c2195d49d49a65f..8374c56056996aebbf3c8ea49df74355bc360f62 100644 (file)
@@ -37,13 +37,13 @@ namespace System.Threading.Tasks.Tests
             // We want to make sure that holding on to the resulting Task doesn't keep
             // that finalizable object alive.
 
-            var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
+            bool finalized = false;
 
             Task t = null;
 
             Thread runner = new Thread(() =>
             {
-                var state = new InvokeActionOnFinalization { Action = () => tcs.SetResult() };
+                var state = new InvokeActionOnFinalization { Action = () => Volatile.Write(ref finalized, true) };
                 var al = new AsyncLocal<object>(){ Value = state }; // ensure the object is stored in ExecutionContext
                 t = Task.Run(() => { }); // run a task that'll capture EC
                 al.Value = null;
@@ -54,19 +54,15 @@ namespace System.Threading.Tasks.Tests
 
             await t; // wait for the task method to complete and clear out its state
 
-            for (int i = 0; i < 2; i++)
+            for (int i = 0; i < 10 && !Volatile.Read(ref finalized); i++)
             {
                 GC.Collect();
                 GC.WaitForPendingFinalizers();
             }
 
-            try
-            {
-                await tcs.Task.WaitAsync(TimeSpan.FromSeconds(60)); // finalizable object should have been collected and finalized
-            }
-            catch (Exception e)
+            if (!Volatile.Read(ref finalized))
             {
-                Environment.FailFast("Look at the created dump", e);
+                Environment.FailFast("Look at the created dump");
             }
 
             GC.KeepAlive(t); // ensure the object is stored in the state machine