private ProfilerEngine(IProductConfiguration config)
        {
            Validate.NotNull(config, nameof(config));

            _versionInfo = ProfilerEngineVersionInfo.CreateNewInstance();

            _profiledThreadInfoProvider = new ProfiledThreadInfoProvider();
            _profiledAppDomainProvider  = new ProfiledAppDomainProvider();

            _enqueueStackSnapshotBufferSegmentForExport = NativeCallback_EnqueueStackSnapshotBufferSegmentForExport;
            _tryShutdownCurrentManagedProfilerEngine    = NativeCallback_TryShutdownCurrentManagedProfilerEngine;

            _completedStackSnapshots = new StackSnapshotsBufferSegmentCollection();

            _pprofBuilder = new PProfBuilder();

            RegisterReversePInvokeCallbacks();

            _resolveAndExportStacksBackgroundLoop = new ResolveAndExportStacksBackgroundLoop(this, config);
            _resolveAndExportStacksBackgroundLoop.Start();
        }
Ejemplo n.º 2
0
        private void RegisterReversePInvokeCallbacks()
        {
            const string ErrorMessage = "While initializing, the Managed Profiler Engine overwrote an existing reverse PInvoke callback."
                                        + " This may indicate a serious problem with code or configuration."
                                        + " Perhaps, there are more than a single process-wide instance of " + nameof(ProfilerEngine) + "?"
                                        + " This could happen, for instance, if the Engine is being loaded into more than a single AppDomain."
                                        + " If so, it is not a supported scenario.";
            {
                NativeInterop.ManagedCallbackRegistry.EnqueueStackSnapshotBufferSegmentForExport.Delegate_t prevExistingCallback =
                    NativeInterop.ManagedCallbackRegistry.EnqueueStackSnapshotBufferSegmentForExport.Set(_enqueueStackSnapshotBufferSegmentForExport);

                if (prevExistingCallback != null)
                {
                    AppDomain currentAppDomain = AppDomain.CurrentDomain;

#pragma warning disable SA1117 // easier to have the mapping key/value on the same line
                    Log.Error(
                        Log.WithCallInfo(LogSourceMoniker),
                        ErrorMessage,
                        "Callback moniker", nameof(NativeInterop.ManagedCallbackRegistry.EnqueueStackSnapshotBufferSegmentForExport),
                        $"{nameof(currentAppDomain)}.{nameof(AppDomain.Id)}", currentAppDomain?.Id,
                        $"{nameof(currentAppDomain)}.{nameof(AppDomain.FriendlyName)}", currentAppDomain?.FriendlyName,
                        $"{nameof(currentAppDomain)}.{nameof(AppDomain.IsDefaultAppDomain)}", currentAppDomain?.IsDefaultAppDomain());
                }
            }

            {
                NativeInterop.ManagedCallbackRegistry.TryShutdownCurrentManagedProfilerEngine.Delegate_t prevExistingCallback =
                    NativeInterop.ManagedCallbackRegistry.TryShutdownCurrentManagedProfilerEngine.Set(_tryShutdownCurrentManagedProfilerEngine);

                if (prevExistingCallback != null)
                {
                    AppDomain currentAppDomain = AppDomain.CurrentDomain;

                    Log.Error(
                        Log.WithCallInfo(LogSourceMoniker),
                        ErrorMessage,
                        "Callback moniker", nameof(NativeInterop.ManagedCallbackRegistry.TryShutdownCurrentManagedProfilerEngine),
                        $"{nameof(currentAppDomain)}.{nameof(AppDomain.Id)}", currentAppDomain?.Id,
                        $"{nameof(currentAppDomain)}.{nameof(AppDomain.FriendlyName)}", currentAppDomain?.FriendlyName,
                        $"{nameof(currentAppDomain)}.{nameof(AppDomain.IsDefaultAppDomain)}", currentAppDomain?.IsDefaultAppDomain());
                }
#pragma warning restore SA1117 // Parameters should be on same line or separate lines
            }
        }