예제 #1
0
        //////////////////////////////////////////////////////////////////////////////////
        //
        // Private Implementation part
        //
        //////////////////////////////////////////////////////////////////////////////////

        private void ConsoleBreakHandler(Object sender, ConsoleCancelEventArgs e)
        {
            // When Control+C is pressed, the Console.Readline() returns immediatelly with
            // null. There is no way how to distinguish between EOF and Ctrl+C. Therefore we set
            // a m_isConsoleBreakHandlerExecuted to true whenever the handler is executed.
            // The code around Console.ReadLine() check when null is returned if the
            // m_isConsoleBreakHandlerExecuted flag is set. If yes, we know that this is caused by
            // Ctrl+C, the code clrears the flag and repeats the read.

            m_isConsoleBreakHandlerExecuted = true;

            switch (e.SpecialKey)
            {
            case ConsoleSpecialKey.ControlBreak:
                Console.WriteLine();
                WriteOutput(MDbgOutputConstants.StdError,
                            "Immediate debugger termination reqested through <Ctrl+Break>");
                WriteOutput(MDbgOutputConstants.StdError, "To break into debugger use Ctrl+C instead.");
                //
                // When ControlBreak is pressed, we cannot set e.Cancel=true....
                //
                break;

            case ConsoleSpecialKey.ControlC:
                try
                {
                    WriteOutput(MDbgOutputConstants.StdOutput, "\n<Ctrl+C>");
                    MDbgProcess p = m_shell.Debugger.Processes.Active;
                    if (p.IsRunning)
                    {
                        p.AsyncStop().WaitOne();
                    }
                }
                catch
                {
                }
                e.Cancel = true;
                break;

            default:
                break;
            }
        }
예제 #2
0
        protected virtual void Dispose(bool disposing)
        {
            // 防止被多次调用
            if (disposed)
            {
                return;
            }

            if (disposing)
            {
                // 清除所有托管资源
                if (_mdbgProcess != null)
                {
                    // 确保基本进程在datach前已经终止了
                    var waithandler = _mdbgProcess.AsyncStop();
                    waithandler.WaitOne();
                    _mdbgProcess.Detach();
                }
            }

            disposed = true;
        }
예제 #3
0
        protected virtual void Dispose(bool disposing)
        {
            // Protect from being called multiple times.
            if (disposed)
            {
                return;
            }

            if (disposing)
            {
                // Clean up all managed resources.
                if (_mdbgProcess != null)
                {
                    // Make sure the underlying CorProcess was stopped before
                    // detached it.
                    var waithandler = _mdbgProcess.AsyncStop();
                    waithandler.WaitOne();
                    _mdbgProcess.Detach();
                }
            }

            disposed = true;
        }
예제 #4
0
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                Usage();
                return;
            }

            int samples        = 10;
            int sampleInterval = 1000;


            var state = ParseState.Unknown;

            foreach (var arg in args.Skip(1))
            {
                switch (state)
                {
                case ParseState.Unknown:
                    if (arg.ToLower() == "/s")
                    {
                        state = ParseState.Samples;
                    }
                    else if (arg.ToLower() == "/i")
                    {
                        state = ParseState.Interval;
                    }
                    else
                    {
                        Usage();
                        return;
                    }
                    break;

                case ParseState.Samples:
                    if (!Int32.TryParse(arg, out samples))
                    {
                        Usage();
                        return;
                    }
                    state = ParseState.Unknown;
                    break;

                case ParseState.Interval:
                    if (!Int32.TryParse(arg, out sampleInterval))
                    {
                        Usage();
                        return;
                    }
                    state = ParseState.Unknown;
                    break;

                default:
                    break;
                }
            }

            string pidOrProcess = args[0];


            var stats    = new Dictionary <int, List <ThreadSnapshot> >();
            var debugger = new MDbgEngine();
            int pid      = -1;

            var processes = Process.GetProcessesByName(pidOrProcess);

            if (processes.Length < 1)
            {
                try {
                    pid = Int32.Parse(pidOrProcess);
                } catch {
                    Console.WriteLine("Error: could not find any processes with that name or pid");
                    return;
                }
            }
            else
            {
                if (processes.Length > 1)
                {
                    Console.WriteLine("Warning: multiple processes share that name, attaching to the first");
                }
                pid = processes[0].Id;
            }


            MDbgProcess attached = null;

            try {
                attached = debugger.Attach(pid);
            } catch (Exception e) {
                Console.WriteLine("Error: failed to attach to process: " + e);
                return;
            }

            attached.Go().WaitOne();

            for (int i = 0; i < samples; i++)
            {
                foreach (MDbgThread thread in attached.Threads)
                {
                    var snapshot = ThreadSnapshot.GetThreadSnapshot(thread);
                    List <ThreadSnapshot> snapshots;
                    if (!stats.TryGetValue(snapshot.Id, out snapshots))
                    {
                        snapshots          = new List <ThreadSnapshot>();
                        stats[snapshot.Id] = snapshots;
                    }

                    snapshots.Add(snapshot);
                }

                attached.Go();
                Thread.Sleep(sampleInterval);
                attached.AsyncStop().WaitOne();
            }

            attached.Detach().WaitOne();

            // perform basic analysis to see which are the top N stack traces observed,
            //  weighted on cost

            Dictionary <Guid, long>   costs  = new Dictionary <Guid, long>();
            Dictionary <Guid, string> stacks = new Dictionary <Guid, string>();

            foreach (var stat in stats.Values)
            {
                long prevTime = -1;
                foreach (var snapshot in stat)
                {
                    long time = snapshot.KernelTime + snapshot.UserTime;
                    if (prevTime != -1)
                    {
                        foreach (var tuple in snapshot.StackHashes)
                        {
                            if (costs.ContainsKey(tuple.Item1))
                            {
                                costs[tuple.Item1] += time - prevTime;
                            }
                            else
                            {
                                costs[tuple.Item1]  = time - prevTime;
                                stacks[tuple.Item1] = tuple.Item2;
                            }
                        }
                    }
                    prevTime = time;
                }
            }

            Console.WriteLine("Most expensive stacks");
            Console.WriteLine("------------------------------------");
            foreach (var group in costs.OrderByDescending(p => p.Value).GroupBy(p => p.Value))
            {
                List <string> stacksToShow = new List <string>();

                foreach (var pair in group.OrderByDescending(p => stacks[p.Key].Length))
                {
                    if (!stacksToShow.Any(s => s.Contains(stacks[pair.Key])))
                    {
                        stacksToShow.Add(stacks[pair.Key]);
                    }
                }

                foreach (var stack in stacksToShow)
                {
                    Console.WriteLine(stack);
                    Console.WriteLine("===> Cost ({0})", group.Key);
                    Console.WriteLine();
                }
            }


            var offenders = stats.Values
                            .Select(_ => ThreadSnapshotStats.FromSnapshots(_))
                            .OrderBy(stat => stat.TotalKernelTime + stat.TotalUserTime)
                            .Reverse();

            foreach (var stat in offenders)
            {
                Console.WriteLine("------------------------------------");
                Console.WriteLine(stat.ThreadId);
                Console.WriteLine("Kernel: {0} User: {1}", stat.TotalKernelTime, stat.TotalUserTime);
                foreach (var method in stat.CommonStack)
                {
                    Console.WriteLine(method);
                }
                Console.WriteLine("Other Stacks:");
                var prev = new List <string>();
                foreach (var trace in stats[stat.ThreadId].Select(_ => _.StackTrace))
                {
                    if (!prev.SequenceEqual(trace))
                    {
                        Console.WriteLine();
                        foreach (var method in trace)
                        {
                            Console.WriteLine(method);
                        }
                    }
                    else
                    {
                        Console.WriteLine("<skipped>");
                    }
                    prev = trace;
                }
                Console.WriteLine("------------------------------------");
            }
        }