【发布时间】:2014-05-28 00:57:35
【问题描述】:
我们的一位客户在使用 .NET 编写的应用程序时遇到问题。它在进程开始后消耗整个 CPU,没有任何窗口可显示。它看起来像一个无限循环。
问题是,这个客户使用的是 Windows 7 Home Edition,这就是为什么我无法通过远程托管调试器连接到应用程序。
我可以创建带有一些调试模式的特殊版本。我认为我可以在进程的请求中运行一个线程,大约一分钟后调用 Debugger.Break 并以某种方式记录线程和堆栈帧。我不确定是否可以在所有线程上记录堆栈帧。
你有过这种不带调试器的调试经验吗?
更新:
经过两天的努力,我终于找到了问题所在。这是坏的 ATI 显卡驱动程序,导致了无限循环。因为有些组件使用 OpenGL。通过迭代当前进程的线程,将它们挂起并写入堆栈跟踪,很容易发现问题。我最终用来发现错误的代码如下:
using System;
using System.Diagnostics;
using System.Text;
using System.Threading;
public class DebuggerContext
{
public int TimeIntervalMs { get; set; }
public Thread InfiniteLoopThread { get; set; }
}
public static class InfiniteLogger
{
public static void LogInfniteLoopAfterTimeInterval(int timeIntervalMs)
{
Thread watchdog = new Thread(Watchdog);
DebuggerContext context = new DebuggerContext()
{
InfiniteLoopThread = Thread.CurrentThread,
TimeIntervalMs = timeIntervalMs,
};
watchdog.Start(context);
}
static void Watchdog(object threadContext)
{
DebuggerContext context = (DebuggerContext)threadContext;
Thread.Sleep(context.TimeIntervalMs);
LogThread(context.InfiniteLoopThread);
var threads = Process.GetCurrentProcess().Threads;
foreach (var thread in threads)
{
if (thread == Thread.CurrentThread)
continue;
LogThread(context.InfiniteLoopThread);
}
}
private static void LogThread(Thread thread)
{
thread.Suspend();
StackTrace stackTrace = new StackTrace(thread, true);
string log = "The infinite loop is in: " + StackTraceToString(stackTrace);
Trace.WriteLine(log);
thread.Resume();
}
/// <summary>
/// http://stackoverflow.com/questions/51768/print-stack-trace-information-from-c-sharp
/// </summary>
/// <returns></returns>
static string StackTraceToString(StackTrace stackTrace)
{
StringBuilder sb = new StringBuilder(256);
var frames = stackTrace.GetFrames();
for (int i = 0; i < frames.Length; i++) /* Ignore current StackTraceToString method...*/
{
var currFrame = frames[i];
var method = currFrame.GetMethod();
var line = currFrame.GetFileLineNumber();
var file = currFrame.GetFileName();
var column = currFrame.GetFileColumnNumber();
sb.AppendLine(string.Format("{0}:[{1},{2}], {3}.{4}",
file,
line,
column,
method.ReflectedType != null ? method.ReflectedType.Name : string.Empty,
method.Name
));
}
return sb.ToString();
}
}
[STAThread]
static void Main(string[] args)
{
InfiniteLogger.LogInfniteLoopAfterTimeInterval(30 * 1000); //log thread state after 30 seconds after start
....
}
【问题讨论】:
-
您检查应用程序日志了吗?也许根本不用调试就可以解决问题。
-
使用 mdbg 或 ProcessExplorer。
-
这个工具很棒。不幸的是,当我选择所需的进程时,它在客户的计算机上崩溃了。
-
是的,我检查了日志。没有什么有趣的...
标签: .net debugging infinite-loop