Handle sessionId as ulong instead of long in EventPipeSession.cs. (#4345)
authorJohan Lorensson <lateralusx.github@gmail.com>
Mon, 23 Oct 2023 23:48:53 +0000 (01:48 +0200)
committerGitHub <noreply@github.com>
Mon, 23 Oct 2023 23:48:53 +0000 (16:48 -0700)
Session id is a uint64 in runtime as well as specified as a uint64 in
IPC protocol,
https://github.com/dotnet/diagnostics/blob/main/documentation/design-docs/ipc-protocol.md#returns-as-an-ipc-message-payload.

EventPipeSession.cs however handled it as a long instead of an ulong,
currently that doesn't affect release builds since it doesn't do much
with the id except passing it back to stop the session, but in debug
builds there is an assert that validates that session id > 0. On Android
physical devices it is not uncommon to get code and memory allocated at
high addresses, including having the high order bit set and when that
happens, EventPipeSession.cs will see a negative session id and assert
on debug builds.

Fix adjust session id as ulong inline with IPC protocol, it also makes
sure keyword serialized when starting a session is handled according to
IPC specification, but only when serialized into the payload, it will
still be typed as long inside EventPipeProvider since it is a public
property.

src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/EventPipeSession.cs
src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/EventPipeSessionConfiguration.cs

index 041502f6f79c071f38751193662bf7b6baa7b130..d61aace345589af66d9f9fc615b2558672dfe78e 100644 (file)
@@ -13,13 +13,13 @@ namespace Microsoft.Diagnostics.NETCore.Client
 {
     public class EventPipeSession : IDisposable
     {
-        private long _sessionId;
+        private ulong _sessionId;
         private IpcEndpoint _endpoint;
         private bool _disposedValue; // To detect redundant calls
         private bool _stopped; // To detect redundant calls
         private readonly IpcResponse _response;
 
-        private EventPipeSession(IpcEndpoint endpoint, IpcResponse response, long sessionId)
+        private EventPipeSession(IpcEndpoint endpoint, IpcResponse response, ulong sessionId)
         {
             _endpoint = endpoint;
             _response = response;
@@ -93,7 +93,7 @@ namespace Microsoft.Diagnostics.NETCore.Client
             {
                 DiagnosticsClient.ValidateResponseMessage(response.Value.Message, operationName);
 
-                long sessionId = BinaryPrimitives.ReadInt64LittleEndian(new ReadOnlySpan<byte>(response.Value.Message.Payload, 0, 8));
+                ulong sessionId = BinaryPrimitives.ReadUInt64LittleEndian(new ReadOnlySpan<byte>(response.Value.Message.Payload, 0, 8));
 
                 EventPipeSession session = new(endpoint, response.Value, sessionId);
                 response = null;
index 25f813d8ffe1cad1b9efc04ba1be6d2f1cdbafb9..0e837d908cbcc5c0b7e2ae3bbeb274e9c0e3b62c 100644 (file)
@@ -59,7 +59,7 @@ namespace Microsoft.Diagnostics.NETCore.Client
                 writer.Write(Providers.Count);
                 foreach (EventPipeProvider provider in Providers)
                 {
-                    writer.Write(provider.Keywords);
+                    writer.Write(unchecked((ulong)provider.Keywords));
                     writer.Write((uint)provider.EventLevel);
 
                     writer.WriteString(provider.Name);