Skip to content

.NET event counters from System.Runtime are not reported in some circumstances in .NET 9 RC 1 #107919

@valco1994

Description

@valco1994

Description

In .NET 9 RC 1 I observe problems with reporting event counters from the System.Runtime provider.

Reproduction Steps

I have following test application:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

public class ControlledExitProgram
{
  private class InterprocessEvent
  {
    private readonly string myId;

    public InterprocessEvent(string id)
    {
      myId = id;
    }

    public void Set()
    {
      Console.WriteLine(myId);
    }
      
    public void SetWaited()
    {
      WaitOne();
      Console.WriteLine(myId);
    }

    public void WaitOne()
    {
      var line = Console.ReadLine();
      if (line != myId)
        throw new ApplicationException(string.Format("Unexpected input: {0}. Event {1} is expected.", line, myId));
    }
  }

  private static string GetReadySignalId(int pid) => $"{nameof(ControlledExitProgram)}.Ready.{pid}";
  private static string GetExitSignalId(int pid) => $"{nameof(ControlledExitProgram)}.Exit.{pid}";
  private static string GetResponseSignalId(int pid) => $"{nameof(ControlledExitProgram)}.Response.{pid}";
  private static InterprocessEvent CreateEvent(string id) => new InterprocessEvent(id);

  public static void Main(string[] args)
  {
    var readyEvent = CreateEvent(GetReadySignalId(Process.GetCurrentProcess().Id));
    readyEvent.SetWaited();

    var typeName = args[0];
    var type = Type.GetType(typeName);
    var constructor = type.GetConstructor(new Type[]{});
    var parameters = new object[] { };
      
    constructor.Invoke(parameters);
      
    var waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);
    Task.Factory.StartNew(() =>
    {
      var exitEvent = CreateEvent(GetExitSignalId(Process.GetCurrentProcess().Id));
      exitEvent.WaitOne();
      waitHandle.Set();
    });

    while (true)
    {
      try
      {
        throw new Exception();
      }
      catch {}

      var list = new List<object>();
      var iterationsCount = 1000000;
      while (iterationsCount-- > 0)
        list.Add(constructor.Invoke(parameters));
        
      Console.WriteLine(list.Aggregate(0, (hash, o) => hash ^ o.GetHashCode()));

      GC.Collect();

      if (waitHandle.WaitOne(TimeSpan.FromSeconds(1)))
      {
        var responseEvent = CreateEvent(GetResponseSignalId(Process.GetCurrentProcess().Id));
        responseEvent.Set();
        break;
      }
    }
  }
}

This application waits for input ControlledExitProgram.Ready.[pid] and then runs some computation until it receives the input ControlledExitProgram.Ready.[pid].

There are two scenarios:

  1. Connect to the application with either ETW or EventPipe requesting data from RuntimeEventSource - provider name "System.Runtime", provider GUID "49592C0F-5A05-516D-AA4B-A64E02026C89". Then write ControlledExitProgram.Ready.[pid] to the standard input of the application.
  2. At first write ControlledExitProgram.Ready.[pid] to the standard input of the application, and then connect to the application in the same way as in the 1st scenario.

Expected behavior

We successfully receive event counters from System.Runtime provider in both scenarios.

Actual behavior

We do NOT receive event counters from System.Runtime provider in the second scenario.

Regression?

Yes, everything was working smoothly until .NET 9 RC 1 (including all previous .NET preview versions).

Known Workarounds

Corresponding data is reported as a System.Runtime meter via Metrics API, see RuntimeMetrics.cs.

So, it's technically possible to access the data. But it's unexpected and breaks some tooling.

Anyway, both approaches (with event counters and metrics) should work properly.

Configuration

.NET 9 RC 1, as far as I see, all supported platforms are affected.

Other information

No response

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions