microsoft / perfview

PerfView is a CPU and memory performance-analysis tool
http://channel9.msdn.com/Series/PerfView-Tutorial
MIT License
4.14k stars 707 forks source link

Disposing EventPipeEventSource does not exit Process #1961

Closed kevingosse closed 9 months ago

kevingosse commented 9 months ago

I have a simple application where I listen to GC events:

var provider = new EventPipeProvider("Microsoft-Windows-DotNETRuntime", EventLevel.Informational, (long)ClrTraceEventParser.Keywords.GC);

var client = new DiagnosticsClient(pid);
var session = client.StartEventPipeSession(provider);
var source = new EventPipeEventSource(session.EventStream);

source.NeedLoadedDotNetRuntimes();
source.AddCallbackOnProcessStart(process =>
{
    process.AddCallbackOnDotNetRuntimeLoad(runtime =>
    {
        runtime.GCEnd += (p, gc) => GCEnd(p, gc);
    });
});

source.Process();

When disposing the source, the thread remains stuck in source.Process:

>   System.IO.Pipes.dll!Interop.Kernel32.ReadFile(System.Runtime.InteropServices.SafeHandle handle, byte* bytes, int numBytesToRead, out int numBytesRead, nint mustBeZero) Line 581    C#
    System.IO.Pipes.dll!System.IO.Pipes.PipeStream.ReadCore(System.Span<byte> buffer) Line 288  C#
    System.IO.Pipes.dll!System.IO.Pipes.PipeStream.Read(byte[] buffer, int offset, int count) Line 35   C#
    Microsoft.Diagnostics.FastSerialization.dll!FastSerialization.IOStreamStreamReader.Fill(int minimum) Line 171   C#
    Microsoft.Diagnostics.FastSerialization.dll!FastSerialization.MemoryStreamReader.ReadByte() Line 67 C#
    Microsoft.Diagnostics.FastSerialization.dll!FastSerialization.Deserializer.ReadTag() Line 734   C#
    Microsoft.Diagnostics.FastSerialization.dll!FastSerialization.Deserializer.ReadObject() Line 215    C#
    Microsoft.Diagnostics.Tracing.TraceEvent.dll!Microsoft.Diagnostics.Tracing.EventPipeEventSource.Process() Line 153  C#

I assume it will be unblocked after the next event is pushed, but because I'm only listening to GC it can take an arbitrarily long amount of time.

I think the FastSerializer should take a cancellation token or something?

kevingosse commented 9 months ago

Never mind, I misread the documentation of source.StopProcessing, which suggests to dispose the session first. That fixed it.