简介:

  Breadpad为google chrominum项目下用于处理dump的一套工具;内部采用跨平台方式实现捕获、生成、解析与平台无关的dump,便于统一处理;支持进程内与进程外捕获,当为进程外捕获时,客户端捕获异常并告知服务器端抓取该crash并生成相应dump文件。以下仅针对windows平台下进行分析。

项目构成:

Common:公共部分主要有:

  GUIDString:得到唯一的guid符号RFC4122格式

(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)的字符串GUIDToWString,主要用来在MinidumpGenerator中创建生成的dump文件的名称,转化为十六进制大写的不带分隔符的字符串GUIDToSymbolServerWString,主要用来作为symbol服务器ID的标识;

  WindowsStringUtils:字符串转换工具,包括:安全拷贝、多字节与宽字节间的转化、获取文件路径中的文件名称;

  HTTPUpload:一个基于WinInet简单封装的http文件上传类,也包含UTF8与UTF16间的转化,此类用在CrashReportSender中提供上传生成的dump文件(似乎未用到该方式);

Crash_generation_app:

一个提供使用示例的demo;测试进程外捕获时需要运行两次该demo,第一个作为服务器,第二次作为客户端,服务器也可以捕获自己的异常crash dump;

Crash_report_sender:

崩溃crash报告发送者,内部会使用HTTPUpload上传;

ReportResult:定义了四种结果状态:

RESULT_FAILED:连接服务器失败,尝试重试;

RESULT_REJECTED:发送至服务器成功,但服务器拒绝接收,可不再发送此报告;

RESULT_SUCCEEDED:发送至服务器成功并接收;

RESULT_THROTTLED:已到达每天上传的最大报告数;

checkpoint_file_:报告发送文件检查点文件,主要用来作为一个上传报告的识别标识;

max_reports_per_day_:每天至多可上传的最大报告数;

last_sent_date_:最近一次上传报告的时间;格式YYYYMMDD;

reports_sent_:最近一天得上传报告数目;

set_max_reports_per_day:设置每天上传的最大报告数目;

max_reports_per_day:获取当前每天上传的最大报告数目;

CrashReportSender:构造函数,参数checkpoint_file为检查点文件,并初始化

max_reports_per_day_值为-1,表示无限制、last_sent_date_值为-1、reports_sent_值为0,此外内部还调用OpenCheckpointFile打开文件和ReadCheckpoint读取到检查点文件的last_sent_date_和reports_sent_值;SendCrashReport:发送crash报告,参数url为指定的服务器地址,parameters为被格式化并将发送的参数信息,dump_file_name为dump文件路径名,report_code为报告请求响应码;

GetCurrentDate:获取当前日期,内部通过GetSystemTime获取年月日;

ReportSent:更新检查点文件内容,主要重写回检点点文件(kCheckpointSignature("GBP1\n")、last_sent_date_、reports_sent_);

总结crash_report_sender:其中的SendCrashReport发送crash报告内部细节为:先获取当前系统时间与文件中读取的比较,若设置了上传上界且达到了上界则不再发送;发送指定的crash文件;重新更新检查点文件内容返回执行结果ReportResult;此外检查点文件格式形如为:

  GBP1\n

  20151208\n

  120\n

Except_handler:异常捕获器对象,主要用来捕获异常,分为进程外和进程内,进程内可不再需要服务器,进程外需要服务器和客户端并开启服务,此时交由服务器抓取,而客户端则只需要捕获异常并通知服务器来抓取不涉及异常和抓取操作;Except_handler内部针对参数不同执行不同的处理方式,此外服务器也可以捕获自己的异常(只要有Except_handler定义),这样进程内捕获既可以直接使用Except_handler也可以使用服务器但pipe参数设置为NULL即可;

AppMemory:进程内存区域信息,包含基地址、长度,主要用在保存minidump时用到;

FilterCallback:任何执行捕获异常前调用的回调函数,可用来过滤、预处理异常信息,该函数返回true则继续进程并导致产生dump文件,否则会忽略该异常,此时若用户需要可以自己再去处理该异常;参数context为回调上下文该参数为Except_handler的构造函数传入的对应参数,exinfo为异常信息,内含异常记录,assertion为断言信息,一般在纯虚函数异常、无效参数异常中用到;

MinidumpCallback:捕获处理dump后的回调函数,返回值含义同上,参数dump_path为生成dump文件的路径,minidump_id为生成dump文件id,succeeded为是否创建成功;其他参数含义同上;

HandlerType:捕获类型,包含:

HANDLER_NONE:捕获任意的异常;

HANDLER_EXCEPTION:设置SetUnhandledExceptionFilter的异常捕获;

HANDLER_INVALID_PARAMETER:设置_set_invalid_parameter_handler的异常捕获;

HANDLER_PURECALL:设置_set_purecall_handler的异常捕获;

HANDLER_ALL:HANDLER_EXCEPTION、HANDLER_INVALID_PARAMETER、HANDLER_PURECALL;

ExceptionHandler构造函数:多个重载版本提供外部简单调用的接口,这样可以方便的实现进程内捕获还是进程外捕获便于区分参数传递避免混乱,事实上内部统一调用函数Initialize完成初始化,未提供的参数则使用默认参数;

Initialize:参数dump_path为生成dump文件路径,filter抓取前滤波器回调函数,callback抓取后回调函数,callback_context传入filter的回调参数,handler_types为将安装的捕获异常类型,dump_type为产生minidump类型;pipe_name为命名管道名称,pipe_handle为命名管道句柄,crash_generation_client为crash生成客户端对象,custom_info为客户端自定义的信息,主要包含客户端信息、软件版本等在进程外捕获模式下会发送给服务器注册时的信息;

dump_path:获取dump文件路径;

set_dump_path:设置dump文件路径,内部调用UpdateNextID更新下一个保存dump文件的路径名称和文件名称,文件名称使用_time64获取并转化为格式为"%Y-%m-%d_%H-%M-%S";

RequestUpload:请求上传某个早期指定的ID的dump文件,用在客户端请求服务器上传某个早期的dump文件;

WriteMinidump:立即写入minidump文件,一般用在用户独自处理异常时调用的接口,但是该接口适合用在当前线程,此外重置版本提供了一个遍历的接口供外部使用,此时可不需要ExceptionHandler实例即可方便处理异常,参数含义同构造函数;

WriteMinidumpForException:立即写入minidump文件,用在用户保存自定义的异常信息,也是用在用户独自处理异常时调用;

WriteMinidumpForChild:立即写入”子”进程的某线程的dump文件,child为某个进程的句柄,child_blamed_thread为改子进程的线程ID,其他参数同构造函数;

get_requesting_thread_id:获取请求线程ID,该值为WriteMinidump或WriteMinidumpForException的请求线程ID;

set_handle_debug_exceptions:设置控制EXCEPTION_BREAKPOINT与

EXCEPTION_SINGLE_STEP异常类型,直接写入dump文件,用在用户自己控制异常的情况;

IsOutOfProcess:是否为进程外捕获,内部通过获取crash_generation_client_是否为NULL判断是否为进程外捕获;

RegisterAppMemory:注册保存至dump文件的进程开始基地址和长度;

UnregisterAppMemory:移除对应的保存至dump文件的进程开始基地址;

其他私有成员:如设置异常捕获、无效参数、纯虚函数异常、写dump回调、以及其他状态控制变量,不再一一列举;

总结:ExceptionHandler作为捕获异常类,提供了多次捕获方式,包括进程内捕获、进程外捕获、用户自定义控制捕获、捕获任何异常、捕获无效参数异常、捕获纯虚函数调用异常、用户手动保存dump、用户保存自定义设置的异常并保存dump等;

重点说明的函数:

Initialize:初始化操作内部通过参数crash_generation_client、pipe_name、pipe_handle决定是进程内还是进程外捕获,对于进程内捕获,内部通过创建一个专门用于捕获异常、写异常的线程(通过创建两个信号量来实现线程间同步);而对于进程外捕获,将创建一个CrashGenerationClient客户端对象,并将服务器端的必要的参数通过命名管道传回给该客户端,当ExceptionHandler中的HandleException、HandleInvalidParameter、HandlePureVirtualCall捕获到异常时通过该客户端对象的RequestDump方法将异常信号保存到客户端对象,最后通过SignalCrashEventAndWait方法重置服务器端的生成crash事件和crash事件(事实上每个客户端都有一个自己的这两个事件),服务器收到crash事件后保存该客户端保存的异常信号,并设置生成crash事件,完成整个异常捕获、告知、保存、交互的过程;基本上ExceptionHandler就差不多只处理这些工作,其他的操作移交给客户端和服务器端处理,再次说明:捕获进程内异常只需要ExceptionHandler就可以,不需要服务器和客户端;进程外捕获需要客户端和服务器端,另外客户端在其中扮演的角色也比较简单,只是提供捕获通告事件、通告捕获内容、请求服务器上传捕获ID对应dump文件等;

CrashGenerationClient:客户端,连接服务器、提供异常告知事件、异常捕获内容;

在ExceptionHandler中创建客户端时,内部执行Register实现注册该客户端到服务器,并构造ProtocolMessage协议消息将客户端必要信息通过命名管道发送给服务器并获取服务器的响应信息(响应信息保护crash事件句柄、crash生成事件句柄、服务器是否存活句柄、服务器进程ID);ExceptionHandler捕获到异常将通过该客户端的接口RequestDump请求服务器抓取,此时没有采用命名管道而是使用事件信号通告;

CrashGenerationServer:服务器,连接客户端、处理客户端请求、抓取客户端crash并生成dump文件,必要时上传dump文件;构造函数中创建了一个MinidumpGenerator的对象dump_generator_用于保存dump文件,此外服务器封装比较简单,对外只提供了Start接口和pre_fetch_custom_info,Start:开启服务器,监听客户端连接,创建服务器存活句柄、与客户端连接、管道读写用到的事件信号、注册回调事件函数(线程池中),创建命名管道用于与客户端通信,pre_fetch_custom_info:是否预抓取客户进程中自定义内存信息;此外注册的回调事件函数OnPipeConnected内部实现当客户连接请求时,获取到客户信息,并注册客户请求dump回调事件和客户端退出回调事件,保存维护客户列表;

总结:CrashGenerationServer通过注册OnPipeConnected事件回调实现不同客户端连接时管道通信(包含必要信息相互通告),并内部处理注册客户请求dump回调事件和客户端退出回调事件,此外还有客户请求上传dump(上传请求将调用OnClientUploadRequestCallback回调,服务器需要自己实现上传操作),其他的均采用事件通知的方式而不再是命名管道,减少协议、通信的麻烦;保存dump使用其成员dump_generator_的 WriteMinidump接口,其内部使用ReadProcessMemory读取客户进程下对应的异常信息并调用dbghelp.dll 库中的接口MiniDumpWriteDump保存,具体保存内容、格式,MinidumpGenerator类实现不再详细分析;

项目总结:

  基本上ExceptionHandler在进程内捕获时采用开启另外一个线程实现捕获抓取,并不再生成客户端和服务器端;进程外捕获时将额外开启服务器进程,此外捕获进程还需要生成客户端;客户端辅助通告服务器连接、请求捕获、请求上传dump;服务器端辅助维护客户端连接、客户端捕获请求、上传请求、dump保存操作;通信基于命名管道、命名管道传递多个事件句柄后期请求捕获通告、客户退出通告将通告事件告知而不再是命名管道,请求上传仍采用管道通知;

  还有其他的工具如ms_symbol_server_converter、dump_syms、symupload暂不分析;其他项目中需要用到的时候仅根据需要结合示例工程Crash_generation_app即可方便使用异常捕获机制,此外可以根据需要设置ExceptionHandler实现自定义捕获的需要。

Breakpad Google的crash捕获、抓取开源库的更多相关文章

  1. android开发之应用Crash自动抓取Log_自动保存崩溃日志到本地

    http://blog.csdn.net/jason0539/article/details/45602655 应用发生crash之后要查看log,判断问题出在什么地方,可是一旦应用发布出去,就要想办 ...

  2. Fiddler捕获抓取 App端数据包

    最近项目设计到App抓包,所以采用Fiddler工具来采集获取APP数据包,但是fiddler对有些app是无法捕获到数据包的,以下是我的处理方法: 1. 我默认代理端口使用的是自定义的端口而不是默认 ...

  3. Windows Phone & Windows App应用程序崩溃crash信息抓取方法

    最近有用户反馈,应用有崩溃的情况,可是本地调试却无法重现问题,理所当然的,我想到了微软的开发者仪表盘,可以查看一段时间内的carsh记录,不过仪表盘生成carsh记录不是实时的,而且生成的报告查看非常 ...

  4. sqlserver 抓取所有执行语句 SQL语句分析 死锁 抓取

    原文:sqlserver 抓取所有执行语句 SQL语句分析 死锁 抓取 在多人开发中最头疼的是人少事多没有时间进行codereview,本来功能都没时间写,哪有时间来开会细细来分析代码.软件能跑就行, ...

  5. 【重磅开源】Hawk-数据抓取工具:简明教程

    Hawk-数据抓取工具:简明教程 标签(空格分隔): Hawk Hawk: Advanced Crawler& ETL tool written in C#/WPF 1.软件介绍 HAWK是一 ...

  6. 使用java开源工具httpClient及jsoup抓取解析网页数据

    今天做项目的时候遇到这样一个需求,需要在网页上展示今日黄历信息,数据格式如下 公历时间:2016年04月11日 星期一 农历时间:猴年三月初五 天干地支:丙申年 壬辰月 癸亥日 宜:求子 祈福 开光 ...

  7. 【开源】Hawk-数据抓取工具:简明教程

    1.软件介绍 HAWK是一种数据采集和清洗工具,依据GPL协议开源,能够灵活,有效地采集来自网页,数据库,文件, 并通过可视化地拖拽, 快速地进行生成,过滤,转换等操作.其功能最适合的领域,是爬虫和数 ...

  8. 关于python抓取google搜索结果的若干问题

    关于python抓取google搜索结果的若干问题     前一段时间一直在研究如何用python抓取搜索引擎结果,在实现的过程中遇到了很多的问题,我把我遇到的问题都记录下来,希望以后遇到同样问题的童 ...

  9. 手把手视频:万能开源Hawk抓取动态网站

    Hawk是沙漠之鹰历时五年开发的开源免费网页抓取工具(爬虫),无需编程,全部可视化. 自从上次发布Hawk 2.0过了小半年,可是还是有不少朋友通过邮件或者微信的方式询问如何使用.看文档还是不如视频教 ...

随机推荐

  1. 借助Html制作渐变的网页背景颜色

    借助Html制作渐变的网页背景颜色 <html> <head> <title>制作渐变背景</title> <meta http-equiv=&q ...

  2. 了不起的全能MAC系统监测工具iStat Menus 5下载

    iStat Menus 5 是一款由软件开发商 Bjango 制作的 System Monitor (工具,也是笔者电脑里的必装应用之一,它能让用户最快速.最直观地了解到几乎各硬件所有的运行状态,其中 ...

  3. maven如何配置

    1. logback介绍 Logback是由log4j创始人设计的又一个开源日志组件.logback当前分成三个模块:logback-core,logback- classic和logback-acc ...

  4. Java文件操作

    1.通过File类中的createNewFile()创建一个新的文件 /**     * 测试创建文件     * @throws IOException     */    @Test    pub ...

  5. nginx 反代理google

    ./configure \ --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/n ...

  6. 在Web工程中引入Jquery插件报错解决方案

    在学习Jquery插件的时候,遇到一个问题就是新建web工程后在WebRoot下引入Jquery插件的时候报错,不知道为什么好纠结,但是项目能正常运行,后来找到解决方案,在这里给大家分享一下. 解决方 ...

  7. web.xml添加编码过滤器

    解决前后台交互汉字乱码 在项目中的web.xml中添加如下代码: <filter> <filter-name>CharacterEncodingFilter</filte ...

  8. linux第二天

    由于今天公司事情比较多,今天基本没有自学.了解了一下type命令:主要是显示命令类型的命令.linux命令分为内置命令和外部命令两种.内置命令就shell内置的命令,外部命令,就是需要有系统存在一个名 ...

  9. vue.js的一些知识点

    1. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8& ...

  10. Android Studio 快捷键

    1.显示注解:F2 2.显示大括号包含范围:Ctrl 3.显示当前文档结构:Ctrl+F12 4.快速打开类:Ctrl+N 5.格式化代码:Ctrl+Alt+L 6.折叠代码:Ctrl+[+/-] 7 ...