进程外生成dump有很多好处,其中最大的好处就是不会被崩溃进程影响,这样dump的过程就不容易出错,但是这样也有一定的弊端。
1. 部分崩溃无法抓取
在一些极端的崩溃,如堆栈溢出之类的崩溃,进程外抓取dump有时候会失败。
2. 无法抓取死锁或者其他原因导致的进程僵死
breakpad现在没有检测进程死锁的代码,也没有在服务端控制客户端请求dump的代码,所以现在breakpad无法抓取死锁等进程僵死的问题。不过因为breakpad的定位是处理崩溃,如果有这种需要的童鞋,可以自行修改breakpad的代码,添加这些功能。
3. 对服务端有依赖
如果指定了在使用进程外抓取dump,breakpad对服务端就有依赖。主要体现在抓取dump时,如果服务端不存在,客户端将无法正常抓取dump,甚至有时会出现阻塞。
当然对于这些问题,随着breakpad的发展肯定会越来越完善。如果,你遇到了了这些问题,而又绕过不了,那就改代码,并且提交给breakpad吧,开源项目就是这么发展的。
通过以下异常安全的指导,可以在异常重现时,确保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库在该平台。
Getting the stacktrace (without symbols)
Decoding Windows crash dumps on Linux
- Obtain the .pdb file and put it on a Windows machine. (It may be possible to do this with Wine, YMMV.)
- Download dump_syms.exe.
- 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.
- Get a copy of msdia80.dll and put it in c:\Program Files\Common Files\Microsoft Shared\VC\.
- 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.