From 5c57f2c0cda44176e237574ceb51d659ef9915fa Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Wed, 13 Apr 2022 09:24:19 +0200 Subject: [PATCH] Make ReRegisterForFinalize GC test more robust (#67896) There is no guarantee that the JIT does not introduce a temporary for the read of the fields `obj1` and `obj2` when they are passed to the function calls, which might keep them alive even when nulling out the fields. This happens when CFG is enabled, causing the test to fail. Change the test to access the fields in separate methods marked as noinline to fix the problem. --- src/tests/GC/API/GC/ReRegisterForFinalize.cs | 29 +++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/tests/GC/API/GC/ReRegisterForFinalize.cs b/src/tests/GC/API/GC/ReRegisterForFinalize.cs index 75a590f8235e9..8e8678566a441 100644 --- a/src/tests/GC/API/GC/ReRegisterForFinalize.cs +++ b/src/tests/GC/API/GC/ReRegisterForFinalize.cs @@ -4,14 +4,15 @@ // Tests ReRegisterForFinalize() using System; +using System.Runtime.CompilerServices; public class Test_ReRegisterForFinalize { public class Dummy { - + public static int flag; ~Dummy() { - Console.WriteLine("In Finalize() of Dummy"); + Console.WriteLine("In Finalize() of Dummy"); if(flag == 0) flag=1; // one object has visited; else flag=0; //error-- both objects have visited } @@ -21,24 +22,32 @@ public class CreateObj{ Dummy obj1; Dummy obj2; + [MethodImpl(MethodImplOptions.NoInlining)] public CreateObj() { obj1 = new Dummy(); obj2 = new Dummy(); - + GC.SuppressFinalize(obj1); // should not call the Finalize() for obj1 GC.SuppressFinalize(obj2); // should not call the Finalize() for obj2 } - public bool RunTest() { - + // Make sure we have no references left to obj1 by doing this in a + // non-inlined separate function. + [MethodImpl(MethodImplOptions.NoInlining)] + private void ReRegisterAndNullFields() + { GC.ReRegisterForFinalize(obj1); // should call Finalize() for obj1 now. - + obj1=null; obj2=null; + } + + public bool RunTest() { + ReRegisterAndNullFields(); GC.Collect(); - + GC.WaitForPendingFinalizers(); // call all Finalizers. if(Dummy.flag==1) { @@ -48,19 +57,19 @@ public class CreateObj{ return false; } } - + } public static int Main() { CreateObj temp = new CreateObj(); bool passed = temp.RunTest(); - + if(passed) { Console.WriteLine("Test for ReRegisterForFinalize() passed!"); return 100; } else { Console.WriteLine("Test for ReRegisterForFinalize() failed!"); - return 1; + return 1; } } }