コード例 #1
0
        // <summary>
        // Starts the child process and returns the diagnostics client once the child proc connects to the reversed diagnostics pipe.
        // The callee needs to resume the diagnostics client at appropriate time.
        // </summary>
        public static DiagnosticsClient Build(ProcessLauncher childProcLauncher, string toolName, int timeoutInSec)
        {
            if (!childProcLauncher.HasChildProc)
            {
                throw new InvalidOperationException("Must have a valid child process to launch.");
            }
            // Create and start the reversed server
            string diagnosticTransportName   = GetTransportName(toolName);
            ReversedDiagnosticsServer server = new ReversedDiagnosticsServer(diagnosticTransportName);

            server.Start();

            // Start the child proc
            if (!childProcLauncher.Start(diagnosticTransportName))
            {
                throw new InvalidOperationException("Failed to start dotnet-counters.");
            }

            // Wait for attach
            IpcEndpointInfo endpointInfo = server.Accept(TimeSpan.FromSeconds(timeoutInSec));

            // If for some reason a different process attached to us, wait until the expected process attaches.
            while (endpointInfo.ProcessId != childProcLauncher.ChildProc.Id)
            {
                endpointInfo = server.Accept(TimeSpan.FromSeconds(timeoutInSec));
            }
            return(new DiagnosticsClient(endpointInfo.Endpoint));
        }
コード例 #2
0
 public DiagnosticsClientHolder(DiagnosticsClient client, IpcEndpointInfo endpointInfo, string port, ReversedDiagnosticsServer server)
 {
     Client       = client;
     EndpointInfo = endpointInfo;
     _port        = port;
     _server      = server;
 }
コード例 #3
0
        /// <summary>
        /// Starts listening to the reversed diagnostics server for new connections.
        /// </summary>
        /// <param name="maxConnections">The maximum number of connections the server will support.</param>
        public void Start(int maxConnections)
        {
            VerifyNotDisposed();

            if (IsListening)
            {
                throw new InvalidOperationException(nameof(ServerEndpointInfoSource.Start) + " method can only be called once.");
            }

            _server = new ReversedDiagnosticsServer(_transportPath);

            _listenTask = ListenAsync(maxConnections, _cancellation.Token);
        }
コード例 #4
0
        /// <summary>
        /// Starts listening to the reversed diagnostics server for new connections.
        /// </summary>
        /// <param name="maxConnections">The maximum number of connections the server will support.</param>
        public void Listen(int maxConnections)
        {
            VerifyNotDisposed();

            if (null != _server || null != _listenTask)
            {
                throw new InvalidOperationException(nameof(ServerEndpointInfoSource.Listen) + " method can only be called once.");
            }

            _server = new ReversedDiagnosticsServer(_transportPath, maxConnections);

            _listenTask = ListenAsync(_cancellation.Token);
        }
コード例 #5
0
        public async Task <DiagnosticsClientHolder> Build(CancellationToken ct, int processId, string portName, bool showChildIO, bool printLaunchCommand)
        {
            if (ProcessLauncher.Launcher.HasChildProc)
            {
                // Create and start the reversed server
                string diagnosticTransportName   = GetTransportName(_toolName);
                ReversedDiagnosticsServer server = new ReversedDiagnosticsServer(diagnosticTransportName);
                server.Start();

                // Start the child proc
                if (!ProcessLauncher.Launcher.Start(diagnosticTransportName, ct, showChildIO, printLaunchCommand))
                {
                    throw new InvalidOperationException($"Failed to start '{ProcessLauncher.Launcher.ChildProc.StartInfo.FileName} {ProcessLauncher.Launcher.ChildProc.StartInfo.Arguments}'.");
                }
                IpcEndpointInfo endpointInfo;
                try
                {
                    // Wait for attach
                    endpointInfo = server.Accept(TimeSpan.FromSeconds(_timeoutInSec));

                    // If for some reason a different process attached to us, wait until the expected process attaches.
                    while (endpointInfo.ProcessId != ProcessLauncher.Launcher.ChildProc.Id)
                    {
                        endpointInfo = server.Accept(TimeSpan.FromSeconds(_timeoutInSec));
                    }
                }
                catch (TimeoutException)
                {
                    Console.Error.WriteLine("Unable to start tracing session - the target app failed to connect to the diagnostics port. This may happen if the target application is running .NET Core 3.1 or older versions. Attaching at startup is only available from .NET 5.0 or later.");
                    throw;
                }
                return(new DiagnosticsClientHolder(new DiagnosticsClient(endpointInfo.Endpoint), endpointInfo, server));
            }
            else if (!string.IsNullOrEmpty(portName))
            {
                ReversedDiagnosticsServer server = new ReversedDiagnosticsServer(portName);
                server.Start();
                string fullPort = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? portName : Path.GetFullPath(portName);
                Console.WriteLine($"Waiting for connection on {fullPort}");
                Console.WriteLine($"Start an application with the following environment variable: DOTNET_DiagnosticPorts={fullPort}");

                IpcEndpointInfo endpointInfo = await server.AcceptAsync(ct);

                return(new DiagnosticsClientHolder(new DiagnosticsClient(endpointInfo.Endpoint), endpointInfo, fullPort, server));
            }
            else
            {
                return(new DiagnosticsClientHolder(new DiagnosticsClient(processId)));
            }
        }
コード例 #6
0
        public async Task RunRemoteServer()
        {
            var debuggee       = Path.GetFullPath(_debuggee);
            var diagnosticPort = $"Fusion_{Process.GetCurrentProcess().Id}";

            // 1. Start the diagnostic server
            ReversedDiagnosticsServer srv = new ReversedDiagnosticsServer(diagnosticPort);

            srv.Start();

            // 2. Start accepting connections
            using CancellationTokenSource cancellation = new CancellationTokenSource(20000);
            var acceptTask = srv.AcceptAsync(cancellation.Token);

            // 3. Run the debuggee
            Console.WriteLine("Starting child process using Diagnostic Port over Pipe");
            ProcessStartInfo psi = new(debuggee);

            psi.CreateNoWindow = false;
            psi.EnvironmentVariables[_diagPortEnvKey] = diagnosticPort;
            var process = Process.Start(psi);

            // 4. Wait for the remote CLR to connect with us
            var endpoint = await acceptTask;

            Console.WriteLine($"Remote process {endpoint.ProcessId} connected with cookie: {endpoint.RuntimeInstanceCookie}");


            // 5. Use the endpoint to start the diagnostic client
            using var fusion = new FusionTrace(endpoint.Endpoint);
            fusion.Start(e => SubscribeDynamicEvents(e), s => SubscribeRuntimeEvents(s));


            while (Console.ReadKey().Key != ConsoleKey.Q)
            {
                ;
            }
        }
コード例 #7
0
 public DiagnosticsClientHolder(DiagnosticsClient client)
 {
     Client  = client;
     _port   = null;
     _server = null;
 }