From 592ecf87262c66dd88c5c778296c7c63ac8794bf Mon Sep 17 00:00:00 2001 From: David Mason Date: Sat, 14 Aug 2021 16:25:04 -0700 Subject: [PATCH 1/9] Small fixes, add tests --- src/coreclr/inc/profilepriv.h | 2 +- src/coreclr/inc/profilepriv.inl | 2 +- src/coreclr/vm/eetoprofinterfaceimpl.cpp | 11 --- src/coreclr/vm/profdetach.cpp | 4 +- src/coreclr/vm/proftoeeinterfaceimpl.cpp | 6 +- .../profiler/common/ProfilerTestRunner.cs | 29 ++++++- src/tests/profiler/multiple/multiple.cs | 47 ++++++++++ src/tests/profiler/multiple/multiple.csproj | 15 ++++ src/tests/profiler/native/CMakeLists.txt | 1 + src/tests/profiler/native/classfactory.cpp | 81 +++++++++++------ .../native/eltprofiler/slowpatheltprofiler.h | 2 +- .../eventpipereadingprofiler.h | 2 +- .../eventpipewritingprofiler.h | 2 +- .../gcallocateprofiler/gcallocateprofiler.h | 2 +- .../native/gcbasicprofiler/gcbasicprofiler.h | 2 +- .../profiler/native/gcprofiler/gcprofiler.h | 2 +- .../getappdomainstaticaddress.h | 2 +- .../metadatagetdispenser.h | 2 +- .../profiler/native/multiple/multiple.cpp | 87 +++++++++++++++++++ src/tests/profiler/native/multiple/multiple.h | 32 +++++++ .../native/nullprofiler/nullprofiler.h | 2 +- src/tests/profiler/native/profiler.cpp | 6 ++ src/tests/profiler/native/profiler.h | 4 +- .../native/rejitprofiler/rejitprofiler.h | 2 +- .../native/releaseondetach/releaseondetach.h | 2 +- .../profiler/native/transitions/transitions.h | 2 +- 26 files changed, 289 insertions(+), 62 deletions(-) create mode 100644 src/tests/profiler/multiple/multiple.cs create mode 100644 src/tests/profiler/multiple/multiple.csproj create mode 100644 src/tests/profiler/native/multiple/multiple.cpp create mode 100644 src/tests/profiler/native/multiple/multiple.h diff --git a/src/coreclr/inc/profilepriv.h b/src/coreclr/inc/profilepriv.h index 75d1c3dbcc29bb..4a77b65e8b24df 100644 --- a/src/coreclr/inc/profilepriv.h +++ b/src/coreclr/inc/profilepriv.h @@ -110,7 +110,7 @@ class ProfilerInfo EventMask eventMask; //--------------------------------------------------------------- - // m_dwProfilerEvacuationCounter keeps track of how many profiler + // dwProfilerEvacuationCounter keeps track of how many profiler // callback calls remain on the stack //--------------------------------------------------------------- // Why volatile? diff --git a/src/coreclr/inc/profilepriv.inl b/src/coreclr/inc/profilepriv.inl index e99591c5ffd18a..cee2dfb36b273d 100644 --- a/src/coreclr/inc/profilepriv.inl +++ b/src/coreclr/inc/profilepriv.inl @@ -168,7 +168,7 @@ inline BOOL ProfControlBlock::IsMainProfiler(ProfToEEInterfaceImpl *pProfToEE) inline ProfilerInfo *ProfControlBlock::GetProfilerInfo(ProfToEEInterfaceImpl *pProfToEE) { ProfilerInfo *pProfilerInfo = NULL; - IterateProfilers(ProfilerCallbackType::Active, + IterateProfilers(ProfilerCallbackType::ActiveOrInitializing, [](ProfilerInfo *pProfilerInfo, ProfToEEInterfaceImpl *pProfToEE, ProfilerInfo **ppFoundProfilerInfo) { if (pProfilerInfo->pProfInterface->m_pProfToEE == pProfToEE) diff --git a/src/coreclr/vm/eetoprofinterfaceimpl.cpp b/src/coreclr/vm/eetoprofinterfaceimpl.cpp index 745f2b6ef1ca10..78a85b964e27a2 100644 --- a/src/coreclr/vm/eetoprofinterfaceimpl.cpp +++ b/src/coreclr/vm/eetoprofinterfaceimpl.cpp @@ -637,9 +637,6 @@ HRESULT EEToProfInterfaceImpl::CreateProfiler( } CONTRACTL_END; - // Always called before Thread created. - _ASSERTE(GetThreadNULLOk() == NULL); - // Try and CoCreate the registered profiler ReleaseHolder pCallback2; HModuleHolder hmodProfilerDLL; @@ -2771,10 +2768,6 @@ HRESULT EEToProfInterfaceImpl::InitializeForAttach(void * pvClientData, UINT cbC _ASSERTE(m_pProfToEE != NULL); - // Attach initialization occurs on the AttachThread, which does not have an EEThread - // object - _ASSERTE(GetThreadNULLOk() == NULL); - // Should only be called on profilers that support ICorProfilerCallback3 _ASSERTE(m_pCallback3 != NULL); @@ -2826,10 +2819,6 @@ HRESULT EEToProfInterfaceImpl::ProfilerAttachComplete() LL_INFO10, "**PROF: Calling profiler's ProfilerAttachComplete() method.\n")); - // Attach initialization occurs on the AttachThread, which does not have an EEThread - // object - _ASSERTE(GetThreadNULLOk() == NULL); - // Should only be called on profilers that support ICorProfilerCallback3 _ASSERTE(m_pCallback3 != NULL); diff --git a/src/coreclr/vm/profdetach.cpp b/src/coreclr/vm/profdetach.cpp index 0161bef95295b1..a820182aacb0ca 100644 --- a/src/coreclr/vm/profdetach.cpp +++ b/src/coreclr/vm/profdetach.cpp @@ -365,8 +365,8 @@ void ProfilingAPIDetach::SleepWhileProfilerEvacuates(ProfilerDetachInfo *pDetach const DWORD kdwDefaultMinSleepMs = 300; // The default "steady state" max sleep is how long we'll wait if, after a couple - // tries the profiler still hasn't evacuated. Default to every 10 minutes - const DWORD kdwDefaultMaxSleepMs = 600000; + // tries the profiler still hasn't evacuated. Default to every 5 seconds + const DWORD kdwDefaultMaxSleepMs = 5000; static DWORD s_dwMinSleepMs = 0; static DWORD s_dwMaxSleepMs = 0; diff --git a/src/coreclr/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/vm/proftoeeinterfaceimpl.cpp index c1e983304986ed..40b3ce5b09476a 100644 --- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp +++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp @@ -9545,14 +9545,16 @@ HRESULT ProfToEEInterfaceImpl::RequestProfilerDetach(DWORD dwExpectedCompletionM } CONTRACTL_END; - PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX( + PROFILER_TO_CLR_ENTRYPOINT_ASYNC_EX( kP2EEAllowableAfterAttach | kP2EETriggers, (LF_CORPROF, LL_INFO1000, "**PROF: RequestProfilerDetach.\n")); #ifdef FEATURE_PROFAPI_ATTACH_DETACH - return ProfilingAPIDetach::RequestProfilerDetach(g_profControlBlock.GetProfilerInfo(this), dwExpectedCompletionMilliseconds); + ProfilerInfo *pProfilerInfo = g_profControlBlock.GetProfilerInfo(this); + _ASSERTE(pProfilerInfo != NULL); + return ProfilingAPIDetach::RequestProfilerDetach(pProfilerInfo, dwExpectedCompletionMilliseconds); #else // FEATURE_PROFAPI_ATTACH_DETACH return E_NOTIMPL; #endif // FEATURE_PROFAPI_ATTACH_DETACH diff --git a/src/tests/profiler/common/ProfilerTestRunner.cs b/src/tests/profiler/common/ProfilerTestRunner.cs index 38c8546b4fc241..d007f755ac725b 100644 --- a/src/tests/profiler/common/ProfilerTestRunner.cs +++ b/src/tests/profiler/common/ProfilerTestRunner.cs @@ -27,7 +27,9 @@ public static int Run(string profileePath, string profileeArguments = "", ProfileeOptions profileeOptions = ProfileeOptions.None, Dictionary envVars = null, - string reverseServerName = null) + string reverseServerName = null, + bool loadAsNotification = false, + int notificationCopies = 1) { string arguments; string program; @@ -44,8 +46,27 @@ public static int Run(string profileePath, if (!profileeOptions.HasFlag(ProfileeOptions.NoStartupAttach)) { envVars.Add("CORECLR_ENABLE_PROFILING", "1"); - envVars.Add("CORECLR_PROFILER_PATH", profilerPath); - envVars.Add("CORECLR_PROFILER", "{" + profilerClsid + "}"); + + if (loadAsNotification) + { + StringBuilder builder = new StringBuilder(); + for(int i = 0; i < notificationCopies; ++i) + { + builder.Append(profilerPath); + builder.Append("="); + builder.Append(profilerClsid.ToString()); + builder.Append(";"); + } + + envVars.Add("CORECLR_ENABLE_NOTIFICATION_PROFILERS", "1"); + envVars.Add("CORECLR_NOTIFICATION_PROFILERS", builder.ToString()); + + } + else + { + envVars.Add("CORECLR_PROFILER", "{" + profilerClsid + "}"); + envVars.Add("CORECLR_PROFILER_PATH", profilerPath); + } } if (profileeOptions.HasFlag(ProfileeOptions.OptimizationSensitive)) @@ -123,7 +144,7 @@ public static int Run(string profileePath, return 100; } - private static string GetProfilerPath() + public static string GetProfilerPath() { string profilerName; if (TestLibrary.Utilities.IsWindows) diff --git a/src/tests/profiler/multiple/multiple.cs b/src/tests/profiler/multiple/multiple.cs new file mode 100644 index 00000000000000..2b40de2db2bc4a --- /dev/null +++ b/src/tests/profiler/multiple/multiple.cs @@ -0,0 +1,47 @@ +// 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.Threading; + +namespace Profiler.Tests +{ + class MultiplyLoaded + { + static readonly Guid MultipleProfilerGuid = new Guid("BFA8EF13-E144-49B9-B95C-FC1C150C7651"); + static readonly string ProfilerPath = ProfilerTestRunner.GetProfilerPath(); + + public static int RunTest(String[] args) + { + for (int i = 0; i < 16; ++i) + { + ProfilerControlHelpers.AttachProfilerToSelf(MultipleProfilerGuid, ProfilerPath); + } + + try + { + throw new Exception("Test exception!"); + } + catch + { + // intentionally swallow the exception + } + + return 100; + } + + public static int Main(string[] args) + { + if (args.Length > 0 && args[0].Equals("RunTest", StringComparison.OrdinalIgnoreCase)) + { + return RunTest(args); + } + + return ProfilerTestRunner.Run(profileePath: System.Reflection.Assembly.GetExecutingAssembly().Location, + testName: "MultiplyLoaded", + profilerClsid: MultipleProfilerGuid, + loadAsNotification: true, + notificationCopies: 16); + } + } +} diff --git a/src/tests/profiler/multiple/multiple.csproj b/src/tests/profiler/multiple/multiple.csproj new file mode 100644 index 00000000000000..c7b6a7b209a090 --- /dev/null +++ b/src/tests/profiler/multiple/multiple.csproj @@ -0,0 +1,15 @@ + + + .NETCoreApp + exe + BuildAndRun + true + 0 + + + + + + + + diff --git a/src/tests/profiler/native/CMakeLists.txt b/src/tests/profiler/native/CMakeLists.txt index e068fdc1ea3cbd..b7357a678b15a9 100644 --- a/src/tests/profiler/native/CMakeLists.txt +++ b/src/tests/profiler/native/CMakeLists.txt @@ -12,6 +12,7 @@ set(SOURCES gcprofiler/gcprofiler.cpp getappdomainstaticaddress/getappdomainstaticaddress.cpp metadatagetdispenser/metadatagetdispenser.cpp + multiple/multiple.cpp nullprofiler/nullprofiler.cpp rejitprofiler/rejitprofiler.cpp rejitprofiler/ilrewriter.cpp diff --git a/src/tests/profiler/native/classfactory.cpp b/src/tests/profiler/native/classfactory.cpp index fe999926de5b70..d09cb4c4e3bb02 100644 --- a/src/tests/profiler/native/classfactory.cpp +++ b/src/tests/profiler/native/classfactory.cpp @@ -14,6 +14,7 @@ #include "rejitprofiler/rejitprofiler.h" #include "releaseondetach/releaseondetach.h" #include "transitions/transitions.h" +#include "multiple/multiple.h" ClassFactory::ClassFactory(REFCLSID clsid) : refCount(0), clsid(clsid) { @@ -60,34 +61,60 @@ HRESULT STDMETHODCALLTYPE ClassFactory::CreateInstance(IUnknown *pUnkOuter, REFI return CLASS_E_NOAGGREGATION; } - //A little simplistic, we create an instance of every profiler, then return the one whose CLSID matches - Profiler* profilers[] = { - new GCAllocateProfiler(), - new GCBasicProfiler(), - new ReJITProfiler(), - new EventPipeReadingProfiler(), - new EventPipeWritingProfiler(), - new MetaDataGetDispenser(), - new GetAppDomainStaticAddress(), - new SlowPathELTProfiler(), - new GCProfiler(), - new ReleaseOnDetach(), - new Transitions(), - new NullProfiler() - // add new profilers here - }; - Profiler* profiler = nullptr; - for (unsigned int i = 0; i < sizeof(profilers)/sizeof(Profiler*); i++) - { - if (clsid == profilers[i]->GetClsid()) - { - profiler = profilers[i]; - break; - } - } - - if (profiler == nullptr) + if (clsid == GCAllocateProfiler::GetClsid()) + { + profiler = new GCAllocateProfiler(); + } + else if (clsid == GCBasicProfiler::GetClsid()) + { + profiler = new GCBasicProfiler(); + } + else if (clsid == ReJITProfiler::GetClsid()) + { + profiler = new ReJITProfiler(); + } + else if (clsid == EventPipeReadingProfiler::GetClsid()) + { + profiler = new EventPipeReadingProfiler(); + } + else if (clsid == EventPipeWritingProfiler::GetClsid()) + { + profiler = new EventPipeWritingProfiler(); + } + else if (clsid == MetaDataGetDispenser::GetClsid()) + { + profiler = new MetaDataGetDispenser(); + } + else if (clsid == GetAppDomainStaticAddress::GetClsid()) + { + profiler = new GetAppDomainStaticAddress(); + } + else if (clsid == SlowPathELTProfiler::GetClsid()) + { + profiler = new SlowPathELTProfiler(); + } + else if (clsid == GCProfiler::GetClsid()) + { + profiler = new GCProfiler(); + } + else if (clsid == ReleaseOnDetach::GetClsid()) + { + profiler = new ReleaseOnDetach(); + } + else if (clsid == Transitions::GetClsid()) + { + profiler = new Transitions(); + } + else if (clsid == NullProfiler::GetClsid()) + { + profiler = new NullProfiler(); + } + else if (clsid == MultiplyLoaded::GetClsid()) + { + profiler = new MultiplyLoaded(); + } + else { printf("No profiler found in ClassFactory::CreateInstance. Did you add your profiler to the list?\n"); return E_FAIL; diff --git a/src/tests/profiler/native/eltprofiler/slowpatheltprofiler.h b/src/tests/profiler/native/eltprofiler/slowpatheltprofiler.h index 254ba12d6e6629..571e677dfb3b9b 100644 --- a/src/tests/profiler/native/eltprofiler/slowpatheltprofiler.h +++ b/src/tests/profiler/native/eltprofiler/slowpatheltprofiler.h @@ -63,7 +63,7 @@ class SlowPathELTProfiler : public Profiler _testType(TestType::Unknown) {} - virtual GUID GetClsid(); + static GUID GetClsid(); virtual HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pICorProfilerInfoUnk); virtual HRESULT STDMETHODCALLTYPE Shutdown(); diff --git a/src/tests/profiler/native/eventpipeprofiler/eventpipereadingprofiler.h b/src/tests/profiler/native/eventpipeprofiler/eventpipereadingprofiler.h index 1d7a41760ef4ac..2b5bc2083ebcfa 100644 --- a/src/tests/profiler/native/eventpipeprofiler/eventpipereadingprofiler.h +++ b/src/tests/profiler/native/eventpipeprofiler/eventpipereadingprofiler.h @@ -22,7 +22,7 @@ class EventPipeReadingProfiler : public Profiler _metadataCache() {} - virtual GUID GetClsid(); + static GUID GetClsid(); virtual HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pICorProfilerInfoUnk); diff --git a/src/tests/profiler/native/eventpipeprofiler/eventpipewritingprofiler.h b/src/tests/profiler/native/eventpipeprofiler/eventpipewritingprofiler.h index fcb9217c19161c..9de3dab1b387ab 100644 --- a/src/tests/profiler/native/eventpipeprofiler/eventpipewritingprofiler.h +++ b/src/tests/profiler/native/eventpipeprofiler/eventpipewritingprofiler.h @@ -17,7 +17,7 @@ class EventPipeWritingProfiler : public Profiler _simpleEvent(0) {} - virtual GUID GetClsid(); + static GUID GetClsid(); virtual HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pICorProfilerInfoUnk); virtual HRESULT STDMETHODCALLTYPE Shutdown(); virtual HRESULT STDMETHODCALLTYPE JITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock); diff --git a/src/tests/profiler/native/gcallocateprofiler/gcallocateprofiler.h b/src/tests/profiler/native/gcallocateprofiler/gcallocateprofiler.h index 65fb3b16240e0a..66095b80357dcd 100644 --- a/src/tests/profiler/native/gcallocateprofiler/gcallocateprofiler.h +++ b/src/tests/profiler/native/gcallocateprofiler/gcallocateprofiler.h @@ -14,7 +14,7 @@ class GCAllocateProfiler : public Profiler _failures(0) {} - virtual GUID GetClsid(); + static GUID GetClsid(); virtual HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pICorProfilerInfoUnk); virtual HRESULT STDMETHODCALLTYPE ObjectAllocated(ObjectID objectId, ClassID classId); virtual HRESULT STDMETHODCALLTYPE Shutdown(); diff --git a/src/tests/profiler/native/gcbasicprofiler/gcbasicprofiler.h b/src/tests/profiler/native/gcbasicprofiler/gcbasicprofiler.h index 613f5f1180ed91..1e1c44c3866ec6 100644 --- a/src/tests/profiler/native/gcbasicprofiler/gcbasicprofiler.h +++ b/src/tests/profiler/native/gcbasicprofiler/gcbasicprofiler.h @@ -14,7 +14,7 @@ class GCBasicProfiler : public Profiler _failures(0) {} - virtual GUID GetClsid(); + static GUID GetClsid(); virtual HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pICorProfilerInfoUnk); virtual HRESULT STDMETHODCALLTYPE Shutdown(); virtual HRESULT STDMETHODCALLTYPE GarbageCollectionStarted(int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason); diff --git a/src/tests/profiler/native/gcprofiler/gcprofiler.h b/src/tests/profiler/native/gcprofiler/gcprofiler.h index 8e0fbebbc4c27d..ab519f6f53399a 100644 --- a/src/tests/profiler/native/gcprofiler/gcprofiler.h +++ b/src/tests/profiler/native/gcprofiler/gcprofiler.h @@ -23,7 +23,7 @@ class GCProfiler : public Profiler _objectReferencesSeen() {} - virtual GUID GetClsid(); + static GUID GetClsid(); virtual HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pICorProfilerInfoUnk); virtual HRESULT STDMETHODCALLTYPE Shutdown(); virtual HRESULT STDMETHODCALLTYPE GarbageCollectionStarted(int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason); diff --git a/src/tests/profiler/native/getappdomainstaticaddress/getappdomainstaticaddress.h b/src/tests/profiler/native/getappdomainstaticaddress/getappdomainstaticaddress.h index 1b902a7ff34905..740ebbdbf09441 100644 --- a/src/tests/profiler/native/getappdomainstaticaddress/getappdomainstaticaddress.h +++ b/src/tests/profiler/native/getappdomainstaticaddress/getappdomainstaticaddress.h @@ -26,7 +26,7 @@ class GetAppDomainStaticAddress : public Profiler GetAppDomainStaticAddress(); virtual ~GetAppDomainStaticAddress(); - virtual GUID GetClsid() override; + static GUID GetClsid(); virtual HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pICorProfilerInfoUnk) override; virtual HRESULT STDMETHODCALLTYPE Shutdown() override; diff --git a/src/tests/profiler/native/metadatagetdispenser/metadatagetdispenser.h b/src/tests/profiler/native/metadatagetdispenser/metadatagetdispenser.h index 407fa731384ae4..28f08bbd58884a 100644 --- a/src/tests/profiler/native/metadatagetdispenser/metadatagetdispenser.h +++ b/src/tests/profiler/native/metadatagetdispenser/metadatagetdispenser.h @@ -18,7 +18,7 @@ class MetaDataGetDispenser : public Profiler MetaDataGetDispenser(); virtual ~MetaDataGetDispenser(); - virtual GUID GetClsid(); + static GUID GetClsid(); virtual HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pICorProfilerInfoUnk); virtual HRESULT STDMETHODCALLTYPE Shutdown(); diff --git a/src/tests/profiler/native/multiple/multiple.cpp b/src/tests/profiler/native/multiple/multiple.cpp new file mode 100644 index 00000000000000..ffbfe0a735fb42 --- /dev/null +++ b/src/tests/profiler/native/multiple/multiple.cpp @@ -0,0 +1,87 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "multiple.h" +#include +#include + +#define MAX_PROFILERS 32 + +using std::thread; + +GUID MultiplyLoaded::GetClsid() +{ + // {BFA8EF13-E144-49B9-B95C-FC1C150C7651} + GUID clsid = { 0xBFA8EF13, 0xE144, 0x49B9, { 0xB9, 0x5C, 0xFC, 0x1C, 0x15, 0x0C, 0x76, 0x51 } }; + return clsid; +} + +HRESULT MultiplyLoaded::InitializeCommon(IUnknown* pICorProfilerInfoUnk) +{ + Profiler::Initialize(pICorProfilerInfoUnk); + + HRESULT hr = S_OK; + if (FAILED(hr = pCorProfilerInfo->SetEventMask2(COR_PRF_MONITOR_EXCEPTIONS, 0))) + { + _failures++; + printf("FAIL: ICorProfilerInfo::SetEventMask2() failed hr=0x%x", hr); + return hr; + } + + return S_OK; +} + +HRESULT MultiplyLoaded::Initialize(IUnknown* pICorProfilerInfoUnk) +{ + return InitializeCommon(pICorProfilerInfoUnk); +} + +HRESULT MultiplyLoaded::InitializeForAttach(IUnknown* pICorProfilerInfoUnk, void* pvClientData, UINT cbClientData) +{ + return InitializeCommon(pICorProfilerInfoUnk); +} + +HRESULT MultiplyLoaded::LoadAsNotficationOnly(BOOL *pbNotificationOnly) +{ + *pbNotificationOnly = TRUE; + return S_OK; +} + +HRESULT MultiplyLoaded::ProfilerDetachSucceeded() +{ + ++_detachCount; + + if (_detachCount == MAX_PROFILERS + && _exceptionThrownSeenCount >= MAX_PROFILERS + && _failures == 0) + { + printf("PROFILER TEST PASSES\n"); + } + + return S_OK; +} + +HRESULT MultiplyLoaded::ExceptionThrown(ObjectID thrownObjectId) +{ + _exceptionThrownSeenCount++; + + thread detachThread([&]() + { + printf("Requesting detach!!\n"); + HRESULT hr = pCorProfilerInfo->RequestProfilerDetach(0); + printf("RequestProfilerDetach hr=0x%x\n", hr); + }); + + detachThread.detach(); + + return S_OK; +} + +HRESULT MultiplyLoaded::Shutdown() +{ + Profiler::Shutdown(); + + fflush(stdout); + + return S_OK; +} diff --git a/src/tests/profiler/native/multiple/multiple.h b/src/tests/profiler/native/multiple/multiple.h new file mode 100644 index 00000000000000..3a75da70620226 --- /dev/null +++ b/src/tests/profiler/native/multiple/multiple.h @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#pragma once + +#include "../profiler.h" + +class MultiplyLoaded : public Profiler +{ +public: + MultiplyLoaded() : Profiler(), + _exceptionThrownSeenCount(0), + _detachCount(0), + _failures(0) + {} + + static GUID GetClsid(); + virtual HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pICorProfilerInfoUnk); + virtual HRESULT STDMETHODCALLTYPE InitializeForAttach(IUnknown* pICorProfilerInfoUnk, void* pvClientData, UINT cbClientData); + virtual HRESULT STDMETHODCALLTYPE Shutdown(); + virtual HRESULT STDMETHODCALLTYPE LoadAsNotficationOnly(BOOL *pbNotificationOnly); + + virtual HRESULT STDMETHODCALLTYPE ProfilerDetachSucceeded(); + virtual HRESULT STDMETHODCALLTYPE ExceptionThrown(ObjectID thrownObjectId); + +private: + std::atomic _exceptionThrownSeenCount; + std::atomic _detachCount; + std::atomic _failures; + + HRESULT InitializeCommon(IUnknown* pCorProfilerInfoUnk); +}; diff --git a/src/tests/profiler/native/nullprofiler/nullprofiler.h b/src/tests/profiler/native/nullprofiler/nullprofiler.h index 1d25829221d911..93831ae3046e83 100644 --- a/src/tests/profiler/native/nullprofiler/nullprofiler.h +++ b/src/tests/profiler/native/nullprofiler/nullprofiler.h @@ -18,7 +18,7 @@ class NullProfiler : public Profiler } - virtual GUID GetClsid(); + static GUID GetClsid(); virtual HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pICorProfilerInfoUnk); virtual HRESULT STDMETHODCALLTYPE Shutdown(); }; diff --git a/src/tests/profiler/native/profiler.cpp b/src/tests/profiler/native/profiler.cpp index 8812cbad6cd65b..6c02102014b92e 100644 --- a/src/tests/profiler/native/profiler.cpp +++ b/src/tests/profiler/native/profiler.cpp @@ -532,6 +532,12 @@ HRESULT STDMETHODCALLTYPE Profiler::EventPipeProviderCreated(EVENTPIPE_PROVIDER return S_OK; } +HRESULT STDMETHODCALLTYPE Profiler::LoadAsNotficationOnly(BOOL *pbNotificationOnly) +{ + *pbNotificationOnly = FALSE; + return S_OK; +} + HRESULT STDMETHODCALLTYPE Profiler::QueryInterface(REFIID riid, void **ppvObject) { if (riid == __uuidof(ICorProfilerCallback10) || diff --git a/src/tests/profiler/native/profiler.h b/src/tests/profiler/native/profiler.h index 1086d9a8efdba4..1faaf1d749e0d2 100644 --- a/src/tests/profiler/native/profiler.h +++ b/src/tests/profiler/native/profiler.h @@ -84,7 +84,7 @@ class ShutdownGuard return; \ } -class Profiler : public ICorProfilerCallback10 +class Profiler : public ICorProfilerCallback11 { private: std::atomic refCount; @@ -105,7 +105,6 @@ class Profiler : public ICorProfilerCallback10 Profiler(); virtual ~Profiler(); - virtual GUID GetClsid() = 0; HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pICorProfilerInfoUnk) override; HRESULT STDMETHODCALLTYPE Shutdown() override; HRESULT STDMETHODCALLTYPE AppDomainCreationStarted(AppDomainID appDomainId) override; @@ -212,6 +211,7 @@ class Profiler : public ICorProfilerCallback10 ULONG numStackFrames, UINT_PTR stackFrames[]) override; HRESULT STDMETHODCALLTYPE EventPipeProviderCreated(EVENTPIPE_PROVIDER provider) override; + HRESULT STDMETHODCALLTYPE LoadAsNotficationOnly(BOOL *pbNotificationOnly) override; HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) override; ULONG STDMETHODCALLTYPE AddRef(void) override; diff --git a/src/tests/profiler/native/rejitprofiler/rejitprofiler.h b/src/tests/profiler/native/rejitprofiler/rejitprofiler.h index f105945c557fb6..c6d075163dc0f0 100644 --- a/src/tests/profiler/native/rejitprofiler/rejitprofiler.h +++ b/src/tests/profiler/native/rejitprofiler/rejitprofiler.h @@ -29,7 +29,7 @@ class ReJITProfiler : public Profiler ReJITProfiler(); virtual ~ReJITProfiler() = default; - virtual GUID GetClsid(); + static GUID GetClsid(); virtual HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pICorProfilerInfoUnk); virtual HRESULT STDMETHODCALLTYPE Shutdown(); diff --git a/src/tests/profiler/native/releaseondetach/releaseondetach.h b/src/tests/profiler/native/releaseondetach/releaseondetach.h index 0f75a99fb95ea2..458dede165c732 100644 --- a/src/tests/profiler/native/releaseondetach/releaseondetach.h +++ b/src/tests/profiler/native/releaseondetach/releaseondetach.h @@ -21,7 +21,7 @@ class ReleaseOnDetach : public Profiler ReleaseOnDetach(); virtual ~ReleaseOnDetach(); - virtual GUID GetClsid(); + static GUID GetClsid(); virtual HRESULT STDMETHODCALLTYPE InitializeForAttach(IUnknown* pCorProfilerInfoUnk, void* pvClientData, UINT cbClientData); virtual HRESULT STDMETHODCALLTYPE Shutdown(); diff --git a/src/tests/profiler/native/transitions/transitions.h b/src/tests/profiler/native/transitions/transitions.h index 0ddf19ac51d88e..6c9e9d57730206 100644 --- a/src/tests/profiler/native/transitions/transitions.h +++ b/src/tests/profiler/native/transitions/transitions.h @@ -11,7 +11,7 @@ class Transitions : public Profiler Transitions(); virtual ~Transitions() = default; - virtual GUID GetClsid(); + static GUID GetClsid(); virtual HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pICorProfilerInfoUnk); virtual HRESULT STDMETHODCALLTYPE Shutdown(); virtual HRESULT STDMETHODCALLTYPE UnmanagedToManagedTransition(FunctionID functionID, COR_PRF_TRANSITION_REASON reason); From d3bf163c4dcdf6feff8c22d56ede1f4a8ed1f00b Mon Sep 17 00:00:00 2001 From: David Mason Date: Sat, 14 Aug 2021 22:16:13 -0700 Subject: [PATCH 2/9] update tests --- .../profiler/common/ProfilerTestRunner.cs | 4 ++++ src/tests/profiler/multiple/multiple.cs | 12 ++++++++++++ .../profiler/native/multiple/multiple.cpp | 2 ++ src/tests/profiler/native/profiler.cpp | 18 +++++++++++------- src/tests/profiler/native/profiler.h | 10 +++++----- .../native/releaseondetach/releaseondetach.cpp | 2 +- src/tests/profiler/unittest/releaseondetach.cs | 6 +----- 7 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/tests/profiler/common/ProfilerTestRunner.cs b/src/tests/profiler/common/ProfilerTestRunner.cs index d007f755ac725b..1c4520d4b9829c 100644 --- a/src/tests/profiler/common/ProfilerTestRunner.cs +++ b/src/tests/profiler/common/ProfilerTestRunner.cs @@ -10,6 +10,8 @@ namespace Profiler.Tests { + public delegate void ProfilerCallback(); + [Flags] public enum ProfileeOptions { @@ -54,7 +56,9 @@ public static int Run(string profileePath, { builder.Append(profilerPath); builder.Append("="); + builder.Append("{"); builder.Append(profilerClsid.ToString()); + builder.Append("}"); builder.Append(";"); } diff --git a/src/tests/profiler/multiple/multiple.cs b/src/tests/profiler/multiple/multiple.cs index 2b40de2db2bc4a..75a319da7bbee2 100644 --- a/src/tests/profiler/multiple/multiple.cs +++ b/src/tests/profiler/multiple/multiple.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Threading; namespace Profiler.Tests @@ -11,6 +13,9 @@ class MultiplyLoaded static readonly Guid MultipleProfilerGuid = new Guid("BFA8EF13-E144-49B9-B95C-FC1C150C7651"); static readonly string ProfilerPath = ProfilerTestRunner.GetProfilerPath(); + [DllImport("Profiler")] + private static extern void PassCallbackToProfiler(ProfilerCallback callback); + public static int RunTest(String[] args) { for (int i = 0; i < 16; ++i) @@ -27,6 +32,13 @@ public static int RunTest(String[] args) // intentionally swallow the exception } + ManualResetEvent _profilerDone = new ManualResetEvent(false); + PassCallbackToProfiler(() => _profilerDone.Set()); + if (!_profilerDone.WaitOne(TimeSpan.FromMinutes(5))) + { + Console.WriteLine("Profiler did not set the callback, test will fail."); + } + return 100; } diff --git a/src/tests/profiler/native/multiple/multiple.cpp b/src/tests/profiler/native/multiple/multiple.cpp index ffbfe0a735fb42..d7e6d9886eb27e 100644 --- a/src/tests/profiler/native/multiple/multiple.cpp +++ b/src/tests/profiler/native/multiple/multiple.cpp @@ -51,11 +51,13 @@ HRESULT MultiplyLoaded::ProfilerDetachSucceeded() { ++_detachCount; + printf("ProfilerDetachSucceeded _detachCount=%d\n", _detachCount.load()); if (_detachCount == MAX_PROFILERS && _exceptionThrownSeenCount >= MAX_PROFILERS && _failures == 0) { printf("PROFILER TEST PASSES\n"); + NotifyManagedCodeViaCallback(pCorProfilerInfo); } return S_OK; diff --git a/src/tests/profiler/native/profiler.cpp b/src/tests/profiler/native/profiler.cpp index 6c02102014b92e..60eca1852143b6 100644 --- a/src/tests/profiler/native/profiler.cpp +++ b/src/tests/profiler/native/profiler.cpp @@ -12,6 +12,9 @@ Profiler *Profiler::Instance = nullptr; std::atomic ShutdownGuard::s_preventHooks(false); std::atomic ShutdownGuard::s_hooksInProgress(0); +ProfilerCallback Profiler::s_callback; +ManualEvent Profiler::s_callbackSet; + Profiler::Profiler() : refCount(0), pCorProfilerInfo(nullptr) { Profiler::Instance = this; @@ -540,7 +543,8 @@ HRESULT STDMETHODCALLTYPE Profiler::LoadAsNotficationOnly(BOOL *pbNotificationOn HRESULT STDMETHODCALLTYPE Profiler::QueryInterface(REFIID riid, void **ppvObject) { - if (riid == __uuidof(ICorProfilerCallback10) || + if (riid == __uuidof(ICorProfilerCallback11) || + riid == __uuidof(ICorProfilerCallback10) || riid == __uuidof(ICorProfilerCallback9) || riid == __uuidof(ICorProfilerCallback8) || riid == __uuidof(ICorProfilerCallback7) || @@ -777,13 +781,13 @@ String Profiler::GetModuleIDName(ModuleID modId) void Profiler::SetCallback(ProfilerCallback cb) { assert(cb != NULL); - callback = cb; - callbackSet.Signal(); + s_callback = cb; + s_callbackSet.Signal(); } -void Profiler::NotifyManagedCodeViaCallback() +void Profiler::NotifyManagedCodeViaCallback(ICorProfilerInfo11 *pCorProfilerInfo) { - callbackSet.Wait(); + s_callbackSet.Wait(); thread callbackThread([&]() { @@ -791,7 +795,7 @@ void Profiler::NotifyManagedCodeViaCallback() // some crst order asserts if we call back in to managed code. Spin up // a new thread to avoid that. pCorProfilerInfo->InitializeCurrentThread(); - callback(); + s_callback(); }); callbackThread.join(); @@ -799,7 +803,7 @@ void Profiler::NotifyManagedCodeViaCallback() extern "C" EXPORT void STDMETHODCALLTYPE PassCallbackToProfiler(ProfilerCallback callback) { - Profiler::Instance->SetCallback(callback); + Profiler::SetCallback(callback); } #ifndef WIN32 diff --git a/src/tests/profiler/native/profiler.h b/src/tests/profiler/native/profiler.h index 1faaf1d749e0d2..4bcfa1b3e0fb68 100644 --- a/src/tests/profiler/native/profiler.h +++ b/src/tests/profiler/native/profiler.h @@ -88,18 +88,20 @@ class Profiler : public ICorProfilerCallback11 { private: std::atomic refCount; - ProfilerCallback callback; - ManualEvent callbackSet; + static ProfilerCallback s_callback; + static ManualEvent s_callbackSet; protected: + static void NotifyManagedCodeViaCallback(ICorProfilerInfo11 *pCorProfilerInfo); + String GetClassIDName(ClassID classId); String GetFunctionIDName(FunctionID funcId); String GetModuleIDName(ModuleID modId); - void NotifyManagedCodeViaCallback(); public: static Profiler *Instance; + static void SetCallback(ProfilerCallback callback); ICorProfilerInfo11* pCorProfilerInfo; @@ -216,6 +218,4 @@ class Profiler : public ICorProfilerCallback11 HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) override; ULONG STDMETHODCALLTYPE AddRef(void) override; ULONG STDMETHODCALLTYPE Release(void) override; - - void SetCallback(ProfilerCallback callback); }; diff --git a/src/tests/profiler/native/releaseondetach/releaseondetach.cpp b/src/tests/profiler/native/releaseondetach/releaseondetach.cpp index 3af0fda98b70de..5efb3739a08e12 100644 --- a/src/tests/profiler/native/releaseondetach/releaseondetach.cpp +++ b/src/tests/profiler/native/releaseondetach/releaseondetach.cpp @@ -31,7 +31,7 @@ ReleaseOnDetach::~ReleaseOnDetach() fflush(stdout); - NotifyManagedCodeViaCallback(); + NotifyManagedCodeViaCallback(pCorProfilerInfo); } GUID ReleaseOnDetach::GetClsid() diff --git a/src/tests/profiler/unittest/releaseondetach.cs b/src/tests/profiler/unittest/releaseondetach.cs index 8b01318775d2fc..e50190b1872dfe 100644 --- a/src/tests/profiler/unittest/releaseondetach.cs +++ b/src/tests/profiler/unittest/releaseondetach.cs @@ -9,14 +9,10 @@ namespace Profiler.Tests { - public delegate void ProfilerCallback(); - class ReleaseOnShutdown { private static readonly Guid ReleaseOnShutdownGuid = new Guid("B8C47A29-9C1D-4EEA-ABA0-8E8B3E3B792E"); - private static ManualResetEvent _profilerDone; - [DllImport("Profiler")] private static extern void PassCallbackToProfiler(ProfilerCallback callback); @@ -39,7 +35,7 @@ public unsafe static int RunTest(string[] args) string rootPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); string profilerPath = Path.Combine(rootPath, profilerName); - _profilerDone = new ManualResetEvent(false); + ManualResetEvent _profilerDone = new ManualResetEvent(false); Console.WriteLine($"Attaching profiler {profilerPath} to self."); ProfilerControlHelpers.AttachProfilerToSelf(ReleaseOnShutdownGuid, profilerPath); From 67bac3b7a61cd0cf2f4c1595b51796c828c72d44 Mon Sep 17 00:00:00 2001 From: David Mason Date: Sat, 14 Aug 2021 23:07:04 -0700 Subject: [PATCH 3/9] Updates --- src/coreclr/dlls/mscorrc/mscorrc.rc | 4 ++-- src/tests/profiler/multiple/multiple.cs | 8 ++++++-- src/tests/profiler/native/multiple/multiple.cpp | 9 ++++++++- src/tests/profiler/native/multiple/multiple.h | 11 ++++------- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/coreclr/dlls/mscorrc/mscorrc.rc b/src/coreclr/dlls/mscorrc/mscorrc.rc index e8955bf5e1626e..963315263cf422 100644 --- a/src/coreclr/dlls/mscorrc/mscorrc.rc +++ b/src/coreclr/dlls/mscorrc/mscorrc.rc @@ -738,8 +738,8 @@ BEGIN IDS_E_PROF_NOT_ATTACHABLE "Loading profiler failed. The profiler COM object was instantiated, but the profiler does not support attaching to a live process. The profiler must be loaded at application startup by using a launcher program included with the profiler (if any) or by setting the COR_ENABLE_PROFILING and COR_PROFILER environment variables before launching the application to be profiled. Profiler CLSID: '%s'" IDS_E_PROF_UNHANDLED_EXCEPTION_ON_LOAD "Loading profiler failed. There was an unhandled exception while trying to instantiate the profiler COM object. Please ensure the CLSID is associated with a valid profiler designed to work with this version of the runtime. Profiler CLSID: '%s'." IDS_PROF_ATTACH_REQUEST_RECEIVED "The CLR received a request to attach a profiler. Profiler CLSID: '%s'." - IDS_PROF_DETACH_INITIATED "The profiler currently in use has requested to be detached from the process. The CLR has disabled communication with the profiler and will unload the profiler when it is safe to do so." - IDS_PROF_DETACH_COMPLETE "The CLR has fully detached and unloaded the profiler." + IDS_PROF_DETACH_INITIATED "The profiler currently in use has requested to be detached from the process. The CLR has disabled communication with the profiler and will unload the profiler when it is safe to do so.\n" + IDS_PROF_DETACH_COMPLETE "The CLR has fully detached and unloaded the profiler.\n" IDS_PROF_DETACH_THREAD_ERROR "There was an internal failure in the profiling API detach infrastructure. The profiler will not be able to be detached. Error code: %d." IDS_PROF_CANCEL_ACTIVATION "The profiler has requested that the CLR instance not load the profiler into this process. Profiler CLSID: '%s'." IDS_PROF_V2PROFILER_DISABLED "Loading profiler failed. The profiler that was configured to load was designed for an older version of the CLR. You can use the COMPlus_ProfAPI_ProfilerCompatibilitySetting environment variable to allow older profilers to be loaded by the current version of the CLR. Please consult the documentation for information on how to use this environment variable, and the risks associated with it. Profiler CLSID: '%s'." diff --git a/src/tests/profiler/multiple/multiple.cs b/src/tests/profiler/multiple/multiple.cs index 75a319da7bbee2..4a248140c7362b 100644 --- a/src/tests/profiler/multiple/multiple.cs +++ b/src/tests/profiler/multiple/multiple.cs @@ -18,6 +18,9 @@ class MultiplyLoaded public static int RunTest(String[] args) { + ManualResetEvent _profilerDone = new ManualResetEvent(false); + PassCallbackToProfiler(() => _profilerDone.Set()); + for (int i = 0; i < 16; ++i) { ProfilerControlHelpers.AttachProfilerToSelf(MultipleProfilerGuid, ProfilerPath); @@ -25,15 +28,16 @@ public static int RunTest(String[] args) try { + Console.WriteLine("Throwing exception"); throw new Exception("Test exception!"); } catch { // intentionally swallow the exception + Console.WriteLine("Exception caught"); } - ManualResetEvent _profilerDone = new ManualResetEvent(false); - PassCallbackToProfiler(() => _profilerDone.Set()); + Console.WriteLine("Waiting for profilers to all detach"); if (!_profilerDone.WaitOne(TimeSpan.FromMinutes(5))) { Console.WriteLine("Profiler did not set the callback, test will fail."); diff --git a/src/tests/profiler/native/multiple/multiple.cpp b/src/tests/profiler/native/multiple/multiple.cpp index d7e6d9886eb27e..769aaef05504eb 100644 --- a/src/tests/profiler/native/multiple/multiple.cpp +++ b/src/tests/profiler/native/multiple/multiple.cpp @@ -9,6 +9,10 @@ using std::thread; +std::atomic MultiplyLoaded::_exceptionThrownSeenCount(0); +std::atomic MultiplyLoaded::_detachCount(0); +std::atomic MultiplyLoaded::_failures(0); + GUID MultiplyLoaded::GetClsid() { // {BFA8EF13-E144-49B9-B95C-FC1C150C7651} @@ -21,6 +25,7 @@ HRESULT MultiplyLoaded::InitializeCommon(IUnknown* pICorProfilerInfoUnk) Profiler::Initialize(pICorProfilerInfoUnk); HRESULT hr = S_OK; + printf("Setting exception mask\n"); if (FAILED(hr = pCorProfilerInfo->SetEventMask2(COR_PRF_MONITOR_EXCEPTIONS, 0))) { _failures++; @@ -65,7 +70,9 @@ HRESULT MultiplyLoaded::ProfilerDetachSucceeded() HRESULT MultiplyLoaded::ExceptionThrown(ObjectID thrownObjectId) { - _exceptionThrownSeenCount++; + int seen = _exceptionThrownSeenCount++; + + printf("MultiplyLoaded::ExceptionThrown, number seen = %d\n", seen); thread detachThread([&]() { diff --git a/src/tests/profiler/native/multiple/multiple.h b/src/tests/profiler/native/multiple/multiple.h index 3a75da70620226..56dc7948ffb384 100644 --- a/src/tests/profiler/native/multiple/multiple.h +++ b/src/tests/profiler/native/multiple/multiple.h @@ -8,10 +8,7 @@ class MultiplyLoaded : public Profiler { public: - MultiplyLoaded() : Profiler(), - _exceptionThrownSeenCount(0), - _detachCount(0), - _failures(0) + MultiplyLoaded() : Profiler() {} static GUID GetClsid(); @@ -24,9 +21,9 @@ class MultiplyLoaded : public Profiler virtual HRESULT STDMETHODCALLTYPE ExceptionThrown(ObjectID thrownObjectId); private: - std::atomic _exceptionThrownSeenCount; - std::atomic _detachCount; - std::atomic _failures; + static std::atomic _exceptionThrownSeenCount; + static std::atomic _detachCount; + static std::atomic _failures; HRESULT InitializeCommon(IUnknown* pCorProfilerInfoUnk); }; From 2b78825c0abf4a11218abedb1b795bfd387635a6 Mon Sep 17 00:00:00 2001 From: David Mason Date: Sat, 14 Aug 2021 23:09:53 -0700 Subject: [PATCH 4/9] Add guid for cross plat --- src/tests/profiler/native/guids.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tests/profiler/native/guids.cpp b/src/tests/profiler/native/guids.cpp index d8d5cf9015153c..492840472d9b0a 100644 --- a/src/tests/profiler/native/guids.cpp +++ b/src/tests/profiler/native/guids.cpp @@ -30,6 +30,7 @@ DEFINE_GUID(IID_ICorProfilerCallback7, 0xF76A2DBA,0x1D52,0x4539, DEFINE_GUID(IID_ICorProfilerCallback8, 0x5BED9B15,0xC079,0x4D47,0xBF,0xE2,0x21,0x5A,0x14,0x0C,0x07,0xE0); DEFINE_GUID(IID_ICorProfilerCallback9, 0x27583EC3,0xC8F5,0x482F,0x80,0x52,0x19,0x4B,0x8C,0xE4,0x70,0x5A); DEFINE_GUID(IID_ICorProfilerCallback10, 0xCEC5B60E,0xC69C,0x495F,0x87,0xF6,0x84,0xD2,0x8E,0xE1,0x6F,0xFB); +DEFINE_GUID(IID_ICorProfilerCallback11, 0x42350846,0xAAED,0x47F7,0xB1,0x28,0xFD,0x0C,0x98,0x88,0x1C,0xDE); DEFINE_GUID(IID_ICorProfilerInfo, 0x28B5557D,0x3F3F,0x48B4,0x90,0xB2,0x5F,0x9E,0xEA,0x2F,0x6C,0x48); DEFINE_GUID(IID_ICorProfilerInfo2, 0xCC0935CD,0xA518,0x487D,0xB0,0xBB,0xA9,0x32,0x14,0xE6,0x54,0x78); DEFINE_GUID(IID_ICorProfilerInfo3, 0xB555ED4F,0x452A,0x4E54,0x8B,0x39,0xB5,0x36,0x0B,0xAD,0x32,0xA0); From 86a1601a01820dfe3c5ce7282c1feb3df2dac6c2 Mon Sep 17 00:00:00 2001 From: David Mason Date: Sat, 14 Aug 2021 23:11:43 -0700 Subject: [PATCH 5/9] Update multiple.cpp --- src/tests/profiler/native/multiple/multiple.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/profiler/native/multiple/multiple.cpp b/src/tests/profiler/native/multiple/multiple.cpp index 769aaef05504eb..af9951078aec56 100644 --- a/src/tests/profiler/native/multiple/multiple.cpp +++ b/src/tests/profiler/native/multiple/multiple.cpp @@ -57,8 +57,8 @@ HRESULT MultiplyLoaded::ProfilerDetachSucceeded() ++_detachCount; printf("ProfilerDetachSucceeded _detachCount=%d\n", _detachCount.load()); - if (_detachCount == MAX_PROFILERS - && _exceptionThrownSeenCount >= MAX_PROFILERS + if (_detachCount == (MAX_PROFILERS - 1) + && _exceptionThrownSeenCount >= (MAX_PROFILERS - 1) && _failures == 0) { printf("PROFILER TEST PASSES\n"); From 0276594c01780226a385b989fa5a999f1396315c Mon Sep 17 00:00:00 2001 From: David Mason Date: Sat, 14 Aug 2021 23:33:15 -0700 Subject: [PATCH 6/9] Reduce number of profilers because 32 made the test take forever --- src/tests/profiler/multiple/multiple.cs | 4 ++-- src/tests/profiler/native/multiple/multiple.cpp | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/tests/profiler/multiple/multiple.cs b/src/tests/profiler/multiple/multiple.cs index 4a248140c7362b..f3bfa3468dbdf8 100644 --- a/src/tests/profiler/multiple/multiple.cs +++ b/src/tests/profiler/multiple/multiple.cs @@ -21,7 +21,7 @@ public static int RunTest(String[] args) ManualResetEvent _profilerDone = new ManualResetEvent(false); PassCallbackToProfiler(() => _profilerDone.Set()); - for (int i = 0; i < 16; ++i) + for (int i = 0; i < 4; ++i) { ProfilerControlHelpers.AttachProfilerToSelf(MultipleProfilerGuid, ProfilerPath); } @@ -57,7 +57,7 @@ public static int Main(string[] args) testName: "MultiplyLoaded", profilerClsid: MultipleProfilerGuid, loadAsNotification: true, - notificationCopies: 16); + notificationCopies: 4); } } } diff --git a/src/tests/profiler/native/multiple/multiple.cpp b/src/tests/profiler/native/multiple/multiple.cpp index af9951078aec56..46b5fc6dac95dd 100644 --- a/src/tests/profiler/native/multiple/multiple.cpp +++ b/src/tests/profiler/native/multiple/multiple.cpp @@ -3,9 +3,8 @@ #include "multiple.h" #include -#include -#define MAX_PROFILERS 32 +#define MAX_PROFILERS 8 using std::thread; From f2a5e3740e17618c5328b7b2617eea812aeaa387 Mon Sep 17 00:00:00 2001 From: David Mason Date: Sun, 15 Aug 2021 01:25:40 -0700 Subject: [PATCH 7/9] Lower again --- src/tests/profiler/multiple/multiple.cs | 7 ++----- src/tests/profiler/native/multiple/multiple.cpp | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/tests/profiler/multiple/multiple.cs b/src/tests/profiler/multiple/multiple.cs index f3bfa3468dbdf8..9de72d96198054 100644 --- a/src/tests/profiler/multiple/multiple.cs +++ b/src/tests/profiler/multiple/multiple.cs @@ -21,10 +21,7 @@ public static int RunTest(String[] args) ManualResetEvent _profilerDone = new ManualResetEvent(false); PassCallbackToProfiler(() => _profilerDone.Set()); - for (int i = 0; i < 4; ++i) - { - ProfilerControlHelpers.AttachProfilerToSelf(MultipleProfilerGuid, ProfilerPath); - } + ProfilerControlHelpers.AttachProfilerToSelf(MultipleProfilerGuid, ProfilerPath); try { @@ -57,7 +54,7 @@ public static int Main(string[] args) testName: "MultiplyLoaded", profilerClsid: MultipleProfilerGuid, loadAsNotification: true, - notificationCopies: 4); + notificationCopies: 2); } } } diff --git a/src/tests/profiler/native/multiple/multiple.cpp b/src/tests/profiler/native/multiple/multiple.cpp index 46b5fc6dac95dd..420fe1038dee65 100644 --- a/src/tests/profiler/native/multiple/multiple.cpp +++ b/src/tests/profiler/native/multiple/multiple.cpp @@ -4,7 +4,7 @@ #include "multiple.h" #include -#define MAX_PROFILERS 8 +#define MAX_PROFILERS 3 using std::thread; From 917b969f8ec19eed85042905244562db6eeedae0 Mon Sep 17 00:00:00 2001 From: David Mason Date: Tue, 17 Aug 2021 00:01:37 -0700 Subject: [PATCH 8/9] add newlines --- src/coreclr/dlls/mscorrc/mscorrc.rc | 42 ++++++++++++++--------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/coreclr/dlls/mscorrc/mscorrc.rc b/src/coreclr/dlls/mscorrc/mscorrc.rc index 963315263cf422..161f6e1e6c8c4c 100644 --- a/src/coreclr/dlls/mscorrc/mscorrc.rc +++ b/src/coreclr/dlls/mscorrc/mscorrc.rc @@ -726,29 +726,29 @@ END // Profiler messages for event log STRINGTABLE DISCARDABLE BEGIN - IDS_E_PROF_BAD_PATH "Loading profiler failed. COR_ENABLE_PROFILING and COR_PROFILER were set properly, but COR_PROFILER_PATH was not. COR_PROFILER_PATH must be set to the full path of the profiler DLL to load with no more than 260 charaters including the null terminator." - IDS_E_PROF_NO_CLSID "Loading profiler failed. COR_ENABLE_PROFILING was set properly, but COR_PROFILER was not. COR_PROFILER must be set to the CLSID of the profiler to load." - IDS_E_PROF_INTERNAL_INIT "Loading profiler failed due to an internal profiling services initialization failure. Profiler CLSID: '%s'. HRESULT: 0x%x." - IDS_E_PROF_BAD_CLSID "Loading profiler failed. COR_PROFILER is set to an invalid CLSID: '%s'. HRESULT: 0x%x." - IDS_E_PROF_NO_CALLBACK_IFACE "Loading profiler failed. COR_PROFILER is set to a CLSID of a COM object that does not implement the interface GUID (IID) requested by the CLR. This often indicates that the profiler does not support this version of the CLR. Profiler CLSID: '%s'. Requested IID: '%s'." - IDS_E_PROF_CCI_FAILED "Loading profiler failed during CoCreateInstance. Profiler CLSID: '%s'. HRESULT: 0x%x." - IDS_E_PROF_INIT_CALLBACK_FAILED "Loading profiler failed. The profiler COM object was instantiated, but the profiler failed during its initialization callback. Profiler CLSID: '%s'. HRESULT: 0x%x." - IDS_PROF_SUPPLEMENTARY_INFO "Process ID (decimal): %d. Message ID: [0x%x]." - IDS_PROF_LOAD_COMPLETE "The profiler was loaded successfully. Profiler CLSID: '%s'." - IDS_E_PROF_NOT_ATTACHABLE "Loading profiler failed. The profiler COM object was instantiated, but the profiler does not support attaching to a live process. The profiler must be loaded at application startup by using a launcher program included with the profiler (if any) or by setting the COR_ENABLE_PROFILING and COR_PROFILER environment variables before launching the application to be profiled. Profiler CLSID: '%s'" - IDS_E_PROF_UNHANDLED_EXCEPTION_ON_LOAD "Loading profiler failed. There was an unhandled exception while trying to instantiate the profiler COM object. Please ensure the CLSID is associated with a valid profiler designed to work with this version of the runtime. Profiler CLSID: '%s'." - IDS_PROF_ATTACH_REQUEST_RECEIVED "The CLR received a request to attach a profiler. Profiler CLSID: '%s'." + IDS_E_PROF_BAD_PATH "Loading profiler failed. COR_ENABLE_PROFILING and COR_PROFILER were set properly, but COR_PROFILER_PATH was not. COR_PROFILER_PATH must be set to the full path of the profiler DLL to load with no more than 260 charaters including the null terminator.\n" + IDS_E_PROF_NO_CLSID "Loading profiler failed. COR_ENABLE_PROFILING was set properly, but COR_PROFILER was not. COR_PROFILER must be set to the CLSID of the profiler to load.\n" + IDS_E_PROF_INTERNAL_INIT "Loading profiler failed due to an internal profiling services initialization failure. Profiler CLSID: '%s'. HRESULT: 0x%x.\n" + IDS_E_PROF_BAD_CLSID "Loading profiler failed. COR_PROFILER is set to an invalid CLSID: '%s'. HRESULT: 0x%x.\n" + IDS_E_PROF_NO_CALLBACK_IFACE "Loading profiler failed. COR_PROFILER is set to a CLSID of a COM object that does not implement the interface GUID (IID) requested by the CLR. This often indicates that the profiler does not support this version of the CLR. Profiler CLSID: '%s'. Requested IID: '%s'.\n" + IDS_E_PROF_CCI_FAILED "Loading profiler failed during CoCreateInstance. Profiler CLSID: '%s'. HRESULT: 0x%x.\n" + IDS_E_PROF_INIT_CALLBACK_FAILED "Loading profiler failed. The profiler COM object was instantiated, but the profiler failed during its initialization callback. Profiler CLSID: '%s'. HRESULT: 0x%x.\n" + IDS_PROF_SUPPLEMENTARY_INFO "Process ID (decimal): %d. Message ID: [0x%x].\n" + IDS_PROF_LOAD_COMPLETE "The profiler was loaded successfully. Profiler CLSID: '%s'.\n" + IDS_E_PROF_NOT_ATTACHABLE "Loading profiler failed. The profiler COM object was instantiated, but the profiler does not support attaching to a live process. The profiler must be loaded at application startup by using a launcher program included with the profiler (if any) or by setting the COR_ENABLE_PROFILING and COR_PROFILER environment variables before launching the application to be profiled. Profiler CLSID: '%s'\n" + IDS_E_PROF_UNHANDLED_EXCEPTION_ON_LOAD "Loading profiler failed. There was an unhandled exception while trying to instantiate the profiler COM object. Please ensure the CLSID is associated with a valid profiler designed to work with this version of the runtime. Profiler CLSID: '%s'.\n" + IDS_PROF_ATTACH_REQUEST_RECEIVED "The CLR received a request to attach a profiler. Profiler CLSID: '%s'.\n" IDS_PROF_DETACH_INITIATED "The profiler currently in use has requested to be detached from the process. The CLR has disabled communication with the profiler and will unload the profiler when it is safe to do so.\n" IDS_PROF_DETACH_COMPLETE "The CLR has fully detached and unloaded the profiler.\n" - IDS_PROF_DETACH_THREAD_ERROR "There was an internal failure in the profiling API detach infrastructure. The profiler will not be able to be detached. Error code: %d." - IDS_PROF_CANCEL_ACTIVATION "The profiler has requested that the CLR instance not load the profiler into this process. Profiler CLSID: '%s'." - IDS_PROF_V2PROFILER_DISABLED "Loading profiler failed. The profiler that was configured to load was designed for an older version of the CLR. You can use the COMPlus_ProfAPI_ProfilerCompatibilitySetting environment variable to allow older profilers to be loaded by the current version of the CLR. Please consult the documentation for information on how to use this environment variable, and the risks associated with it. Profiler CLSID: '%s'." - IDS_PROF_V2PROFILER_ENABLED "A profiler designed for an older version of the CLR was loaded because of the environment variable setting below. Older profilers will continue to work in many cases, but if you encounter problems, please consider upgrading the profiler or changing the setting of the environment variable. Please consult the documentation for information on how to use this environment variable, and the risks associated with it. Environment variable setting: %s=%s. Profiler CLSID: '%s'." - IDS_PROF_PROFILER_DISABLED "Profilers will not be loaded by the current version of the CLR because of the environment variable setting below. Please consult the documentation for information on how to use this environment variable, and the risks associated with it. Environment variable setting: %s=%s. Profiler CLSID: '%s'." - IDS_E_PROF_NOTIFICATION_DISABLED "Profiler was prevented from loading notification profiler due to app settings." - IDS_E_PROF_NOTIFICATION_LIMIT_EXCEEDED "Notification profiler was prevented from loading because the limit of notification profilers was reached." - IDS_E_PROF_TIMEOUT_WAITING_FOR_CONCURRENT_GC "Profiler timed out on waiting for concurrent GC to finish after '%d' milliseconds. Please configure your profiler to increase its attaching time out value or consult the documentation for the COMPlus_ProfAPI_AttachProfilerMinTimeoutInMs environment variable and try again. Profiler CLSID: '%s'." - IDS_PROF_ALREADY_LOADED "A request was made to load a profiler when a profiler was already loaded." + IDS_PROF_DETACH_THREAD_ERROR "There was an internal failure in the profiling API detach infrastructure. The profiler will not be able to be detached. Error code: %d.\n" + IDS_PROF_CANCEL_ACTIVATION "The profiler has requested that the CLR instance not load the profiler into this process. Profiler CLSID: '%s'.\n" + IDS_PROF_V2PROFILER_DISABLED "Loading profiler failed. The profiler that was configured to load was designed for an older version of the CLR. You can use the COMPlus_ProfAPI_ProfilerCompatibilitySetting environment variable to allow older profilers to be loaded by the current version of the CLR. Please consult the documentation for information on how to use this environment variable, and the risks associated with it. Profiler CLSID: '%s'.\n" + IDS_PROF_V2PROFILER_ENABLED "A profiler designed for an older version of the CLR was loaded because of the environment variable setting below. Older profilers will continue to work in many cases, but if you encounter problems, please consider upgrading the profiler or changing the setting of the environment variable. Please consult the documentation for information on how to use this environment variable, and the risks associated with it. Environment variable setting: %s=%s. Profiler CLSID: '%s'.\n" + IDS_PROF_PROFILER_DISABLED "Profilers will not be loaded by the current version of the CLR because of the environment variable setting below. Please consult the documentation for information on how to use this environment variable, and the risks associated with it. Environment variable setting: %s=%s. Profiler CLSID: '%s'.\n" + IDS_E_PROF_NOTIFICATION_DISABLED "Profiler was prevented from loading notification profiler due to app settings.\n" + IDS_E_PROF_NOTIFICATION_LIMIT_EXCEEDED "Notification profiler was prevented from loading because the limit of notification profilers was reached.\n" + IDS_E_PROF_TIMEOUT_WAITING_FOR_CONCURRENT_GC "Profiler timed out on waiting for concurrent GC to finish after '%d' milliseconds. Please configure your profiler to increase its attaching time out value or consult the documentation for the COMPlus_ProfAPI_AttachProfilerMinTimeoutInMs environment variable and try again. Profiler CLSID: '%s'.\n" + IDS_PROF_ALREADY_LOADED "A request was made to load a profiler when a profiler was already loaded.\n" END From abae1b09b917fe324ad1c5f8106bf4bbd6a28442 Mon Sep 17 00:00:00 2001 From: David Mason Date: Tue, 17 Aug 2021 00:02:20 -0700 Subject: [PATCH 9/9] Adjust expected ms --- src/coreclr/vm/profdetach.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/profdetach.cpp b/src/coreclr/vm/profdetach.cpp index a820182aacb0ca..ffbe0bec68617a 100644 --- a/src/coreclr/vm/profdetach.cpp +++ b/src/coreclr/vm/profdetach.cpp @@ -170,9 +170,9 @@ HRESULT ProfilingAPIDetach::RequestProfilerDetach(ProfilerInfo *pProfilerInfo, D if (dwExpectedCompletionMilliseconds == 0) { - // Pick suitable default if the profiler just leaves this at 0. 5 seconds is + // Pick suitable default if the profiler just leaves this at 0. 2.5 seconds is // reasonable. - dwExpectedCompletionMilliseconds = 5000; + dwExpectedCompletionMilliseconds = 2500; } {