public static async Task <bool> TEST_DisabledCommandsError() { bool fSuccess = true; string serverName = ReverseServer.MakeServerAddress(); Logger.logger.Log($"Server name is '{serverName}'"); var server = new ReverseServer(serverName); using var memoryStream1 = new MemoryStream(); using var memoryStream2 = new MemoryStream(); using var memoryStream3 = new MemoryStream(); Task <bool> subprocessTask = Utils.RunSubprocess( currentAssembly: Assembly.GetExecutingAssembly(), environment: new Dictionary <string, string> { { Utils.DiagnosticPortsEnvKey, $"{serverName}" } }, duringExecution: async(pid) => { Stream stream = await server.AcceptAsync(); IpcAdvertise advertise = IpcAdvertise.Parse(stream); Logger.logger.Log(advertise.ToString()); Logger.logger.Log($"Send profiler attach Diagnostics IPC Command"); // send profiler attach command (0x03=ProfilerCommandId, 0x01=attach commandid) var message = new IpcMessage(0x03, 0x01); Logger.logger.Log($"Sent: {message.ToString()}"); IpcMessage response = IpcClient.SendMessage(stream, message); Logger.logger.Log($"received: {response.ToString()}"); if (response.Header.CommandSet != 0xFF && response.Header.CommandId != 0xFF) { throw new Exception("Command did not fail!"); } stream = await server.AcceptAsync(); advertise = IpcAdvertise.Parse(stream); Logger.logger.Log(advertise.ToString()); Logger.logger.Log($"Send ResumeRuntime Diagnostics IPC Command"); // send ResumeRuntime command (0x04=ProcessCommandSet, 0x01=ResumeRuntime commandid) message = new IpcMessage(0x04, 0x01); Logger.logger.Log($"Sent: {message.ToString()}"); response = IpcClient.SendMessage(stream, message); Logger.logger.Log($"received: {response.ToString()}"); } ); fSuccess &= await subprocessTask; return(fSuccess); }
public static int Main(string[] args) { if (args.Length > 0 && args[0].Equals("RunTest", StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("In RunTest, exiting."); return(100); } string serverName = ReverseServer.MakeServerAddress(); Task backgroundTask = Task.Run(() => { ReverseServer server = null; try { Task task = Task.Run(async() => { server = new ReverseServer(serverName); using (Stream serverStream = await server.AcceptAsync()) { IpcAdvertise advertise = IpcAdvertise.Parse(serverStream); Console.WriteLine($"Got IpcAdvertise: {advertise}"); int processId = (int)advertise.ProcessId; // While we are paused in startup send the profiler startup command string profilerPath = GetProfilerPath(); DiagnosticsIPCWorkaround client = new DiagnosticsIPCWorkaround(processId); client.SetStartupProfiler(ReverseStartupProfilerGuid, profilerPath); // Resume runtime message IpcMessage resumeMessage = new IpcMessage(0x04, 0x01); Console.WriteLine($"Sent resume runtime message: {resumeMessage.ToString()}"); IpcMessage resumeResponse = IpcClient.SendMessage(serverStream, resumeMessage); Logger.logger.Log($"Received: {resumeResponse.ToString()}"); } }); task.Wait(); } catch (Exception e) { Console.WriteLine($"ReverseServer saw exception {e.Message}"); Console.WriteLine(e.StackTrace); Console.WriteLine($"Inner exception {e.InnerException?.Message}"); Console.WriteLine(e.InnerException?.StackTrace); } finally { server?.Shutdown(); } }); return(ProfilerTestRunner.Run(profileePath: System.Reflection.Assembly.GetExecutingAssembly().Location, testName: "ReverseStartup", profilerClsid: Guid.Empty, profileeOptions: ProfileeOptions.NoStartupAttach | ProfileeOptions.ReverseDiagnosticsMode, reverseServerName: serverName)); }
public static async Task <bool> TEST_TracesHaveRelevantEvents() { bool fSuccess = true; string serverName = ReverseServer.MakeServerAddress(); Logger.logger.Log($"Server name is '{serverName}'"); var server = new ReverseServer(serverName); using var memoryStream = new MemoryStream(); Task <bool> subprocessTask = Utils.RunSubprocess( currentAssembly: Assembly.GetExecutingAssembly(), environment: new Dictionary <string, string> { { Utils.DiagnosticPortsEnvKey, $"{serverName}" } }, duringExecution: async(pid) => { Stream stream = await server.AcceptAsync(); IpcAdvertise advertise = IpcAdvertise.Parse(stream); Logger.logger.Log(advertise.ToString()); var config = new SessionConfiguration( circularBufferSizeMB: 1000, format: EventPipeSerializationFormat.NetTrace, providers: new List <Provider> { new Provider("Microsoft-Windows-DotNETRuntimePrivate", 0x80000000, EventLevel.Verbose) }); Logger.logger.Log("Starting EventPipeSession over standard connection"); using Stream eventStream = EventPipeClient.CollectTracing(pid, config, out var sessionId); Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:x}"); Task readerTask = eventStream.CopyToAsync(memoryStream); Logger.logger.Log($"Send ResumeRuntime Diagnostics IPC Command"); // send ResumeRuntime command (0x04=ProcessCommandSet, 0x01=ResumeRuntime commandid) var message = new IpcMessage(0x04, 0x01); Logger.logger.Log($"Sent: {message.ToString()}"); IpcMessage response = IpcClient.SendMessage(stream, message); Logger.logger.Log($"received: {response.ToString()}"); await Task.Delay(TimeSpan.FromSeconds(2)); Logger.logger.Log("Stopping EventPipeSession over standard connection"); EventPipeClient.StopTracing(pid, sessionId); await readerTask; Logger.logger.Log("Stopped EventPipeSession over standard connection"); } ); fSuccess &= await subprocessTask; memoryStream.Seek(0, SeekOrigin.Begin); using var source = new EventPipeEventSource(memoryStream); var parser = new ClrPrivateTraceEventParser(source); bool isStartupEventPresent = false; parser.StartupEEStartupStart += (eventData) => isStartupEventPresent = true; source.Process(); Logger.logger.Log($"isStartupEventPresent: {isStartupEventPresent}"); return(isStartupEventPresent && fSuccess); }
public static async Task <bool> TEST_RuntimeResumesExecutionWithCommand() { bool fSuccess = true; string serverName = ReverseServer.MakeServerAddress(); Logger.logger.Log($"Server name is '{serverName}'"); var server = new ReverseServer(serverName); Task <bool> subprocessTask = Utils.RunSubprocess( currentAssembly: Assembly.GetExecutingAssembly(), environment: new Dictionary <string, string> { { Utils.DiagnosticPortsEnvKey, $"{serverName}" } }, duringExecution: async(_) => { Stream stream = await server.AcceptAsync(); IpcAdvertise advertise = IpcAdvertise.Parse(stream); Logger.logger.Log(advertise.ToString()); // send ResumeRuntime command (0x04=ProcessCommandSet, 0x01=ResumeRuntime commandid) var message = new IpcMessage(0x04, 0x01); Logger.logger.Log($"Sent: {message.ToString()}"); IpcMessage response = IpcClient.SendMessage(stream, message); Logger.logger.Log($"received: {response.ToString()}"); } ); fSuccess &= await subprocessTask; return(fSuccess); }
public void SetStartupProfiler(Guid profilerGuid, string profilerPath) { MethodInfo startupProfiler = typeof(DiagnosticsClient).GetMethod("SetStartupProfiler", BindingFlags.Public); if (startupProfiler != null) { throw new Exception("You updated DiagnosticsClient to a version that supports SetStartupProfiler, please remove this and use the real code."); } Console.WriteLine("Sending startup profiler message."); using (var stream = new MemoryStream()) using (var writer = new BinaryWriter(stream)) { writer.Write(profilerGuid.ToByteArray()); writer.WriteString(profilerPath); writer.Flush(); byte[] payload = stream.ToArray(); var message = new IpcMessage(0x03, 0x02, payload); Console.WriteLine($"Sent: {message.ToString()}"); IpcMessage response = IpcClient.SendMessage(ConnectionHelper.GetStandardTransport(_processId), message); Console.WriteLine($"Received: {response.ToString()}"); } Console.WriteLine("Finished sending startup profiler message."); }
public static async Task <bool> TEST_CanGetProcessInfo2WhileSuspended() { bool fSuccess = true; Task <bool> subprocessTask = Utils.RunSubprocess( currentAssembly: Assembly.GetExecutingAssembly(), environment: new Dictionary <string, string> { { Utils.DiagnosticPortSuspend, "1" } }, duringExecution: (int pid) => { Stream stream = ConnectionHelper.GetStandardTransport(pid); // 0x04 = ProcessCommandSet, 0x04 = ProcessInfo2 var processInfoMessage = new IpcMessage(0x04, 0x04); Logger.logger.Log($"Wrote: {processInfoMessage}"); IpcMessage response = IpcClient.SendMessage(stream, processInfoMessage); Logger.logger.Log($"Received: [{response.Payload.Select(b => b.ToString("X2") + " ").Aggregate(string.Concat)}]"); ProcessInfo2 processInfo2 = ProcessInfo2.TryParse(response.Payload); Utils.Assert(String.IsNullOrEmpty(processInfo2.ManagedEntrypointAssemblyName)); // send resume command on this connection var message = new IpcMessage(0x04, 0x01); Logger.logger.Log($"Sent: {message.ToString()}"); response = IpcClient.SendMessage(ConnectionHelper.GetStandardTransport(pid), message); Logger.logger.Log($"Received: {response.ToString()}"); return(Task.FromResult(true)); } ); fSuccess &= await subprocessTask; return(fSuccess); }
public static async Task <bool> TEST_AdvertiseAndProcessInfoCookiesMatch() { bool fSuccess = true; string serverName = ReverseServer.MakeServerAddress(); Logger.logger.Log($"Server name is '{serverName}'"); var server = new ReverseServer(serverName); using var memoryStream = new MemoryStream(); Task <bool> subprocessTask = Utils.RunSubprocess( currentAssembly: Assembly.GetExecutingAssembly(), environment: new Dictionary <string, string> { { Utils.DiagnosticPortsEnvKey, $"{serverName},nosuspend" } }, duringExecution: async(pid) => { Stream stream = await server.AcceptAsync(); IpcAdvertise advertise = IpcAdvertise.Parse(stream); Logger.logger.Log(advertise.ToString()); Logger.logger.Log($"Send ProcessInfo Diagnostics IPC Command"); // send ProcessInfo command (0x04=ProcessCommandSet, 0x00=ProcessInfo commandid) var message = new IpcMessage(0x04, 0x00); Logger.logger.Log($"Sent: {message.ToString()}"); IpcMessage response = IpcClient.SendMessage(stream, message); Logger.logger.Log($"received: {response.ToString()}"); ProcessInfo info = ProcessInfo.TryParse(response.Payload); Logger.logger.Log($"ProcessInfo: {{ id={info.ProcessId}, cookie={info.RuntimeCookie}, cmdline={info.Commandline}, OS={info.OS}, arch={info.Arch} }}"); Utils.Assert(info.RuntimeCookie.Equals(advertise.RuntimeInstanceCookie), $"The runtime cookie reported by ProcessInfo and Advertise must match. ProcessInfo: {info.RuntimeCookie.ToString()}, Advertise: {advertise.RuntimeInstanceCookie.ToString()}"); Logger.logger.Log($"ProcessInfo and Advertise Cookies are equal"); } ); fSuccess &= await subprocessTask; return(fSuccess); }
public bool SetEnvironmentVariable(string name, string val) { MethodInfo setEnvironmentVariable = typeof(DiagnosticsClient).GetMethod("SetEnvironmentVariable", BindingFlags.Public); if (setEnvironmentVariable != null) { throw new Exception("You updated DiagnosticsClient to a version that supports SetEnvironmentVariable, please remove this and use the real code."); } Console.WriteLine($"Sending SetEnvironmentVariable message name={name} value={val ?? "NULL"}."); using (var stream = new MemoryStream()) using (var writer = new BinaryWriter(stream)) { writer.WriteString(name); writer.WriteString(val); writer.Flush(); byte[] payload = stream.ToArray(); var message = new IpcMessage(0x04, 0x03, payload); Console.WriteLine($"Sent: {message.ToString()}"); IpcMessage response = IpcClient.SendMessage(ConnectionHelper.GetStandardTransport(_processId), message); Console.WriteLine($"Received: {response.ToString()}"); if (response.Header.CommandSet != 255 || response.Header.CommandId != 0) { Console.WriteLine($"SetEnvironmentVariable failed."); return(false); } } Console.WriteLine($"Finished sending SetEnvironmentVariable message."); return(true); }
public static async Task <bool> TEST_MultipleConnectPortsSuspend() { bool fSuccess = true; var serverAndNames = new List <(ReverseServer, string)>(); string dotnetDiagnosticPorts = ""; for (int i = 0; i < s_NumberOfPorts; i++) { string serverName = ReverseServer.MakeServerAddress(); var server = new ReverseServer(serverName); Logger.logger.Log($"Server {i} address is '{serverName}'"); serverAndNames.Add((server, serverName)); dotnetDiagnosticPorts += $"{serverName};"; } Logger.logger.Log($"export DOTNET_DiagnosticPorts={dotnetDiagnosticPorts}"); var advertisements = new List <IpcAdvertise>(); Object sync = new Object(); int subprocessId = -1; Task <bool> subprocessTask = Utils.RunSubprocess( currentAssembly: Assembly.GetExecutingAssembly(), environment: new Dictionary <string, string> { { Utils.DiagnosticPortsEnvKey, dotnetDiagnosticPorts } }, duringExecution: async(int pid) => { subprocessId = pid; // Create an eventpipe session that will tell us when // the EEStartupStarted event happens. This will tell us // the the runtime has been resumed. This should only happen // AFTER all suspend ports have sent the resume command. var config = new SessionConfiguration( circularBufferSizeMB: 1000, format: EventPipeSerializationFormat.NetTrace, providers: new List <Provider> { new Provider("Microsoft-Windows-DotNETRuntimePrivate", 0x80000000, EventLevel.Verbose), // workaround for https://github.com/dotnet/runtime/issues/44072 which happens because the // above provider only sends 2 events and that can cause EventPipeEventSource (from TraceEvent) // to not dispatch the events if the EventBlock is a size not divisible by 8 (the reading alignment in TraceEvent). // Adding this provider keeps data flowing over the pipe so the reader doesn't get stuck waiting for data // that won't come otherwise. new Provider("Microsoft-DotNETCore-SampleProfiler") }); Logger.logger.Log("Starting EventPipeSession over standard connection"); using Stream eventStream = EventPipeClient.CollectTracing(pid, config, out var sessionId); Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:x}"); var mre = new ManualResetEvent(false); Task readerTask = Task.Run(async() => { Logger.logger.Log($"Creating EventPipeEventSource"); using var source = new EventPipeEventSource(eventStream); var parser = new ClrPrivateTraceEventParser(source); parser.StartupEEStartupStart += (eventData) => mre.Set(); Logger.logger.Log($"Created EventPipeEventSource"); Logger.logger.Log($"Starting processing"); await Task.Run(() => source.Process()); Logger.logger.Log($"Finished processing"); }); for (int i = 0; i < s_NumberOfPorts; i++) { fSuccess &= !mre.WaitOne(0); Logger.logger.Log($"Runtime HAS NOT resumed (expects: true): {fSuccess}"); var(server, _) = serverAndNames[i]; int serverIndex = i; Stream stream = await server.AcceptAsync(); IpcAdvertise advertise = IpcAdvertise.Parse(stream); lock (sync) advertisements.Add(advertise); Logger.logger.Log($"Server {serverIndex} got advertise {advertise.ToString()}"); // send resume command on this connection var message = new IpcMessage(0x04, 0x01); Logger.logger.Log($"Port {serverIndex} sent: {message.ToString()}"); IpcMessage response = IpcClient.SendMessage(stream, message); Logger.logger.Log($"Port {serverIndex} received: {response.ToString()}"); } Logger.logger.Log($"Waiting on EEStartupStarted event"); mre.WaitOne(); Logger.logger.Log($"Saw EEStartupStarted Event"); Logger.logger.Log($"Stopping EventPipeSession"); EventPipeClient.StopTracing(pid, sessionId); await readerTask; Logger.logger.Log($"Stopped EventPipeSession"); // runtime should have resumed now fSuccess &= mre.WaitOne(0); Logger.logger.Log($"Runtime HAS resumed (expects: true): {fSuccess}"); } ); fSuccess &= await subprocessTask; foreach (var(server, _) in serverAndNames) { server.Shutdown(); } if (advertisements.Count() > 0) { Guid referenceCookie = advertisements[0].RuntimeInstanceCookie; foreach (var adv in advertisements) { fSuccess &= (int)adv.ProcessId == subprocessId; fSuccess &= adv.RuntimeInstanceCookie.Equals(referenceCookie); } } else { fSuccess &= false; } return(fSuccess); }
public static async Task <bool> TEST_SuspendDefaultPort() { bool fSuccess = true; int subprocessId = -1; Task <bool> subprocessTask = Utils.RunSubprocess( currentAssembly: Assembly.GetExecutingAssembly(), environment: new Dictionary <string, string> { { Utils.DiagnosticPortSuspend, "1" } }, duringExecution: async(int pid) => { subprocessId = pid; // Create an eventpipe session that will tell us when // the EEStartupStarted event happens. This will tell us // the the runtime has been resumed. This should only happen // AFTER all suspend ports have sent the resume command. var config = new SessionConfiguration( circularBufferSizeMB: 1000, format: EventPipeSerializationFormat.NetTrace, providers: new List <Provider> { new Provider("Microsoft-Windows-DotNETRuntimePrivate", 0x80000000, EventLevel.Verbose), // workaround for https://github.com/dotnet/runtime/issues/44072 which happens because the // above provider only sends 2 events and that can cause EventPipeEventSource (from TraceEvent) // to not dispatch the events if the EventBlock is a size not divisible by 8 (the reading alignment in TraceEvent). // Adding this provider keeps data flowing over the pipe so the reader doesn't get stuck waiting for data // that won't come otherwise. new Provider("Microsoft-DotNETCore-SampleProfiler") }); Logger.logger.Log("Starting EventPipeSession over standard connection"); using Stream eventStream = EventPipeClient.CollectTracing(pid, config, out var sessionId); Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:x}"); var mre = new ManualResetEvent(false); Task readerTask = Task.Run(async() => { Logger.logger.Log($"Creating EventPipeEventSource"); using var source = new EventPipeEventSource(eventStream); var parser = new ClrPrivateTraceEventParser(source); parser.StartupEEStartupStart += (eventData) => mre.Set(); Logger.logger.Log($"Created EventPipeEventSource"); Logger.logger.Log($"Starting processing"); await Task.Run(() => source.Process()); Logger.logger.Log($"Finished processing"); }); fSuccess &= !mre.WaitOne(0); Logger.logger.Log($"Runtime HAS NOT resumed (expects: true): {fSuccess}"); // send resume command on this connection var message = new IpcMessage(0x04, 0x01); Logger.logger.Log($"Sent: {message.ToString()}"); IpcMessage response = IpcClient.SendMessage(ConnectionHelper.GetStandardTransport(pid), message); Logger.logger.Log($"Received: {response.ToString()}"); Logger.logger.Log($"Waiting for EEStartupStarted event"); mre.WaitOne(); Logger.logger.Log($"Saw EEStartupStarted event!"); Logger.logger.Log($"Stopping EventPipeSession"); EventPipeClient.StopTracing(pid, sessionId); await readerTask; Logger.logger.Log($"Stopped EventPipeSession"); // runtime should have resumed now fSuccess &= mre.WaitOne(0); Logger.logger.Log($"Runtime HAS resumed (expects: true): {fSuccess}"); } ); fSuccess &= await subprocessTask; return(fSuccess); }
public static async Task <bool> TEST_ProcessInfoBeforeAndAfterSuspension() { // This test only applies to platforms where the PAL is used if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return(true); } // This test only applies to CoreCLR (this checks if we're running on Mono) if (Type.GetType("Mono.RuntimeStructs") != null) { return(true); } bool fSuccess = true; string serverName = ReverseServer.MakeServerAddress(); Logger.logger.Log($"Server name is '{serverName}'"); var server = new ReverseServer(serverName); using var memoryStream1 = new MemoryStream(); using var memoryStream2 = new MemoryStream(); using var memoryStream3 = new MemoryStream(); Task <bool> subprocessTask = Utils.RunSubprocess( currentAssembly: Assembly.GetExecutingAssembly(), environment: new Dictionary <string, string> { { Utils.DiagnosticPortsEnvKey, $"{serverName}" } }, duringExecution: async(pid) => { Process currentProcess = Process.GetCurrentProcess(); Stream stream = await server.AcceptAsync(); IpcAdvertise advertise = IpcAdvertise.Parse(stream); Logger.logger.Log(advertise.ToString()); Logger.logger.Log($"Get ProcessInfo while process is suspended"); // 0x04 = ProcessCommandSet, 0x04 = ProcessInfo2 var message = new IpcMessage(0x04, 0x04); Logger.logger.Log($"Sent: {message.ToString()}"); IpcMessage response = IpcClient.SendMessage(stream, message); Logger.logger.Log($"received: {response.ToString()}"); ProcessInfo2 pi2Before = ProcessInfo2.TryParse(response.Payload); Utils.Assert(pi2Before.Commandline.Equals(currentProcess.MainModule.FileName), $"Before resuming, the commandline should be the mock value of the host executable path '{currentProcess.MainModule.FileName}'. Observed: '{pi2Before.Commandline}'"); // recycle stream = await server.AcceptAsync(); advertise = IpcAdvertise.Parse(stream); Logger.logger.Log(advertise.ToString()); // Start EP session to know when runtime is resumed var config = new SessionConfiguration( circularBufferSizeMB: 1000, format: EventPipeSerializationFormat.NetTrace, providers: new List <Provider> { new Provider("Microsoft-Windows-DotNETRuntimePrivate", 0x80000000, EventLevel.Verbose), new Provider("Microsoft-DotNETCore-SampleProfiler") }); Logger.logger.Log("Starting EventPipeSession over standard connection"); using Stream eventStream = EventPipeClient.CollectTracing(pid, config, out var sessionId); Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId:x}"); TaskCompletionSource <bool> runtimeResumed = new(false, TaskCreationOptions.RunContinuationsAsynchronously); var eventPipeTask = Task.Run(() => { Logger.logger.Log("Creating source"); using var source = new EventPipeEventSource(eventStream); var parser = new ClrPrivateTraceEventParser(source); parser.StartupEEStartupStart += (_) => runtimeResumed.SetResult(true); source.Process(); Logger.logger.Log("stopping processing"); }); Logger.logger.Log($"Send ResumeRuntime Diagnostics IPC Command"); // send ResumeRuntime command (0x04=ProcessCommandSet, 0x01=ResumeRuntime commandid) message = new IpcMessage(0x04, 0x01); Logger.logger.Log($"Sent: {message.ToString()}"); response = IpcClient.SendMessage(stream, message); Logger.logger.Log($"received: {response.ToString()}"); // recycle stream = await server.AcceptAsync(); advertise = IpcAdvertise.Parse(stream); Logger.logger.Log(advertise.ToString()); // wait a little bit to make sure the runtime of the target is fully up, i.e., g_EEStarted == true // on resource constrained CI machines this may not be instantaneous Logger.logger.Log($"awaiting resume"); await Utils.WaitTillTimeout(runtimeResumed.Task, TimeSpan.FromSeconds(10)); Logger.logger.Log($"resumed"); // await Task.Delay(TimeSpan.FromSeconds(1)); Logger.logger.Log("Stopping EventPipeSession over standard connection"); EventPipeClient.StopTracing(pid, sessionId); Logger.logger.Log($"Await reader task"); await eventPipeTask; Logger.logger.Log("Stopped EventPipeSession over standard connection"); ProcessInfo2 pi2After = default; // The timing is not exact. There is a small window after resuming where the mock // value is still present. Retry several times to catch it. var retryTask = Task.Run(async() => { int i = 0; do { Logger.logger.Log($"Get ProcessInfo after resumption: attempt {i++}"); // 0x04 = ProcessCommandSet, 0x04 = ProcessInfo2 message = new IpcMessage(0x04, 0x04); Logger.logger.Log($"Sent: {message.ToString()}"); response = IpcClient.SendMessage(stream, message); Logger.logger.Log($"received: {response.ToString()}"); pi2After = ProcessInfo2.TryParse(response.Payload); // recycle stream = await server.AcceptAsync(); advertise = IpcAdvertise.Parse(stream); Logger.logger.Log(advertise.ToString()); } while (pi2After.Commandline.Equals(pi2Before.Commandline)); }); await Utils.WaitTillTimeout(retryTask, TimeSpan.FromSeconds(10)); Utils.Assert(!pi2After.Commandline.Equals(pi2Before.Commandline), $"After resuming, the commandline should be the correct value. Observed: Before='{pi2Before.Commandline}' After='{pi2After.Commandline}'"); } ); fSuccess &= await subprocessTask; return(fSuccess); }
public static async Task <bool> TEST_CanStartAndStopSessionWhilepaused() { bool fSuccess = true; string serverName = ReverseServer.MakeServerAddress(); Logger.logger.Log($"Server name is '{serverName}'"); var server = new ReverseServer(serverName); using var memoryStream1 = new MemoryStream(); using var memoryStream2 = new MemoryStream(); using var memoryStream3 = new MemoryStream(); Task <bool> subprocessTask = Utils.RunSubprocess( currentAssembly: Assembly.GetExecutingAssembly(), environment: new Dictionary <string, string> { { Utils.DiagnosticPortsEnvKey, $"{serverName}" } }, duringExecution: async(pid) => { Stream stream = await server.AcceptAsync(); IpcAdvertise advertise = IpcAdvertise.Parse(stream); Logger.logger.Log(advertise.ToString()); var config = new SessionConfiguration( circularBufferSizeMB: 1000, format: EventPipeSerializationFormat.NetTrace, providers: new List <Provider> { new Provider("Microsoft-Windows-DotNETRuntime", UInt64.MaxValue, EventLevel.Verbose) }); Logger.logger.Log("Starting EventPipeSession over standard connection"); using Stream eventStream1 = EventPipeClient.CollectTracing(pid, config, out var sessionId1); Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId1:x}"); Task readerTask1 = eventStream1.CopyToAsync(memoryStream1); Logger.logger.Log("Starting EventPipeSession over standard connection"); using Stream eventStream2 = EventPipeClient.CollectTracing(pid, config, out var sessionId2); Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId2:x}"); Task readerTask2 = eventStream2.CopyToAsync(memoryStream2); Logger.logger.Log("Starting EventPipeSession over standard connection"); using Stream eventStream3 = EventPipeClient.CollectTracing(pid, config, out var sessionId3); Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId3:x}"); Task readerTask3 = eventStream3.CopyToAsync(memoryStream3); await Task.Delay(TimeSpan.FromSeconds(1)); Logger.logger.Log("Stopping EventPipeSession over standard connection"); EventPipeClient.StopTracing(pid, sessionId1); EventPipeClient.StopTracing(pid, sessionId2); EventPipeClient.StopTracing(pid, sessionId3); await readerTask1; await readerTask2; await readerTask3; Logger.logger.Log("Stopped EventPipeSession over standard connection"); Logger.logger.Log($"Send ResumeRuntime Diagnostics IPC Command"); // send ResumeRuntime command (0x04=ProcessCommandSet, 0x01=ResumeRuntime commandid) var message = new IpcMessage(0x04, 0x01); Logger.logger.Log($"Sent: {message.ToString()}"); IpcMessage response = IpcClient.SendMessage(stream, message); Logger.logger.Log($"received: {response.ToString()}"); } ); fSuccess &= await subprocessTask; return(fSuccess); }
public static async Task <bool> TEST_MultipleSessionsCanBeStartedWhilepaused() { bool fSuccess = true; string serverName = ReverseServer.MakeServerAddress(); Logger.logger.Log($"Server name is '{serverName}'"); var server = new ReverseServer(serverName); using var memoryStream1 = new MemoryStream(); using var memoryStream2 = new MemoryStream(); using var memoryStream3 = new MemoryStream(); Task <bool> subprocessTask = Utils.RunSubprocess( currentAssembly: Assembly.GetExecutingAssembly(), environment: new Dictionary <string, string> { { Utils.DiagnosticsMonitorAddressEnvKey, serverName } }, duringExecution: async(pid) => { Stream stream = await server.AcceptAsync(); IpcAdvertise advertise = IpcAdvertise.Parse(stream); Logger.logger.Log(advertise.ToString()); var config = new SessionConfiguration( circularBufferSizeMB: 1000, format: EventPipeSerializationFormat.NetTrace, providers: new List <Provider> { new Provider("Microsoft-Windows-DotNETRuntimePrivate", 0x80000000, EventLevel.Verbose) }); Logger.logger.Log("Starting EventPipeSession over standard connection"); using Stream eventStream1 = EventPipeClient.CollectTracing(pid, config, out var sessionId1); Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId1:x}"); Task readerTask1 = eventStream1.CopyToAsync(memoryStream1); Logger.logger.Log("Starting EventPipeSession over standard connection"); using Stream eventStream2 = EventPipeClient.CollectTracing(pid, config, out var sessionId2); Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId2:x}"); Task readerTask2 = eventStream2.CopyToAsync(memoryStream2); Logger.logger.Log("Starting EventPipeSession over standard connection"); using Stream eventStream3 = EventPipeClient.CollectTracing(pid, config, out var sessionId3); Logger.logger.Log($"Started EventPipeSession over standard connection with session id: 0x{sessionId3:x}"); Task readerTask3 = eventStream3.CopyToAsync(memoryStream3); Logger.logger.Log($"Send ResumeRuntime Diagnostics IPC Command"); // send ResumeRuntime command (0xFF=ServerCommandSet, 0x01=ResumeRuntime commandid) var message = new IpcMessage(0xFF, 0x01); Logger.logger.Log($"Sent: {message.ToString()}"); IpcMessage response = IpcClient.SendMessage(stream, message); Logger.logger.Log($"received: {response.ToString()}"); await Task.Delay(TimeSpan.FromSeconds(2)); Logger.logger.Log("Stopping EventPipeSession over standard connection"); EventPipeClient.StopTracing(pid, sessionId1); EventPipeClient.StopTracing(pid, sessionId2); EventPipeClient.StopTracing(pid, sessionId3); await readerTask1; await readerTask2; await readerTask3; Logger.logger.Log("Stopped EventPipeSession over standard connection"); } ); fSuccess &= await Utils.WaitTillTimeout(subprocessTask, TimeSpan.FromMinutes(1)); int nStartupEventsSeen = 0; memoryStream1.Seek(0, SeekOrigin.Begin); using (var source = new EventPipeEventSource(memoryStream1)) { var parser = new ClrPrivateTraceEventParser(source); parser.StartupEEStartupStart += (eventData) => nStartupEventsSeen++; source.Process(); } memoryStream2.Seek(0, SeekOrigin.Begin); using (var source = new EventPipeEventSource(memoryStream2)) { var parser = new ClrPrivateTraceEventParser(source); parser.StartupEEStartupStart += (eventData) => nStartupEventsSeen++; source.Process(); } memoryStream3.Seek(0, SeekOrigin.Begin); using (var source = new EventPipeEventSource(memoryStream3)) { var parser = new ClrPrivateTraceEventParser(source); parser.StartupEEStartupStart += (eventData) => nStartupEventsSeen++; source.Process(); } Logger.logger.Log($"nStartupEventsSeen: {nStartupEventsSeen}"); return(nStartupEventsSeen == 3 && fSuccess); }