Windows下使用breakpad进行崩溃DUMP收集与分析


进程内与进程外的异常处理—— 进程内写minidump通常被认为是不安全的,关键处理数据结构可能已经被破坏,异常处理程序运行所处的堆栈或可能已经被覆盖,等等。所有3个平台都支持“进程外”异常处理。

进程外生成dump有很多好处,其中最大的好处就是不会被崩溃进程影响,这样dump的过程就不容易出错,但是这样也有一定的弊端。

1. 部分崩溃无法抓取
在一些极端的崩溃,如堆栈溢出之类的崩溃,进程外抓取dump有时候会失败。

2. 无法抓取死锁或者其他原因导致的进程僵死
breakpad现在没有检测进程死锁的代码,也没有在服务端控制客户端请求dump的代码,所以现在breakpad无法抓取死锁等进程僵死的问题。不过因为breakpad的定位是处理崩溃,如果有这种需要的童鞋,可以自行修改breakpad的代码,添加这些功能。

3. 对服务端有依赖
如果指定了在使用进程外抓取dump,breakpad对服务端就有依赖。主要体现在抓取dump时,如果服务端不存在,客户端将无法正常抓取dump,甚至有时会出现阻塞。

当然对于这些问题,随着breakpad的发展肯定会越来越完善。如果,你遇到了了这些问题,而又绕过不了,那就改代码,并且提交给breakpad吧,开源项目就是这么发展的。


客户端:C/S(客户进程/服务进程)
服务器:或称后台,请区分服务进程与服务器。

handler负责产生dump,sender负责上传。因为程序crash时,自己的堆栈被破坏,本身是不安全的,不适合再做其他事情。
打个比方:进程1是crash进程,使用handler,进程2是监控进程,进程1crash时,handler会产生一个minidump,通过管道发送给进程2,进程2此时使用sender发送到服务器。
在main最前面设好handler和callback,在callback里调用另一进程来上报dump,使用本进程来做是不安全的。

通过以下异常安全的指导,可以在异常重现时,确保hander所有的代码得到执行:

  • 禁止使用程序的堆,堆已经被破坏,不可用,allocators堆分配器可能不起作用。
  • 严格禁止资源的分配。handler可能创建了个文件来获取dump,可能执行个过程来处理此文件。
  • 明令禁止执行crash的线程。这个线程只能执行此类代码:必要的来过渡处理一个专用的预先分配handler线程,异常handler返回的代码。
  • Handler们自己不能尝试walk stacks来处理crash,因为stacks可能已经和以前不一致。操作系统的内存管理器和代码模块管理器来产生Dump.
  • 避免包括运行时库在内的库的代码,除非证明符合以上指南。比如:STL的string可能不能用了,因为它是需要在堆上allocate内存的。意味着许多C的库不能用了,尤其是在Windows上,因为可能在操作堆。

异常重现时,handler尽可能让该线程在生成dump期间保持原状态,在转储生成,它很困难甚至不可能对一个线程来准确地捕捉自己的状态。执行另一个独立线程处理异常也是危险的,因为堆栈越界异常可能存在。处理异常时,堆栈溢出是相当危险的。因为可能否决申请资源的请求,Breakpad handler库当他设置handler时会创建自己的线程。Mac OS X,这个处理程序线程被创建在正常设置的异常处理程序,handler线程将标示在一个异常事件上。在Windows和Linux,handler线程发出少量的代码执行异常的线程。因为执行的代码在异常线程在本例中是小和安全,这并不构成问题。甚至当一个异常是由于超过栈大小限制,这段代码非常紧凑的执行完全在堆栈的保护页面没有引发一个异常。

在一个感兴趣的点上,可直接产生dump来分析。 



回调过滤器

当处理程序线程开始处理一个异常,它调用一个可选的用户定义的过滤器回调函数,它负责判断是否应该继续Breakpad的处理程序处理异常。这种机制提供了插件代码的开发人员方便,可能对使用自己模块外的模块crash不感兴趣。如果筛选器回调表明它是不感兴趣的异常,Breakpad处理程序安排送至任何之前安装的handler。



Dump的产生

假设过滤器回调赞同(或不存在),在处理程序被安装时,handler写一个转储在应用程序开发人员指定的目录中,使用以前生成的唯一标识符,以避免名称冲突。不同平台转储生成的机制也不同,但一般来说,这个过程包括列举每个线程的异常,并捕获它的状态,包括处理器上下文和活跃的部分地区的堆栈。转储还包括一个加载到应用程序的代码模块列表,和一个哪个线程生成的异常或请求转储的指示器。转储是写在磁盘上的位置为了避免在这一过程中分配内存。



Sender 库

Breakpad的发送方库提供一个函数来发送一个崩溃报告服务器崩溃。它接受一个接收崩溃的服务器的URL,一个映射的键-值参数,将伴随转储,通往一个转储文件本身。每个键-值参数和多个不同部分dump作为HTTP POST请求使用平台的本地HTTP工具发送到指定的URL。在Linux上,libcurl用于这个功能,因为它是最接近一个标准的HTTP库在该平台。




需要注意的是:在上传dump文件的时候,crash_report_sender并不会对dump文件进行分析,而是直接上传整个dump文件,如果你需要上传的dump文件非常大的话,可以考虑把崩溃分析处理的逻辑放入前台,通过去重或者直接上传分析结果,减少上传的文件大小。



后台处理dump文件,windows下处理方式差不多,因为Windows下符号是pdb,需要先用dump_syms把pdb转换为sym格式的符号。
解析的时候用minidump_stackwalk解析。

Getting the stacktrace (without symbols)

Run minidump_stackwalk foo.dmp. For 32-bit, minidump_stackwalk will display the stacktrace without symbols. For 64-bit, it will only display the top frame.

Decoding Windows crash dumps on Linux

Windows crash dumps can be decoded the same way as Linux crash dumps. The issue is mainly getting the debugging symbols as a .sym file instead of a .pdb file.

To convert a .pdb file to a .sym file:
  1. Obtain the .pdb file and put it on a Windows machine. (It may be possible to do this with Wine, YMMV.)
  2. Download dump_syms.exe.
  3. Run: dump_syms foo.pdb > foo.sym
    • If no error messages, then you are done.
    • If you get: CoCreateInstance CLSID_DiaSource failed (msdia80.dll unregistered?), go to step 4.
  4. Get a copy of msdia80.dll and put it in c:\Program Files\Common Files\Microsoft Shared\VC\.
  5. As Administrator, run: regsvr32 c:\Program Files\Common Files\Microsoft Shared\VC\msdia80.dll.
    • On success, retry step 3.
    • If you get error 0x80004005, you did not run as Administrator.
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

asmcvc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值