runtime: Calling EventSource.Write with data containing an array of string throws on .net Core 2.1, works on .net Core 2.0

I have code that calls EventSource.Write and passes in a field that is an array of strings. The code looks similar to:

public static void LogFoo(string[] foo) {
    EventSource logger = new EventSource(...);
    logger.Write("...", options, new { Foo = foo });
}

This code works without issue when run targeting any version of .net Framework I’ve tested, and when targeting netcoreapp2.0. It does not work with netcoreapp2.1 with runtime version v2.1.300, instead throwing a System.NotSupportedException: ‘Arrays of null-terminated string are not supported.’ . While the message is pretty clear, I’m wondering if this functionality regression was intentional?

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Comments: 16 (14 by maintainers)

Most upvoted comments

I’d still like to get this addressed in 3.0 if we can

After some further research, this works because you can pass arbitrary sized collections of strings to EventSource, but the specific example above doesn’t work.

Anonymous types with arrays as arguments are broken for all types. I.e. if you pass new { args = new int[] { 1, 2, 3, 4 }} as a parameter to WriteEvent it will also fail.

I suspect the code above is doing that because WriteEvent(1, new string[] { "sample", "array" }); will fail because the C# compiler resolves to the WriteEvent(int eventId, params object[]? args) overload and the strings are passed as individual arguments instead of one array argument.

If you use the IEnumerable overload instead it will correctly send the event in .net 5:

        [Event(2, Level = EventLevel.LogAlways)]
        public void StringIEnumerableEvent(IEnumerable<string> args)
        {
            WriteEvent(2, args);
        }

This is not an issue for built in types (int, double, etc) arrays. I am not a C# language spec expert, but I suspect the issue is that string is an object and ints, etc, are value types so they won’t use the object[] params overload.

The real issue here is the fact that anonymous types don’t work with array types. I think this will require enough changes to EventSource that it should probably be pushed out to 6.0.

@josalem, I suspect you are right that this is not going to be trivial. It stems from the fact that I was trying to unify the way we serialize strings between TraceLogging ETW and EventPipe so that I could add support for TraceLogging in EventPipe without having to support two deserialization schemes within TraceEvent. TraceLogging ETW previously used counted strings and had support for arrays of counted strings but when I switched things over to NULL-terminated strings, I did not realize, nor have a test case that covered arrays of strings. The code had always been written to disallow this, but the path was never hit.

I suspect that it is possible to implement this without too much trouble, but I don’t know what the encoding would look like. I don’t believe that this would require fundamental changes to EventSource, but would require that we understand what the encoding should look like for supporting this on the ETW side, and then making sure that this works on the EventPipe side as well.

If you want to dig into this more, let me know and I can connect you with the right person who can tell us what the encoding should look like.