layout: post
title: “使用Google开源库breakpad实现错误报告功能(Windows环境)”
subtitle: “Google大法好”
date: “2017-08-16”
author: “cj”
tags:
breakpad
c++
windows
google
bugreport
Windows环境下以前使用的CrashRpt1403错误报告系统出了点问题,问题上传端口(80)被微信服务器测试环境占用了,索性使用breakpad更新之。
目录
环境搭建
下载
按照官方教程,下载源码
git clone https://chromium.googlesource.com/breakpad/breakpad
有几个第三方库默认情况没有下载,按需手动下载到breakpad/src/thirdparty中
cd breakpad
git clone https://chromium.googlesource.com/linux-syscall-support src/third_party/lss
编译
与linux环境下直接configure&&make不同,Windows下需要google另一个工具gyp生成visual studio 的sln文件。另外gyp依赖Python2.x版本,如果系统环境变量PATH中指定的python.exe已经是Python3.x版的话,需要手动修改。Python2.x与3.x共用方案网上一搜大把不再赘述。
安装gyp:
git clone https://chromium.googlesource.com/external/gyp
cd gyp
python setup.py install
生成sln解决方案:
your-path-to-gyp/gyp.bat your-path-to-breakpad/src/client/windows/breakpad_client.gyp --no-circular-check
打开breakpad_client.sln并编译所需的库文件:
- ommon.lib
- exception_handler.lib
- crash_generation_client.lib
部署
在Windows下编译好应用程序后,使用breakpad的工具dump_syms.exe生成sym符号表,并上传至服务器。当客户环境中的应用程序崩溃时,调用一个脚本将dump信息上传至服务器,服务器端处理一下并生成stack walk信息发送到自己的邮箱。思路与上一篇linux版完全一样,只不过生成sym的环境换成了Windows,并增加了web服务以便处理。
下面以分为新版本发布时的“生成sym”和崩溃发生时的“处理dmp”记录一下。
生成sym并上传
新版本发布时,自动生成sym文件并上传
windows-publish
参考了这篇文章,摘录如下:
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:
- 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.
2020年1月13日23:57:56增补
新 win10
系统一直报 CoCreateInstance CLSID_DiaSource {3BFCEA48-620F-4B6B-81F7-B9AF75454C7D} failed (msdia*.dll unregistered?) Open failed
错误,按照上述方法注册了 c:\Program Files\Common Files\Microsoft Shared\VC\
文件夹下存在的 msdia80.dll
, msdia90.dll
, msdia100.dll
,问题依旧。
用 everything
搜索 msdia
,发现一大堆,试着注册了几个,试到 "C:\Program Files (x86)\Microsoft SDKs\UWPNuGetPackages\microsoft.net.native.compiler\1.7.6\tools\Runtime\x86\msdia120.dll"
的时候成功了。
懒人的解决方案:publish.bat
@echo off
rem 引用dump_sym.exe
set dump_syms="D:\dev_libs\google\breakpad\src\tools\windows\binaries\dump_syms.exe"
rem 需要使用7z进行压缩
set the_7z="..\7-Zip\7z.exe"
rem fciv是Windows发布的一个生成文件MD5值的小工具
set fciv="fciv.exe"
rem 需要使用curl上传文件
set curl="curl.exe"
rem 生成sym
%dump_syms% ..\..\Release\your-app.pdb > your-app.sym
rem 压缩
%the_7z% a publish.7z your-app.sym ..\ChangeLog.txt
del your-app.sym
rem 获取压缩文件MD5值
for /f %%i in ('%fciv% -md5 publish.7z') do set md5=%%i
rem 获取文件版本号
set /p pub_version=<..\..\Release\VersionNo.ini
rem 上传压缩文件至服务器
%curl% -F "action=upload" -F "md5=%md5%" -F "pub_version=%pub_version%" -F "publish=@publish.7z;type=application/7z" https://www.your-domain.com/crash/publish.php
del publish.7z
echo Done!
linux-publish
publish.php
<?php
// Specify the directory where to save error reports
$file_root = "/var/www/html/crash/app/";
// This is to avoid PHP warning
date_default_timezone_set('UTC');
// Writes error code and text message and then exits
function done($return_status, $message)
{
// Write HTTP responce code
header("HTTP/1.0 ".$return_status." ".$message);
// Write HTTP responce body (for backwards compatibility)
echo $return_status." ".$message;
exit(0);
}
// Checks that text fild doesn't contain inacceptable symbols
function checkOK($field)
{
if (stristr($field, "\\r") || stristr($field, "\\n"))
{
done(450, "Invalid input parameter.");
}
}
$md5_hash = ""; // MD5 hash for error report ZIP
$file_name = ""; // Destination file name
$pub_version = ""; // Publish version
// Check that MD5 hash exists
if(!isset($_POST['md5']))
{
done(450, "MD5 hash is missing.");
}
// Get MD5 hash
$md5_hash = $_POST['md5'];
checkOK($md5_hash);
if(strlen($md5_hash)!=32)
{
done(450, "MD5 hash value has wrong length.");
}
// Get CrashGUID
if(!array_key_exists("pub_version", $_POST))
{
done(450, "Publish version missing.");
}
$pub_version =