1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-09 17:44:48 +09:00

Fix race condition in nongcheap.cpp test (#105658)

This commit is contained in:
Egor Bogatov 2024-07-31 23:09:39 +02:00 committed by GitHub
parent bcbca94ce9
commit 7f10eeada7
Signed by: github
GPG key ID: B5690EEEBB952194
3 changed files with 56 additions and 14 deletions

View file

@ -141,20 +141,22 @@ namespace Profiler.Tests
return 100;
}
public const string ProfilerName = "Profiler";
public static string GetProfilerPath()
{
string profilerName;
if (TestLibrary.Utilities.IsWindows)
{
profilerName = "Profiler.dll";
profilerName = $"{ProfilerName}.dll";
}
else if (TestLibrary.Utilities.IsLinux)
{
profilerName = "libProfiler.so";
profilerName = $"lib{ProfilerName}.so";
}
else
{
profilerName = "libProfiler.dylib";
profilerName = $"lib{ProfilerName}.dylib";
}
string profilerPath = Path.Combine(Environment.CurrentDirectory, profilerName);

View file

@ -3,6 +3,7 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
namespace Profiler.Tests
@ -26,16 +27,28 @@ namespace Profiler.Tests
int gen = GC.GetGeneration("string7");
if (gen != int.MaxValue)
throw new Exception("object is expected to be in a non-gc heap for this test to work");
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void InvokeGc()
{
// Notify the profiler that we're done with the allocations
// It's a sort of workaround for possible race conditions between
// GarbageCollectionFinished and ObjectAllocated
NotifyNongcAllocationsFinished();
GC.Collect();
}
[MethodImpl(MethodImplOptions.NoInlining)]
static void Consume(object o) {}
static void Consume(object o) { }
public static int RunTest(String[] args)
[DllImport(ProfilerTestRunner.ProfilerName)]
private static extern void NotifyNongcAllocationsFinished();
public static int RunTest(String[] args)
{
AllocateNonGcHeapObjects();
InvokeGc();
Console.WriteLine("Test Passed");
return 100;
}

View file

@ -4,6 +4,12 @@
#include "nongcheap.h"
#include <vector>
#ifdef _MSC_VER
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __attribute__((visibility("default")))
#endif // _MSC_VER
GUID NonGcHeapProfiler::GetClsid()
{
// {EF0D191C-3FC7-4311-88AF-E474CBEB2859}
@ -11,8 +17,17 @@ GUID NonGcHeapProfiler::GetClsid()
return clsid;
}
std::atomic<bool> _allocationsFinished;
extern "C" DLLEXPORT void NotifyNongcAllocationsFinished()
{
printf("NotifyNongcAllocationsFinished is invoked.\n");
_allocationsFinished = true;
}
HRESULT NonGcHeapProfiler::Initialize(IUnknown* pICorProfilerInfoUnk)
{
_allocationsFinished = false;
Profiler::Initialize(pICorProfilerInfoUnk);
HRESULT hr = S_OK;
@ -20,7 +35,7 @@ HRESULT NonGcHeapProfiler::Initialize(IUnknown* pICorProfilerInfoUnk)
COR_PRF_ENABLE_OBJECT_ALLOCATED | COR_PRF_MONITOR_OBJECT_ALLOCATED,
COR_PRF_HIGH_BASIC_GC)))
{
printf("FAIL: ICorProfilerInfo::SetEventMask2() failed hr=0x%x", hr);
printf("FAIL: ICorProfilerInfo::SetEventMask2() failed hr=0x%x\n", hr);
return hr;
}
@ -41,16 +56,22 @@ HRESULT STDMETHODCALLTYPE NonGcHeapProfiler::ObjectAllocated(ObjectID objectId,
{
// We expect GetObjectGeneration to return an error (CORPROF_E_NOT_GC_OBJECT)
// for non-GC objects.
printf("FAIL: GetObjectGeneration failed for nongc object: hr=0x%x\n", hr);
_failures++;
}
_nonGcHeapObjects++;
if (gen.rangeLength != 0 || gen.rangeLengthReserved != 0 || gen.rangeStart != 0)
{
printf("FAIL: GetObjectGeneration returned unexpected values: rangeLength=%u, rangeLengthReserved=%u, rangeStart=%p\n",
(uint32_t)gen.rangeLength, (uint32_t)gen.rangeLengthReserved, (void*)gen.rangeStart);
_failures++;
}
_nonGcHeapObjects++;
}
else if (FAILED(hr))
{
printf("FAIL: GetObjectGeneration failed: hr=0x%x\n", hr);
_failures++;
}
return S_OK;
@ -60,6 +81,12 @@ HRESULT NonGcHeapProfiler::GarbageCollectionFinished()
{
SHUTDOWNGUARD();
if (!_allocationsFinished)
{
printf("Ignoring this GarbageCollectionFinished: NotifyNongcAllocationsFinished has not been invoked yet.\n");
return S_OK;
}
_garbageCollections++;
std::vector<uint64_t> segment_starts;
@ -93,13 +120,13 @@ HRESULT NonGcHeapProfiler::GarbageCollectionFinished()
if (nongc_segments[i].rangeLength > nongc_segments[i].rangeLengthReserved)
{
printf("FAIL: GetNonGCHeapBounds: rangeLength > rangeLengthReserved");
printf("FAIL: GetNonGCHeapBounds: rangeLength > rangeLengthReserved\n");
_failures++;
}
if (!nongc_segments[i].rangeStart)
{
printf("FAIL: GetNonGCHeapBounds: rangeStart is null");
printf("FAIL: GetNonGCHeapBounds: rangeStart is null\n");
_failures++;
}
segment_starts.push_back(nongc_segments[i].rangeStart);
@ -128,13 +155,13 @@ HRESULT NonGcHeapProfiler::GarbageCollectionFinished()
if (gc_segments[i].rangeLength > gc_segments[i].rangeLengthReserved)
{
printf("FAIL: GetGenerationBounds: rangeLength > rangeLengthReserved");
printf("FAIL: GetGenerationBounds: rangeLength > rangeLengthReserved\n");
_failures++;
}
if (!gc_segments[i].rangeStart)
{
printf("FAIL: GetGenerationBounds: rangeStart is null");
printf("FAIL: GetGenerationBounds: rangeStart is null\n");
_failures++;
}
segment_starts.push_back(gc_segments[i].rangeStart);
@ -154,12 +181,12 @@ HRESULT NonGcHeapProfiler::GarbageCollectionFinished()
if (segment_starts[i] == segment_starts[i+1])
{
printf("FAIL: Duplicated segment starts");
printf("FAIL: Duplicated segment starts\n");
_failures++;
}
if (segment_ends[i] == segment_ends[i+1])
{
printf("FAIL: Duplicated segment ends");
printf("FAIL: Duplicated segment ends\n");
_failures++;
}
if (segment_ends[i] > segment_starts[i+1])
@ -211,7 +238,7 @@ HRESULT NonGcHeapProfiler::GarbageCollectionFinished()
if (nonGcObjectsEnumerated != _nonGcHeapObjects)
{
printf("FAIL: objectAllocated(%d) != _nonGcHeapObjects(%d)\n!", nonGcObjectsEnumerated, (int)_nonGcHeapObjects);
printf("FAIL: nonGcObjectsEnumerated(%d) != _nonGcHeapObjects(%d)\n!", nonGcObjectsEnumerated, (int)_nonGcHeapObjects);
_failures++;
}
}