青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 319, comments - 22, trackbacks - 0, articles - 11
  C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

Google Breakpad 完全解析(二) —— Windows前臺(tái)實(shí)現(xiàn)篇

2011年02月7日 — Asp J

Table of contents for Google Breakpad 完全解析

  1. Google Breakpad 完全解析(一) —— Windows入門篇
  2. Google Breakpad 完全解析(二) —— Windows前臺(tái)實(shí)現(xiàn)篇

原創(chuàng)文章,轉(zhuǎn)載請(qǐng)標(biāo)明出處:Soul Apogee (http://bigasp.com),謝謝。

好,看完了如何使用breakpad,我們現(xiàn)在看看breakpad在Windows下到底是如何實(shí)現(xiàn)的呢?

代碼結(jié)構(gòu)

在我們來(lái)看breakpad是如何實(shí)現(xiàn)其強(qiáng)大的功能之前,我們先來(lái)看一下他的代碼結(jié)構(gòu)吧。

Google breakpad的源代碼都在src的目錄下,他分為如下幾個(gè)文件夾:
client:這下面包含了前臺(tái)應(yīng)用程序中捕捉dump的部分代碼,里面按照平臺(tái)分成各個(gè)子文件夾
common:前臺(tái)后臺(tái)都會(huì)用到的部分基礎(chǔ)代碼,字符串轉(zhuǎn)換,內(nèi)存讀寫(xiě),md5神馬的
google_breakpad:breakpad中公共的頭文件
processor:用于在后臺(tái)處理崩潰的核心代碼
testing:測(cè)試工程
third_party:第三方庫(kù)
tools:一些小工具,用于處理dump文件和符號(hào)表

我們先來(lái)看Windows下前臺(tái)實(shí)現(xiàn)的部分,也就是client文件夾下的代碼。

breakpad的崩潰捕獲機(jī)制

在Windows下捕獲崩潰,大家很容易會(huì)想到那個(gè)捕獲結(jié)構(gòu)化異常的Api:SetUnhandledExceptionFilter

breakpad中也使用了這個(gè)Api來(lái)實(shí)現(xiàn)的崩潰捕獲,另外,breakpad還捕獲了另外兩種C++運(yùn)行庫(kù)提供的崩潰,一種是使用_set_purecall_handler捕獲純虛函數(shù)調(diào)用產(chǎn)生的崩潰,還有一種是使用_set_invalid_parameter_handler捕獲錯(cuò)誤的參數(shù)調(diào)用產(chǎn)生的崩潰。

1
2
3
4
5
6
7
8
9
10
    if (handler_types & HANDLER_EXCEPTION)
      previous_filter_ = SetUnhandledExceptionFilter(HandleException);
 
#if _MSC_VER >= 1400  // MSVC 2005/8
    if (handler_types & HANDLER_INVALID_PARAMETER)
      previous_iph_ = _set_invalid_parameter_handler(HandleInvalidParameter);
#endif  // _MSC_VER >= 1400
 
    if (handler_types & HANDLER_PURECALL)
      previous_pch_ = _set_purecall_handler(HandlePureVirtualCall);

另外由于C++運(yùn)行庫(kù)提供的崩潰回調(diào)中,并不會(huì)提供當(dāng)前的線程現(xiàn)場(chǎng)和崩潰信息,所以breakpad會(huì)自己生成好這些信息,然后請(qǐng)求生成dump。
這里值得一說(shuō)的是,在非異常崩潰處理中,breakpad獲取線程現(xiàn)場(chǎng)使用的函數(shù)是RtlCaptureContext而不是GetThreadContext。
RtlCaptureContext只能捕獲當(dāng)前線程的現(xiàn)場(chǎng),而GetThreadContext可以捕獲任意線程的現(xiàn)場(chǎng),只要有這個(gè)線程的句柄即可。
但是GetThreadContext有兩個(gè)不好的地方:不能獲取當(dāng)前線程的現(xiàn)場(chǎng);獲取現(xiàn)場(chǎng)前必須先用SuspendThread暫停目標(biāo)線程。
而RtlCaptureContext雖然只能獲取當(dāng)前線程的現(xiàn)場(chǎng),但是調(diào)用他時(shí)可以不用暫停線程的運(yùn)行。
對(duì)于breakpad來(lái)說(shuō),崩潰發(fā)生后越早獲取現(xiàn)場(chǎng)就越好,所以breakpad使用RtlCaptureContext函數(shù)作為他的線程獲取函數(shù)。

breakpad中的C/S結(jié)構(gòu)

由于breakpad是在進(jìn)程外抓取dump,所以breakpad需要實(shí)現(xiàn)一個(gè)C/S結(jié)構(gòu)來(lái)處理崩潰進(jìn)程抓取dump的請(qǐng)求。

1. breakpad跨進(jìn)程通信的實(shí)現(xiàn)
breakpad中使用了命名管道來(lái)實(shí)現(xiàn)IPC。

在客戶端,初始化ExceptionHandler的時(shí)候,如果指定了PipeName,也就表示此時(shí)需要使用進(jìn)程外的dump抓 取,ExceptionHandler,會(huì)建立一個(gè) CrashGenerationClient的對(duì)象,由這個(gè)對(duì)象連接服務(wù)端,將自己注冊(cè)到服務(wù)端上 去。
大家可以參看exception_handler.cc中的ExceptionHandler::Initialize函數(shù)。

在服務(wù)端,初始化CrashGenerationServer的時(shí)候,就會(huì)建立一個(gè)命名管道,并等待客戶端來(lái)連接。一旦有客戶端連接上來(lái),服務(wù)端會(huì) 為每一個(gè)客戶端生成一個(gè)ClientInfo的對(duì)象,之后用這個(gè)對(duì)象來(lái)管理所有的客戶端,一旦有崩潰發(fā)生,服務(wù)端都會(huì)從這個(gè)對(duì)象中取出dump所需要的信 息。
大家可以參看crash_generation_server.cc中的CrashGenerationServer::HandleReadDoneState函數(shù)。

2. breakpad捕獲崩潰生成dump的流程
breakpad進(jìn)程外生成dump的流程大概如下:
google-breakpad-out-of-process-dump:
google-breakpad-out-of-process-dump
這段流程的代碼就是crash_generation_client.cc和crash_generation_server.cc。

有兩個(gè)簡(jiǎn)單的問(wèn)題,這里說(shuō)明一下,高手們就請(qǐng)直接忽略吧,咩哈哈:
在服務(wù)端如何為客戶端生成事件句柄?
使用DuplicateHandle,即可把任意一個(gè)內(nèi)核對(duì)象的句柄復(fù)制到其他進(jìn)程,并且可以指定產(chǎn)生的句柄的權(quán)限。

如何異步的等待一個(gè)事件?
使用RegisterWaitForSingleObject,即可異步的等待一個(gè)事件,當(dāng)事件發(fā)生的時(shí)候,就可以回調(diào)到一個(gè)指定的回 調(diào)函數(shù)中,但是要注意的是,RegisterWaitForSingleObject會(huì)在一個(gè)新的線程中來(lái)等待這個(gè)事件,此處很容易產(chǎn)生多線程的調(diào)用,需 要注意線程問(wèn)題。

3. 服務(wù)端關(guān)鍵數(shù)據(jù)結(jié)構(gòu):ClientInfo
ClientInfo是服務(wù)端中最重要的數(shù)據(jù)結(jié)構(gòu),服務(wù)端通過(guò)它來(lái)管理所有的客戶端。客戶端注冊(cè)時(shí),會(huì)保存或生成里面所有的信息,在客戶端請(qǐng)求生成dump的時(shí)候,服務(wù)端就會(huì)通過(guò)ClientInfo獲取所有客戶端的信息。ClientInfo中保存了如下信息:

  • 客戶端進(jìn)程pid和句柄
  • 生成Minidump的類型
  • 自定義的客戶端信息
  • 客戶端崩潰的線程ID
  • 客戶端崩潰的信息
  • 客戶端請(qǐng)求崩潰所使用的事件句柄

這里有一個(gè)問(wèn)題:在客戶端發(fā)生崩潰時(shí),服務(wù)器如何通過(guò)ClientInfo獲取到客戶端的崩潰信息呢?

客戶端中有幾個(gè)用于保存崩潰信息的變量,在注冊(cè)時(shí),客戶端會(huì)將這幾個(gè)變量的地址發(fā)送至服務(wù)端,服務(wù)端將其保存在ClientInfo中,然后當(dāng)崩潰 發(fā)生的時(shí)候,服務(wù)端就可以通過(guò)ReadProcessMemory讀取客戶端中的信息,從而生成dump。這樣做就避免了每次發(fā)生崩潰,都要通過(guò)Pipe 將崩潰信息傳遞到服務(wù)端中去了。

這些變量分別是:崩潰的線程ID,EXCEPTION_POINTERS和MDRawAssertionInfo。
EXCEPTION_POINTERS和MDRawAssertionInfo的區(qū)別在于,異常崩潰的信息會(huì)被寫(xiě)入EXCEPTION_POINTERS,非異常崩潰(非法參數(shù)和純虛函數(shù)調(diào)用)的信息會(huì)被寫(xiě)入MDRawAssertionInfo中。

dump文件的上傳

在breakpad的工程中,有一個(gè)工程叫做:crash_report_sender,里面是一個(gè)上傳崩潰文件的類,他的實(shí)現(xiàn)很簡(jiǎn)單,他使用Windows Internet Api來(lái)完成dump文件的上傳。
在使用crash_report_sender時(shí),可以為其指定一個(gè)checkpoint_file。

1
explicit CrashReportSender(const wstring &checkpoint_file);

這個(gè)文件只有一個(gè)作用,就是用來(lái)保存上次上傳崩潰的時(shí)間和今天上傳過(guò)的崩潰的次數(shù)。通過(guò)這個(gè)文件,我們就可以來(lái)設(shè)置每日上傳的崩潰的最大數(shù)量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
CrashReportSender::CrashReportSender(const wstring &checkpoint_file)
    : checkpoint_file_(checkpoint_file),
      max_reports_per_day_(-1),
      last_sent_date_(-1),
      reports_sent_(0) {
  FILE *fd;
  if (OpenCheckpointFile(L"r", &fd) == 0) {
    ReadCheckpoint(fd);
    fclose(fd);
  }
}
 
ReportResult CrashReportSender::SendCrashReport(
    const wstring &url, const map<wstring, wstring> &parameters,
    const wstring &dump_file_name, wstring *report_code) {
  int today = GetCurrentDate();
  if (today == last_sent_date_ &&
      max_reports_per_day_ != -1 &&
      reports_sent_ >= max_reports_per_day_) {
    return RESULT_THROTTLED;
  }
 
  // 上傳文件部分代碼,省略
}

調(diào)整每日上傳崩潰的最大數(shù)量的函數(shù)是set_max_reports_per_day。

需要注意的是:在上傳dump文件的時(shí)候,crash_report_sender并不會(huì)對(duì)dump文件進(jìn)行分析,而是直接上傳整個(gè)dump文件, 如果你需要上傳的dump文件非常大的話,可以考慮把崩潰分析處理的邏輯放入前臺(tái),通過(guò)去重或者直接上傳分析結(jié)果,減少上傳的文件大小。

breakpad存在的問(wèn)題

進(jìn)程外生成dump有很多好處,其中最大的好處就是不會(huì)被崩潰進(jìn)程影響,這樣dump的過(guò)程就不容易出錯(cuò),但是這樣也有一定的弊端。

1. 部分崩潰無(wú)法抓取
在一些極端的崩潰,如堆棧溢出之類的崩潰,進(jìn)程外抓取dump有時(shí)候會(huì)失敗。

2. 無(wú)法抓取死鎖或者其他原因?qū)е碌倪M(jìn)程僵死
breakpad現(xiàn)在沒(méi)有檢測(cè)進(jìn)程死鎖的代碼,也沒(méi)有在服務(wù)端控制客戶端請(qǐng)求dump的代碼,所以現(xiàn)在breakpad無(wú)法抓取死鎖等進(jìn)程僵死的問(wèn)題。不過(guò)因?yàn)閎reakpad的定位是處理崩潰,如果有這種需要的童鞋,可以自行修改breakpad的代碼,添加這些功能。

3. 對(duì)服務(wù)端有依賴
如果指定了在使用進(jìn)程外抓取dump,breakpad對(duì)服務(wù)端就有依賴。主要體現(xiàn)在抓取dump時(shí),如果服務(wù)端不存在,客戶端將無(wú)法正常抓取dump,甚至有時(shí)會(huì)出現(xiàn)阻塞。

當(dāng)然對(duì)于這些問(wèn)題,隨著breakpad的發(fā)展肯定會(huì)越來(lái)越完善。如果,你遇到了了這些問(wèn)題,而又繞過(guò)不了,那就改代碼,并且提交給breakpad吧,開(kāi)源項(xiàng)目就是這么發(fā)展的。

好,到此breakpad的Windows實(shí)現(xiàn)就已經(jīng)說(shuō)完了,如果有神馬問(wèn)題,還請(qǐng)多多指教。謝謝大家。

北京德勝門中醫(yī)院http://www.0531jsk.com/德勝門中醫(yī)院

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲私人影吧| 99精品国产福利在线观看免费| 亚洲一区二区精品在线观看| 久久精品欧美日韩| 日韩视频欧美视频| 麻豆成人综合网| 久久久欧美一区二区| 美日韩精品视频免费看| 亚洲已满18点击进入久久| 国产精品免费一区二区三区在线观看 | 亚洲精品视频在线播放| 在线播放不卡| 亚洲国产精品久久人人爱蜜臀| 一区二区三区四区国产| 欧美制服第一页| 亚洲视频1区| 国产日韩精品久久久| 99人久久精品视频最新地址| 牛牛国产精品| 精品二区久久| 精品动漫一区| 欧美午夜不卡视频| 99精品国产热久久91蜜凸| 欧美成人一区二区| 激情欧美丁香| 亚洲欧洲免费视频| 亚洲精品美女在线观看| 欧美区在线播放| 欧美日韩视频一区二区| 欧美国产日韩精品免费观看| 久久久99免费视频| 亚洲欧洲另类| 亚洲图片自拍偷拍| 久久福利毛片| 蜜臀av性久久久久蜜臀aⅴ| 麻豆精品视频在线观看| 91久久久在线| 亚洲男人天堂2024| 欧美黑人国产人伦爽爽爽| 欧美激情网站在线观看| 亚洲精品美女在线| 亚洲欧美精品suv| 亚洲男女毛片无遮挡| 久久国产精品一区二区三区四区| 麻豆精品视频在线观看| 一区二区三区黄色| 老牛嫩草一区二区三区日本| 免费亚洲一区| 亚洲在线电影| 亚洲综合清纯丝袜自拍| 亚洲免费一级电影| 欧美日韩国产亚洲一区| 久久www成人_看片免费不卡| 久久久精品一区二区三区| 亚洲第一在线视频| 亚洲自拍偷拍福利| 欧美激情综合在线| 激情欧美一区二区三区在线观看 | 欧美激情在线有限公司| 99精品热6080yy久久| 久久国产精品一区二区三区| 亚洲国产高清一区| 久久国产高清| 国产欧美欧美| 亚洲自拍偷拍麻豆| 99国产精品国产精品久久 | 国产欧美日韩精品在线| 99精品欧美一区二区蜜桃免费| 久久手机免费观看| 日韩视频在线播放| 毛片精品免费在线观看| 国产夜色精品一区二区av| 国产精品v日韩精品v欧美精品网站| 91久久精品国产91性色| 亚洲一级在线观看| 亚洲精品国产视频| 久久日韩粉嫩一区二区三区| 久久久久久亚洲综合影院红桃 | 亚洲日本黄色| 欧美1区视频| 欧美激情精品久久久久久久变态| 国产精品综合| 亚洲一区久久久| 亚洲毛片在线观看.| 久久亚洲春色中文字幕久久久| 国产女主播视频一区二区| 亚洲尤物影院| 一本色道久久综合亚洲精品小说 | 欧美freesex8一10精品| 精品91久久久久| 久久夜色精品国产欧美乱极品| 亚洲精品日本| 91久久夜色精品国产网站| 欧美韩日一区二区三区| 一本久道综合久久精品| 亚洲美女在线看| 欧美国产精品日韩| 一本到高清视频免费精品| 牛牛影视久久网| 免费在线视频一区| 一本久道综合久久精品| 亚洲伊人第一页| 亚洲国产二区| 午夜日韩在线观看| 亚洲国产婷婷综合在线精品 | 黑人一区二区三区四区五区| 老鸭窝毛片一区二区三区| 久久夜色精品国产噜噜av| 亚洲国产精品高清久久久| 亚洲国产精品久久精品怡红院| 欧美有码在线观看视频| 亚洲国产日韩在线一区模特| 亚洲精品国产精品国自产观看浪潮| 欧美视频在线观看免费网址| 久久精品综合| 欧美高清视频一区| 亚洲制服av| 久久免费国产精品| 99国产精品久久久| 国产精品爽黄69| 亚洲高清视频在线| 欧美在线亚洲一区| 亚洲视频在线看| 欧美日韩在线播放一区二区| 在线视频你懂得一区| 免费日韩一区二区| 在线日韩av| 久久精品1区| 久久精品视频在线免费观看| 国产精品v片在线观看不卡| 亚洲精品影视| 欧美制服丝袜| **性色生活片久久毛片| 性xx色xx综合久久久xx| 欧美国产在线观看| 久久人人爽人人爽| 久久国产色av| 午夜精品www| 欧美成人自拍| 亚洲激情在线激情| 国产一区二区日韩精品| 国产精品视频免费在线观看| 牛牛精品成人免费视频| 欧美了一区在线观看| 亚洲欧洲日韩女同| 一本色道久久88综合日韩精品| 久久久久久久久综合| 亚洲风情亚aⅴ在线发布| 欧美色一级片| 欧美日韩国产首页| 亚洲黄色精品| 国产女主播在线一区二区| 一区二区三区视频在线看| 亚洲电影在线看| 欧美一区二区三区精品电影| 久久国产精品网站| 亚洲成人在线观看视频| 欧美全黄视频| 国产精自产拍久久久久久| 国产精品久久777777毛茸茸| 国产偷国产偷精品高清尤物| 国产精品私拍pans大尺度在线| 一区二区电影免费观看| 亚洲一区久久| 亚洲在线电影| 一区二区三区日韩| 国产精品男女猛烈高潮激情| 国产精品久久一区主播| 一区二区三区精品视频| 欧美三级电影网| 性欧美xxxx大乳国产app| 久久亚洲国产成人| 亚洲国产一区二区三区青草影视| 欧美激情一区二区三区成人| 一本久道久久综合中文字幕| 欧美在线看片| 最新国产精品拍自在线播放| 欧美日韩一区二区视频在线观看| 午夜亚洲性色视频| 亚洲精品欧美一区二区三区| 欧美在线视频观看免费网站| 亚洲国产成人精品久久久国产成人一区| 欧美国产精品| 欧美在线看片| 一区二区av| 欧美成年人视频| 欧美在线视频观看| 在线一区二区三区四区五区| 亚洲电影欧美电影有声小说| 国产精品亚洲综合色区韩国| 欧美精品一卡| 久久综合亚州| 久久电影一区| 一区二区三区精品国产| 亚洲国产精品传媒在线观看 | 国产精品magnet| 免费永久网站黄欧美| 欧美在线看片a免费观看| 亚洲午夜精品国产| 亚洲精品欧美极品|