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

posts - 319, comments - 22, trackbacks - 0, articles - 11
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

Google Breakpad 完全解析(二) —— Windows前臺實現篇

2011年02月7日 — Asp J

Table of contents for Google Breakpad 完全解析

  1. Google Breakpad 完全解析(一) —— Windows入門篇
  2. Google Breakpad 完全解析(二) —— Windows前臺實現篇

原創文章,轉載請標明出處:Soul Apogee (http://bigasp.com),謝謝。

好,看完了如何使用breakpad,我們現在看看breakpad在Windows下到底是如何實現的呢?

代碼結構

在我們來看breakpad是如何實現其強大的功能之前,我們先來看一下他的代碼結構吧。

Google breakpad的源代碼都在src的目錄下,他分為如下幾個文件夾:
client:這下面包含了前臺應用程序中捕捉dump的部分代碼,里面按照平臺分成各個子文件夾
common:前臺后臺都會用到的部分基礎代碼,字符串轉換,內存讀寫,md5神馬的
google_breakpad:breakpad中公共的頭文件
processor:用于在后臺處理崩潰的核心代碼
testing:測試工程
third_party:第三方庫
tools:一些小工具,用于處理dump文件和符號表

我們先來看Windows下前臺實現的部分,也就是client文件夾下的代碼。

breakpad的崩潰捕獲機制

在Windows下捕獲崩潰,大家很容易會想到那個捕獲結構化異常的Api:SetUnhandledExceptionFilter

breakpad中也使用了這個Api來實現的崩潰捕獲,另外,breakpad還捕獲了另外兩種C++運行庫提供的崩潰,一種是使用_set_purecall_handler捕獲純虛函數調用產生的崩潰,還有一種是使用_set_invalid_parameter_handler捕獲錯誤的參數調用產生的崩潰。

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++運行庫提供的崩潰回調中,并不會提供當前的線程現場和崩潰信息,所以breakpad會自己生成好這些信息,然后請求生成dump。
這里值得一說的是,在非異常崩潰處理中,breakpad獲取線程現場使用的函數是RtlCaptureContext而不是GetThreadContext。
RtlCaptureContext只能捕獲當前線程的現場,而GetThreadContext可以捕獲任意線程的現場,只要有這個線程的句柄即可。
但是GetThreadContext有兩個不好的地方:不能獲取當前線程的現場;獲取現場前必須先用SuspendThread暫停目標線程。
而RtlCaptureContext雖然只能獲取當前線程的現場,但是調用他時可以不用暫停線程的運行。
對于breakpad來說,崩潰發生后越早獲取現場就越好,所以breakpad使用RtlCaptureContext函數作為他的線程獲取函數。

breakpad中的C/S結構

由于breakpad是在進程外抓取dump,所以breakpad需要實現一個C/S結構來處理崩潰進程抓取dump的請求。

1. breakpad跨進程通信的實現
breakpad中使用了命名管道來實現IPC。

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

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

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

有兩個簡單的問題,這里說明一下,高手們就請直接忽略吧,咩哈哈:
在服務端如何為客戶端生成事件句柄?
使用DuplicateHandle,即可把任意一個內核對象的句柄復制到其他進程,并且可以指定產生的句柄的權限。

如何異步的等待一個事件?
使用RegisterWaitForSingleObject,即可異步的等待一個事件,當事件發生的時候,就可以回調到一個指定的回 調函數中,但是要注意的是,RegisterWaitForSingleObject會在一個新的線程中來等待這個事件,此處很容易產生多線程的調用,需 要注意線程問題。

3. 服務端關鍵數據結構:ClientInfo
ClientInfo是服務端中最重要的數據結構,服務端通過它來管理所有的客戶端。客戶端注冊時,會保存或生成里面所有的信息,在客戶端請求生成dump的時候,服務端就會通過ClientInfo獲取所有客戶端的信息。ClientInfo中保存了如下信息:

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

這里有一個問題:在客戶端發生崩潰時,服務器如何通過ClientInfo獲取到客戶端的崩潰信息呢?

客戶端中有幾個用于保存崩潰信息的變量,在注冊時,客戶端會將這幾個變量的地址發送至服務端,服務端將其保存在ClientInfo中,然后當崩潰 發生的時候,服務端就可以通過ReadProcessMemory讀取客戶端中的信息,從而生成dump。這樣做就避免了每次發生崩潰,都要通過Pipe 將崩潰信息傳遞到服務端中去了。

這些變量分別是:崩潰的線程ID,EXCEPTION_POINTERS和MDRawAssertionInfo。
EXCEPTION_POINTERS和MDRawAssertionInfo的區別在于,異常崩潰的信息會被寫入EXCEPTION_POINTERS,非異常崩潰(非法參數和純虛函數調用)的信息會被寫入MDRawAssertionInfo中。

dump文件的上傳

在breakpad的工程中,有一個工程叫做:crash_report_sender,里面是一個上傳崩潰文件的類,他的實現很簡單,他使用Windows Internet Api來完成dump文件的上傳。
在使用crash_report_sender時,可以為其指定一個checkpoint_file。

1
explicit CrashReportSender(const wstring &checkpoint_file);

這個文件只有一個作用,就是用來保存上次上傳崩潰的時間和今天上傳過的崩潰的次數。通過這個文件,我們就可以來設置每日上傳的崩潰的最大數量。

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;
  }
 
  // 上傳文件部分代碼,省略
}

調整每日上傳崩潰的最大數量的函數是set_max_reports_per_day。

需要注意的是:在上傳dump文件的時候,crash_report_sender并不會對dump文件進行分析,而是直接上傳整個dump文件, 如果你需要上傳的dump文件非常大的話,可以考慮把崩潰分析處理的邏輯放入前臺,通過去重或者直接上傳分析結果,減少上傳的文件大小。

breakpad存在的問題

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

1. 部分崩潰無法抓取
在一些極端的崩潰,如堆棧溢出之類的崩潰,進程外抓取dump有時候會失敗。

2. 無法抓取死鎖或者其他原因導致的進程僵死
breakpad現在沒有檢測進程死鎖的代碼,也沒有在服務端控制客戶端請求dump的代碼,所以現在breakpad無法抓取死鎖等進程僵死的問題。不過因為breakpad的定位是處理崩潰,如果有這種需要的童鞋,可以自行修改breakpad的代碼,添加這些功能。

3. 對服務端有依賴
如果指定了在使用進程外抓取dump,breakpad對服務端就有依賴。主要體現在抓取dump時,如果服務端不存在,客戶端將無法正常抓取dump,甚至有時會出現阻塞。

當然對于這些問題,隨著breakpad的發展肯定會越來越完善。如果,你遇到了了這些問題,而又繞過不了,那就改代碼,并且提交給breakpad吧,開源項目就是這么發展的。

好,到此breakpad的Windows實現就已經說完了,如果有神馬問題,還請多多指教。謝謝大家。

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

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美精品午夜视频| 久久久人人人| 国产综合久久久久久鬼色| 欧美日韩蜜桃| 欧美日韩成人网| 老司机精品视频网站| 欧美一区二区三区四区视频| 亚洲欧美精品伊人久久| 欧美一级成年大片在线观看| 久久精品成人欧美大片古装| 国产一区 二区 三区一级| 久久免费的精品国产v∧| 亚洲激精日韩激精欧美精品| 亚洲免费电影在线| 亚洲手机视频| 久久久久成人精品| 美女主播视频一区| 亚洲第一视频网站| 99精品国产在热久久| 亚洲伊人网站| 久久久久免费| 欧美激情欧美激情在线五月| 亚洲免费观看高清完整版在线观看熊| 日韩午夜电影在线观看| 欧美一级视频| 欧美日韩一区二区三区免费 | 久久综合久久美利坚合众国| 噜噜噜久久亚洲精品国产品小说| 亚洲黄色尤物视频| 亚洲黄色影院| 欧美一站二站| 欧美 日韩 国产在线| 欧美日韩在线播放一区二区| 国产自产高清不卡| 一区二区三区鲁丝不卡| 国产精品激情av在线播放| 狠狠色2019综合网| 日韩视频一区二区| 久久精品一区二区三区四区| 亚洲欧洲一区二区三区在线观看 | 欧美一区二区播放| 久久一区亚洲| 国产麻豆精品在线观看| 亚洲日本理论电影| 久久综合色一综合色88| 亚洲一区二区四区| 欧美二区不卡| 韩日欧美一区二区三区| 午夜视频一区二区| 夜夜嗨网站十八久久| 欧美成年人视频| 1024亚洲| 久久中文精品| 欧美在线免费一级片| 国产精品亚洲综合色区韩国| 中日韩高清电影网| 欧美激情亚洲精品| 久久视频在线视频| 影音先锋日韩精品| 久久久久久91香蕉国产| 亚洲精品久久视频| 欧美日韩mv| 亚洲一区二区三区激情| 亚洲精品在线观| 欧美国产一区在线| 欧美电影美腿模特1979在线看| 亚洲影视综合| 国产精品视频最多的网站| 亚洲天堂男人| 一本色道久久综合一区| 国产精品av免费在线观看| 一区二区三区欧美日韩| 亚洲激情在线观看视频免费| 欧美精彩视频一区二区三区| 91久久久亚洲精品| 亚洲精品中文字幕在线观看| 欧美日韩一区在线| 香蕉久久一区二区不卡无毒影院 | 亚洲视频电影图片偷拍一区| 亚洲免费观看高清完整版在线观看| 欧美精品在线网站| 亚洲一区www| 欧美一级免费视频| 亚洲电影网站| 亚洲精品乱码久久久久| 国产精品久久久久久久久动漫| 小黄鸭精品密入口导航| 久久成人av少妇免费| 亚洲国产精品一区制服丝袜| 91久久久一线二线三线品牌| 欧美午夜精品理论片a级大开眼界| 亚洲一区在线免费| 久久福利视频导航| 日韩午夜电影av| 亚洲视频免费观看| 黑人极品videos精品欧美裸| 欧美华人在线视频| 国产精品进线69影院| 久久这里只有精品视频首页| 欧美日韩国产一区二区三区地区| 欧美影片第一页| 欧美成人免费小视频| 亚洲欧美在线一区| 免费成人美女女| 亚洲欧美国产三级| 免费日韩av电影| 欧美综合激情网| 欧美精品1区2区3区| 久久精品论坛| 欧美日韩一区二区三区在线| 久久免费视频一区| 亚洲一区国产| 亚洲日韩欧美一区二区在线| 香蕉国产精品偷在线观看不卡 | 亚洲三级毛片| 午夜国产精品视频| 99热这里只有成人精品国产| 欧美一区免费| 亚洲午夜国产一区99re久久| 狂野欧美激情性xxxx| 欧美一区午夜精品| 欧美午夜久久| 免费试看一区| 免费成人黄色av| 国产精品福利在线| 亚洲国产精彩中文乱码av在线播放| 欧美三区在线观看| 亚洲午夜精品网| 欧美福利电影网| 老司机午夜精品视频| 国产人成精品一区二区三| 亚洲免费高清| 夜夜嗨av一区二区三区网站四季av| 久久国产视频网站| 久久精品日产第一区二区| 国产精品久久久久久一区二区三区 | 欧美日韩精品久久久| 欧美激情第8页| 悠悠资源网亚洲青| 久久都是精品| 免费观看成人| 亚洲国产综合在线看不卡| 免费成人你懂的| 亚洲国产日韩欧美| 亚洲乱码国产乱码精品精天堂| 欧美.www| 亚洲日本在线观看| 一区二区三区视频在线看| 欧美成人中文字幕| 亚洲精品国产系列| 亚洲视频999| 国产乱肥老妇国产一区二| 午夜精品久久久久久久久久久久久| 销魂美女一区二区三区视频在线| 国产欧美日韩麻豆91| 久久国产精品久久国产精品| 久久综合狠狠| 亚洲电影在线免费观看| 欧美黄网免费在线观看| 日韩一级精品| 羞羞答答国产精品www一本| 国产亚洲a∨片在线观看| 久久久最新网址| 久久久久久国产精品mv| 经典三级久久| 欧美紧缚bdsm在线视频| 亚洲一区二区三区乱码aⅴ蜜桃女| 欧美一区观看| 在线免费日韩片| 欧美日韩国产在线一区| 亚洲视频免费观看| 欧美1区视频| 国产亚洲永久域名| 欧美高清在线视频观看不卡| 这里只有精品丝袜| 美女主播视频一区| 亚洲欧美www| 亚洲人线精品午夜| 国产欧美日韩精品a在线观看| 欧美成人乱码一区二区三区| 欧美一区2区视频在线观看 | 久久久久一区二区| 一本久久a久久免费精品不卡| 欧美一区二区精品| 欧美日韩亚洲成人| 久久精品理论片| 亚洲午夜一二三区视频| 亚洲日本va午夜在线影院| 久久婷婷一区| 91久久夜色精品国产网站| 欧美一区二区免费观在线| 亚洲福利在线视频| 99国产成+人+综合+亚洲欧美| 欧美一级大片在线观看| 亚洲激情图片小说视频| 久久精品在线免费观看| 中文一区字幕| 亚洲精品韩国| 国产一区视频网站| 国产精品一区亚洲|