-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix handling of collectible thread statics and GC (#40671)
- NonGc Thread statics helper returns a ByRef, not a pointer for collectible statics - Add test coverage for collectible statics - Remove test coverage for converting thread static variable into byref and using that to keep alive the static data as it wasn't fully safe itself
- Loading branch information
1 parent
ead2cd5
commit c47a92d
Showing
10 changed files
with
219 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
src/tests/Loader/CollectibleAssemblies/Statics/Accessor.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
|
||
public interface IStaticTest | ||
{ | ||
void SetStatic(int val, int val2, int val3, int val4, int val5); | ||
void GetStatic(out int val1, out int val2, out int val3, out int val4, out int val5); | ||
void SetStaticObject(object val, object val2, object val3, object val4, object val5); | ||
void GetStaticObject(out object val1, out object val2, out object val3, out object val4, out object val5); | ||
} |
11 changes: 11 additions & 0 deletions
11
src/tests/Loader/CollectibleAssemblies/Statics/Accessor.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
<OutputType>Library</OutputType> | ||
<CLRTestKind>BuildOnly</CLRTestKind> | ||
<CLRTestPriority>0</CLRTestPriority> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<Compile Include="Accessor.cs" /> | ||
</ItemGroup> | ||
</Project> |
54 changes: 54 additions & 0 deletions
54
src/tests/Loader/CollectibleAssemblies/Statics/CollectibleStatics.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.IO; | ||
using System.Reflection; | ||
using System.Reflection.Emit; | ||
using System.Runtime.CompilerServices; | ||
using System.Runtime.InteropServices; | ||
using System.Runtime.Loader; | ||
|
||
class Program | ||
{ | ||
static int Main(string[] args) | ||
{ | ||
var alc = new AssemblyLoadContext("test", isCollectible: true); | ||
var a = alc.LoadFromAssemblyPath(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Unloaded.dll")); | ||
|
||
var accessor = (IStaticTest)Activator.CreateInstance(a.GetType("StaticTest")); | ||
accessor.SetStatic(12759, 548739, 5468, 8518, 9995); | ||
accessor.GetStatic(out int val1, out int val2, out int val3, out int val4, out int val5); | ||
if (val1 != 12759) | ||
return 1; | ||
if (val2 != 548739) | ||
return 2; | ||
if (val3 != 5468) | ||
return 3; | ||
if (val4 != 8518) | ||
return 4; | ||
if (val5 != 9995) | ||
return 5; | ||
|
||
object obj1 = new object(); | ||
object obj2 = new object(); | ||
object obj3 = new object(); | ||
object obj4 = new object(); | ||
object obj5 = new object(); | ||
accessor.SetStaticObject(obj1, obj2, obj3, obj4, obj5); | ||
accessor.GetStaticObject(out object val1Obj, out object val2Obj, out object val3Obj, out object val4Obj, out object val5Obj); | ||
if (val1Obj != obj1) | ||
return 11; | ||
if (val2Obj != obj2) | ||
return 12; | ||
if (val3Obj != obj3) | ||
return 13; | ||
if (val4Obj != obj4) | ||
return 14; | ||
if (val5Obj != obj5) | ||
return 15; | ||
|
||
GC.KeepAlive(accessor); | ||
return 100; | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
src/tests/Loader/CollectibleAssemblies/Statics/CollectibleStatics.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
<OutputType>Exe</OutputType> | ||
<CLRTestKind>BuildAndRun</CLRTestKind> | ||
<CLRTestPriority>0</CLRTestPriority> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<ProjectReference Include="Unloaded.csproj" /> | ||
<ProjectReference Include="Accessor.csproj" /> | ||
<Compile Include="CollectibleStatics.cs" /> | ||
</ItemGroup> | ||
</Project> |
113 changes: 113 additions & 0 deletions
113
src/tests/Loader/CollectibleAssemblies/Statics/Unloaded.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.Runtime.CompilerServices; | ||
|
||
// Use multiple classes to trigger multiple statics allocation events | ||
public class StaticTest2 | ||
{ | ||
[ThreadStatic] | ||
public static int ThreadStaticValue; | ||
public static int StaticValue; | ||
} | ||
|
||
public class StaticTest3 | ||
{ | ||
public static int StaticValue; | ||
} | ||
|
||
public class StaticTest4 | ||
{ | ||
[ThreadStatic] | ||
public static object ThreadStaticValue; | ||
public static object StaticValue; | ||
} | ||
public class StaticTest5 | ||
{ | ||
[ThreadStatic] | ||
public static object ThreadStaticValue; | ||
public static object StaticValue; | ||
} | ||
public class StaticTest6 | ||
{ | ||
public static object StaticValue; | ||
} | ||
|
||
|
||
public class StaticTest : IStaticTest | ||
{ | ||
[ThreadStatic] | ||
public static int ThreadStaticValue; | ||
public static int StaticValue; | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
public static void SetValues(out int valTargetA, int valA | ||
, out int valTargetB, int valB | ||
, out int valTargetC, int valC | ||
, out int valTargetD, int valD | ||
, out int valTargetE, int valE | ||
) | ||
{ | ||
valTargetA = valA; | ||
valTargetB = valB; | ||
valTargetC = valC; | ||
valTargetD = valD; | ||
valTargetE = valE; | ||
} | ||
|
||
public void SetStatic(int val, int val2, int val3, int val4, int val5) | ||
{ | ||
// Use this odd pathway to increase the chance that in the presence of GCStress issues will be found | ||
SetValues(out ThreadStaticValue, val | ||
, out StaticValue, val2 | ||
, out StaticTest2.StaticValue, val3 | ||
, out StaticTest2.ThreadStaticValue, val4 | ||
, out StaticTest3.StaticValue, val5 | ||
); | ||
} | ||
|
||
public void GetStatic(out int val1, out int val2, out int val3, out int val4, out int val5) | ||
{ | ||
val1 = ThreadStaticValue; | ||
val2 = StaticValue; | ||
val3 = StaticTest2.StaticValue; | ||
val4 = StaticTest2.ThreadStaticValue; | ||
val5 = StaticTest3.StaticValue; | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
public static void SetValuesObject(out object valTargetA, object valA | ||
, out object valTargetB, object valB | ||
, out object valTargetC, object valC | ||
, out object valTargetD, object valD | ||
, out object valTargetE, object valE | ||
) | ||
{ | ||
valTargetA = valA; | ||
valTargetB = valB; | ||
valTargetC = valC; | ||
valTargetD = valD; | ||
valTargetE = valE; | ||
} | ||
|
||
public void SetStaticObject(object val, object val2, object val3, object val4, object val5) | ||
{ | ||
// Use this odd pathway to increase the chance that in the presence of GCStress issues will be found | ||
SetValuesObject(out StaticTest4.ThreadStaticValue, val | ||
, out StaticTest4.StaticValue, val2 | ||
, out StaticTest5.StaticValue, val3 | ||
, out StaticTest5.ThreadStaticValue, val4 | ||
, out StaticTest6.StaticValue, val5 | ||
); | ||
} | ||
|
||
public void GetStaticObject(out object val1, out object val2, out object val3, out object val4, out object val5) | ||
{ | ||
val1 = StaticTest4.ThreadStaticValue; | ||
val2 = StaticTest4.StaticValue; | ||
val3 = StaticTest5.StaticValue; | ||
val4 = StaticTest5.ThreadStaticValue; | ||
val5 = StaticTest6.StaticValue; | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
src/tests/Loader/CollectibleAssemblies/Statics/Unloaded.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
<OutputType>Library</OutputType> | ||
<CLRTestKind>BuildOnly</CLRTestKind> | ||
<CLRTestPriority>0</CLRTestPriority> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<ProjectReference Include="Accessor.csproj" /> | ||
<Compile Include="Unloaded.cs" /> | ||
</ItemGroup> | ||
</Project> |