diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index 372222dce0ffe7..11a9b8b5e00923 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -824,6 +824,10 @@ void EEStartupHelper() ExecutionManager::Init(); +#ifdef FEATURE_PERFMAP + PerfMap::SignalDependenciesReady(); +#endif + JitHost::Init(); #ifndef TARGET_UNIX diff --git a/src/coreclr/vm/perfmap.cpp b/src/coreclr/vm/perfmap.cpp index f2cc1212595891..c4c12604433c2a 100644 --- a/src/coreclr/vm/perfmap.cpp +++ b/src/coreclr/vm/perfmap.cpp @@ -28,6 +28,7 @@ #endif Volatile PerfMap::s_enabled = false; +Volatile PerfMap::s_dependenciesReady = false; PerfMap * PerfMap::s_Current = nullptr; bool PerfMap::s_ShowOptimizationTiers = false; bool PerfMap::s_GroupStubsOfSameType = false; @@ -121,6 +122,17 @@ void PerfMap::Enable(PerfMapType type, bool sendExisting) if (sendExisting) { + // When Enable is called very early in startup (e.g., via DiagnosticServer IPC before + // SystemDomain::Attach and ExecutionManager::Init), the AppDomain and EEJitManager + // may not exist yet. We use s_dependenciesReady (a Volatile) to guard against + // this, rather than null-checking individual pointers which would have race conditions + // due to non-Volatile statics like m_pEEJitManager. + // Safe to skip: no assemblies are loaded and no code is JIT'd at that point. + if (!s_dependenciesReady) + { + return; + } + AppDomain::AssemblyIterator assemblyIterator = GetAppDomain()->IterateAssembliesEx( (AssemblyIterationFlags)(kIncludeLoaded | kIncludeExecution)); CollectibleAssemblyHolder pAssembly; @@ -208,6 +220,15 @@ void PerfMap::Disable() } } +// Signal that all dependencies (AppDomain, ExecutionManager) are ready. +// This method must be called before any code is JITed or restored from R2R image. +void PerfMap::SignalDependenciesReady() +{ + LIMITED_METHOD_CONTRACT; + + s_dependenciesReady = true; +} + // Construct a new map for the process. PerfMap::PerfMap() { diff --git a/src/coreclr/vm/perfmap.h b/src/coreclr/vm/perfmap.h index 5268c4b0d56aef..4dc23f65e107db 100644 --- a/src/coreclr/vm/perfmap.h +++ b/src/coreclr/vm/perfmap.h @@ -24,6 +24,9 @@ class PerfMap private: static Volatile s_enabled; + // Set to true after all dependencies (AppDomain, ExecutionManager) are initialized. + static Volatile s_dependenciesReady; + // The one and only PerfMap for the process. static PerfMap * s_Current; @@ -104,6 +107,9 @@ class PerfMap // Close the map and flush any remaining data. static void Disable(); + // Signal that all dependencies (AppDomain, ExecutionManager) are ready. + static void SignalDependenciesReady(); + static bool LowGranularityStubs() { return !s_IndividualAllocationStubReporting; } }; #endif // PERFPID_H