/// <summary> /// Set a profiler as the startup profiler. It is only valid to issue this command /// while the runtime is paused in the "reverse server" mode. /// </summary> /// <param name="profilerGuid">Guid for the profiler to be attached</param> /// <param name="profilerPath">Path to the profiler to be attached</param> public void SetStartupProfiler(Guid profilerGuid, string profilerPath) { if (profilerGuid == null || profilerGuid == Guid.Empty) { throw new ArgumentException($"{nameof(profilerGuid)} must be a valid Guid"); } if (String.IsNullOrEmpty(profilerPath)) { throw new ArgumentException($"{nameof(profilerPath)} must be non-null"); } byte[] serializedConfiguration = SerializePayload(profilerGuid, profilerPath); var message = new IpcMessage(DiagnosticsServerCommandSet.Profiler, (byte)ProfilerCommandId.StartupProfiler, serializedConfiguration); var response = IpcClient.SendMessage(_endpoint, message); switch ((DiagnosticsServerResponseId)response.Header.CommandId) { case DiagnosticsServerResponseId.Error: uint hr = BitConverter.ToUInt32(response.Payload, 0); if (hr == (uint)DiagnosticsIpcError.UnknownCommand) { throw new UnsupportedCommandException("The target runtime does not support the ProfilerStartup command."); } else if (hr == (uint)DiagnosticsIpcError.InvalidArgument) { throw new ServerErrorException("The runtime must be suspended to issue the SetStartupProfiler command."); } throw new ServerErrorException($"Profiler startup failed (HRESULT: 0x{hr:X8})"); case DiagnosticsServerResponseId.OK: return; default: throw new ServerErrorException($"Profiler startup failed - server responded with unknown command"); } }
/// <summary> /// Trigger a core dump generation. /// </summary> /// <param name="dumpType">Type of the dump to be generated</param> /// <param name="dumpPath">Full path to the dump to be generated. By default it is /tmp/coredump.{pid}</param> /// <param name="flags">logging and crash report flags. On runtimes less than 6.0, only LoggingEnabled is supported.</param> /// <param name="token">The token to monitor for cancellation requests.</param> public async Task WriteDumpAsync(DumpType dumpType, string dumpPath, WriteDumpFlags flags, CancellationToken token) { IpcMessage request = CreateWriteDumpMessage(DumpCommandId.GenerateCoreDump3, dumpType, dumpPath, flags); IpcMessage response = await IpcClient.SendMessageAsync(_endpoint, request, token).ConfigureAwait(false); if (!ValidateResponseMessage(response, "Write dump", ValidateResponseOptions.UnknownCommandReturnsFalse | ValidateResponseOptions.ErrorMessageReturned)) { request = CreateWriteDumpMessage(DumpCommandId.GenerateCoreDump2, dumpType, dumpPath, flags); response = await IpcClient.SendMessageAsync(_endpoint, request, token).ConfigureAwait(false); if (!ValidateResponseMessage(response, "Write dump", ValidateResponseOptions.UnknownCommandReturnsFalse)) { if ((flags & ~WriteDumpFlags.LoggingEnabled) != 0) { throw new ArgumentException($"Only {nameof(WriteDumpFlags.LoggingEnabled)} flag is supported by this runtime version", nameof(flags)); } request = CreateWriteDumpMessage(dumpType, dumpPath, logDumpGeneration: (flags & WriteDumpFlags.LoggingEnabled) != 0); response = await IpcClient.SendMessageAsync(_endpoint, request, token).ConfigureAwait(false); ValidateResponseMessage(response, "Write dump"); } } }
/// <summary> /// Attach a profiler. /// </summary> /// <param name="attachTimeout">Timeout for attaching the profiler</param> /// <param name="profilerGuid">Guid for the profiler to be attached</param> /// <param name="profilerPath">Path to the profiler to be attached</param> /// <param name="additionalData">Additional data to be passed to the profiler</param> public void AttachProfiler(TimeSpan attachTimeout, Guid profilerGuid, string profilerPath, byte[] additionalData = null) { if (profilerGuid == null || profilerGuid == Guid.Empty) { throw new ArgumentException($"{nameof(profilerGuid)} must be a valid Guid"); } if (String.IsNullOrEmpty(profilerPath)) { throw new ArgumentException($"{nameof(profilerPath)} must be non-null"); } byte[] serializedConfiguration = SerializeProfilerAttach((uint)attachTimeout.TotalSeconds, profilerGuid, profilerPath, additionalData); var message = new IpcMessage(DiagnosticsServerCommandSet.Profiler, (byte)ProfilerCommandId.AttachProfiler, serializedConfiguration); var response = IpcClient.SendMessage(_endpoint, message); switch ((DiagnosticsServerResponseId)response.Header.CommandId) { case DiagnosticsServerResponseId.Error: uint hr = BitConverter.ToUInt32(response.Payload, 0); if (hr == (uint)DiagnosticsIpcError.UnknownCommand) { throw new UnsupportedCommandException("The target runtime does not support profiler attach"); } throw new ServerErrorException($"Profiler attach failed (HRESULT: 0x{hr:X8})"); case DiagnosticsServerResponseId.OK: return; default: throw new ServerErrorException($"Profiler attach failed - server responded with unknown command"); } // The call to set up the pipe and send the message operates on a different timeout than attachTimeout, which is for the runtime. // We should eventually have a configurable timeout for the message passing, potentially either separately from the // runtime timeout or respect attachTimeout as one total duration. }
private static IpcMessage Read(Stream stream) { return(IpcMessage.Parse(stream)); }
private static void Write(Stream stream, IpcMessage message) { Write(stream, message.Serialize()); }
private static void Write(Stream stream, IpcMessage message) { byte[] buffer = message.Serialize(); stream.Write(buffer, 0, buffer.Length); }
/// <summary> /// Sends a single DiagnosticsIpc Message to the dotnet process associated with the <paramref name="endpoint"/>. /// </summary> /// <param name="endpoint">An endpoint that provides a diagnostics connection to a runtime instance.</param> /// <param name="message">The DiagnosticsIpc Message to be sent</param> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> /// <returns>An <see cref="IpcResponse"/> containing the response message and continuation stream.</returns> public static async Task <IpcResponse> SendMessageGetContinuationAsync(IpcEndpoint endpoint, IpcMessage message, CancellationToken cancellationToken) { Stream stream = null; try { stream = await endpoint.ConnectAsync(cancellationToken).ConfigureAwait(false); await WriteAsync(stream, message, cancellationToken).ConfigureAwait(false); IpcMessage response = await ReadAsync(stream, cancellationToken).ConfigureAwait(false); return(new IpcResponse(response, Release(ref stream))); } finally { stream?.Dispose(); } }
/// <summary> /// Sends a single DiagnosticsIpc Message to the dotnet process associated with the <paramref name="endpoint"/>. /// </summary> /// <param name="endpoint">An endpoint that provides a diagnostics connection to a runtime instance.</param> /// <param name="message">The DiagnosticsIpc Message to be sent</param> /// <param name="cancellationToken">The token to monitor for cancellation requests.</param> /// <returns>An <see cref="IpcMessage"/> that is the response message.</returns> public static async Task <IpcMessage> SendMessageAsync(IpcEndpoint endpoint, IpcMessage message, CancellationToken cancellationToken) { using IpcResponse response = await SendMessageGetContinuationAsync(endpoint, message, cancellationToken).ConfigureAwait(false); return(response.Message); }
/// <summary> /// Sends a single DiagnosticsIpc Message to the dotnet process associated with the <paramref name="endpoint"/>. /// </summary> /// <param name="endpoint">An endpoint that provides a diagnostics connection to a runtime instance.</param> /// <param name="message">The DiagnosticsIpc Message to be sent</param> /// <returns>An <see cref="IpcMessage"/> that is the response message.</returns> public static IpcMessage SendMessage(IpcEndpoint endpoint, IpcMessage message) { using IpcResponse response = SendMessageGetContinuation(endpoint, message); return(response.Message); }
private static Task <IpcMessage> ReadAsync(Stream stream, CancellationToken cancellationToken) { return(IpcMessage.ParseAsync(stream, cancellationToken)); }
private static Task WriteAsync(Stream stream, IpcMessage message, CancellationToken cancellationToken) { byte[] buffer = message.Serialize(); return(stream.WriteAsync(buffer, 0, buffer.Length, cancellationToken)); }
public IpcResponse(IpcMessage message, Stream continuation) { Message = message; Continuation = continuation; }