Skip to content

Commit

Permalink
Make ReRegisterForFinalize GC test more robust (#67896)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jakobbotsch committed Apr 13, 2022
1 parent 7eb5d7b commit 5c57f2c
Showing 1 changed file with 19 additions and 10 deletions.
29 changes: 19 additions & 10 deletions src/tests/GC/API/GC/ReRegisterForFinalize.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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) {
Expand All @@ -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;
}
}
}

0 comments on commit 5c57f2c

Please sign in to comment.