在进程崩溃的时候自动抓取一个DUMP文件

在如下的情况下需要使用这样的技巧:

1. 生产环境上出问题, 我们需要抓取dump文件, 在线下去debug.

2. 正在运行一大堆测试, 当其中一个崩溃的时候, 不希望在运行时干扰整个测试动作, 仅需要收集一些测试信息.

3. 问题在连接到debugger后无法重现.

 

简单来说, 就是你希望在对环境影响最小的前提下, 抓取尽可能多的信息.

 

为了满足这种需求, 最好的方式是配置 just-in-time (JIT) debugger , 让它在进程崩溃的任何时候能够: 启动, 抓取dump, 退出.

 

JIT debugger的基本思想是:当一个进程崩溃的时候,加载debugger, attach debugger到进程上, 以便我们弄清楚为什么会崩溃.

 

有注册表键值可以提供这项基本的功能, 针对托管的, 非托管的都有. 如果你的应用程序是用托管代码编写的, 你也许会问, "我的应用程序是托管代码, 为什么我要关心native code?" 即使是给你最基本的托管代码应用程序都会运行native code, 如果你的需求是收集任何crash的数据, 你将需要为这两种类型的代码设置注册表键值. 在CLR第四版中, 已经定义了带有native code的托管JIT debugger. 然而, 这个修改并不影响我这里的指导, 这里, V2 V4都适用.

 

我如何配置debugger?

=====================

1. 下载并安装最新的“Debugging Tools for Windows.”

        a. 如果你是在运行64-bit OS, 你将会需要32-Bit and 64-bit 两个版本.

        b. 你在机器上既可以安装整个的工具集(这很快, 安装很小), 或者你可以在一台机器上安装, 然后从安装路径拷贝"cdb.exe"到任何目标机器上.

 

注意, 下面的sample.reg文件假设你安装32位debugger到c:\debuggers\x86\下, 64位debugger到c:\debuggers\x64\ 下

 

2. 创建或配置下面的注册表键和值(如果你使用的是64位版的windows, 你还需要在Wow6432节点下配置这些值)

        a. 键: HKLM\Software\Microsoft\Windows NT\Current Version\AeDebug:

                    i. 值: "Debugger"

                               1. 类型: String

                               2. 值数据: <path to cdb> -pv -p %ld -c “.dump /u /ma <dump file path\name.dmp>;.kill;qd"

                   ii. 值:  “Auto”

                               1. 类型: String

                               2. 值数据: "1"

 

        b. 键: HKLM\Software\Microsoft\.NETFramework

                   i. 值: “DbgManagedDebugger"

                               1. 类型: String

                               2. 值数据: <path to cdb> -pv -p %ld -c ".dump /u /ma <dump file path\name.dmp>;.kill;qd"

                  ii. 值: "DbgJITDebugLaunchSetting"

                               1. 类型: DWORD(32-bit)

                               2. 值数据: 2

 

注意: 你应该根据合适的debugger的位数, 比如说, 你想要OS/CLR为64位进程崩溃加载64位的debugger, 32位的进程崩溃加载32为的debugger. 请确保你的debugger的路径是被正确地设置了的.

 

下面的sample.reg文件会配置机器上的cdb.exe为自动加载, 并在每个进程崩溃的时候生成一个crash dump文件. 注意文件中的关于debugger路径和dump文件存放路径的假设.

 

Windows Registry Editor Version 5.00

;This reg file installs just-in-time debuggers to capture a dump of all process
;crashes for the machine.

;

;Assumes 32-bit debugger is cdb.exe and is installed to c:\debuggers\x86\.

;Assumes 64-bit debugger is cdb.exe and is installed to c:\debuggers\x64\.

;

;Assumes crash dumps can be written to c:\crash_dumps\.

;Make sure all users have write access to this directory.

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework]

"DbgManagedDebugger"="\"c:\\debuggers\\x64\\cdb.exe\" -pv -p %ld -c \".dump /u /ma c:\\crash_dumps\\crash.dmp;.kill;qd\""

"DbgJITDebugLaunchSetting"=dword:00000002

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug]

"Debugger"="\"c:\\debuggers\\x64\\cdb.exe\" -pv -p %ld -c \".dump /u /ma c:\\crash_dumps\\crash.dmp;.kill;qd\""

"Auto"="1"

;The following keys are only used on 64-bit versions of Windows (note Wow6432Node).

;They can be safely created with no side-effects on 32-bit versions of Windows.

;Alternatively, you can delete the remainder of this file if you’re running a

;32-bit version of Windows.

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug]

"Debugger"="\"c:\\debuggers\\x86\\cdb.exe\" -pv -p %ld -c \".dump /u /ma c:\\crash_dumps\\crash.dmp;.kill;qd\""

"Auto"="1"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework]

"DbgManagedDebugger"="\"c:\\debuggers\\x86\\cdb.exe\" -pv -p %ld -c \".dump /u /ma c:\\crash_dumps\\crash.dmp;.kill;qd\""

"DbgJITDebugLaunchSetting"=dword:00000002

 

这些键值有什么作用?

=====================

“Debugger” 和“DbgManagedDebugger” 的值数据基本上就是在进程崩溃的时候运行的命令行(printf格式的字符串). OS 或者 CLR 用实际值替代掉其中的格式指示符, 然后使用当前用户的崩溃进程的上下文来运行命令. 比如说, 会用崩溃的process id去替换掉 "%ld".

在命令行中, 我指定了:

  • 加载cdb.exel, 也就是debugger
    • 很显然, 你必须为debugger指定正确的路径
  • “-pv %ld” : 非侵入性地(仅仅是把线程暂停)挂接到崩溃的进程上(操作系统或CLR会实质上地帮你添写PID)
  • “.dump /u /ma <dump file path\name.dmp>”: 拿下完整的内存dump, 使用一个独一无二的名字(使用日期, 时间, 和进程ID来扩展名称), 把它保存到指定的路径
    • 路径和文件名可以是任何你想指定的形式. 因为debugger是在崩溃的进程的上下文中加载的, 所以你要确保你指定的路径是任何用户都有权限写入的
  • “.kill”: 干掉目标进程, 因为你已经得到了你需要的数据.
  • “qd”: 离开debugger

“Auto” 和“DbgJITDebugLaunchSetting”的值设定了何时加载debugger的策略规则(policy). 正如我上面写道的, 我们希望尽快地得到数据, 并继续, 所以我们不希望用户干预的介入. 比如说, 在一个服务器上, 可能不会有人登录并点击什么OK按钮. 我描述的配置会自动地为机器上的所有进程加载注册了的debugger, 而不会弹出框来让你选择(参考Enabling JIT-attach Debugging, 其中有关于弹这个框的更多信息). 注意, 当这些配置存在了之后, 机器上运行的所有进程在崩溃的时候都会自动地加载起debugger, 从而不会让你有机会去在"Windows Error Reporting"里呈交这个crash.

 

我不在乎一台机器上的绝大多数的进程, 我可以只抓取某一个进程的crash dump么?

====================

这个问题的答案取决于你OS的版本, 还有CLR的版本. 下面是规则:

  • 对于native code来说: 你的OS必须是Vista/Server 2008 或者更高.
  • 对于managed code来说: 你的CLR的版本必须是V4(或者更高)

下面是如何配置的方法:

1. 如同上面的2.a.i 和2.b.i一样, 配置debugger键值. (AeDebug\Debugger 和.NETFramework\DbgManagedDebugger)

2. 确保AeDebug\Auto 和.NETFramework\DbgJITDebugLaunchSetting 已经被配置为自动加载(再一次强调, 参考Enabling JIT-attach Debugging 来查找更多信息).

                     a. 或者你可以删除它们Or you can delete them.

3. 创建如下的注册表键值对Create the following registry keys and values:

                     a. HKLM\Software\Microsoft\Windows\Windows Error Reporting\DebugApplications

                                     i. 值: <Name of application executable> (e.g. “myapp.exe”)

                                                   1. 类型: DWORD (32-bit)

                                                   2. 值数据: 1

                     b. 为每一个你希望debugger自动加载的应用程序重复这个操作.

 

如果你更喜欢个人的控制, 你可以配置HKCU中的DebugApplications 键值对. 当这些配置生效的时候, debugger会仅为你指定的进程加载起来, 而其他进程所使用的会是普通的错误处理方式(比如说, 最默认的配置下, 会弹出一个框, 让你提交这个错误到微软去.)

 

下面的例子中的sample.reg文件, 会配置cdb.exe为自动加载的, 但仅仅是为HelloWorld.exe. 你可以替代HelloWorld.exe为你想要抓取dump的进程.

Windows Registry Editor Version 5.00

;This reg file installs just-in-time debuggers to capture a dump of only the
;processes listed under the [DebugApplications] key, below.

;

;Assumes 32-bit debugger is cdb.exe and is installed to c:\debuggers\x86\.

;Assumes 64-bit debugger is cdb.exe and is installed to c:\debuggers\x64\.

;

;Assumes crash dumps can be written to c:\crash_dumps\.

;Make sure all users have write access to this directory.

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework]

"DbgManagedDebugger"="\"c:\\debuggers\\x64\\cdb.exe\" -pv -p %ld -c \".dump /u /ma c:\\crash_dumps\\crash.dmp;.kill;qd\""

"DbgJITDebugLaunchSetting"=dword:00000000

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug]

"Debugger"="\"c:\\debuggers\\x64\\cdb.exe\" -pv -p %ld -c \".dump /u /ma c:\\crash_dumps\\crash.dmp;.kill;qd\""

"Auto"="0"

;The following keys are only used on 64-bit versions of Windows (note Wow6432Node).

;They can be safely created with no side-effects on 32-bit versions of Windows.

;Alternatively, you can delete the remainder of this file if you’re running a

;32-bit version of Windows.

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\AeDebug]

"Debugger"="\"c:\\debuggers\\x86\\cdb.exe\" -pv -p %ld -c \".dump /u /ma c:\\crash_dumps\\crash.dmp;.kill;qd\""

"Auto"="0"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework]

"DbgManagedDebugger"="\"c:\\debuggers\\x86\\cdb.exe\" -pv -p %ld -c \".dump /u /ma c:\\crash_dumps\\crash.dmp;.kill;qd\""

"DbgJITDebugLaunchSetting"=dword:00000000

;For each application you want the debugger to be auto-launched, add a row below

;similar to “HelloWorld.exe"=dword:00000001 but replacing HelloWorld.exe with

;your application .exe name.

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\DebugApplications]

"HelloWorld.exe"=dword:00000001

 

除了抓dump, 我还可以做更多的事情么?

=========================

关于Windows Debugger是的命令行开关的更多的信息, 可以在Debugging Tools fow Windows中包括的文档中找到. 你并没有被限制仅仅抓取dump, 你还可以执行很多debugger的自动化操作呢.

 

嗯, 那么究竟是什么导致了问题发生?

========================

现在, 你已经有了dump文件, 是时候来弄清楚为什么应用程序崩溃了. 对于那些已经熟悉了dump debugging的读者, 到这里你就拉出WinDBG + SOS(托管debugging的扩展组件), 并深入研究了. 但是请等一下! 如果你的应用程序运行在CLR V4上(.Net Framework 4.0), 你可以在Visual Studio 2010中进行debug了. 我们的目标是在VS2010中, debug dump像live debug一样的体验(如同走到了断点).

 

针对如何debug托管代码的crash, 搜索"managed dump debugging"会返回不少结果. 一个很好的初学者去处是Tess Ferrandez’s blog (一个微软的技术支持大牛). 她有不少关于这个话题的精彩文章, 包括dump debugging in VS 2010, 还有一些实验, 手把手的文章.

 

 

Automatically Capturing a Dump When a Process Crashes

http://blogs.msdn.com/clrteam/archive/2009/10/15/automatically-capturing-a-dump-when-a-process-crashes.aspx

Enabling JIT-attach Debugging

http://msdn.microsoft.com/en-us/library/2ac5yxx6(VS.80).aspx

posted on 2010-03-08 22:10  中道学友  阅读(11536)  评论(0编辑  收藏  举报

导航

技术追求准确,态度积极向上