1 常见的导致 Electron 应用奔溃原因
1.1 JavaScript 层可能导致的奔溃
- 传给 WebGL 渲染的ArrayBuffer,实际宽或高为零
- 图片宽或高为零,传给 Canvas 绘制
- Electron 12 及以下版本,来自 node.js C add-on 层的 ArrayBuffer,必须复制一次,否则渲染进程会奔溃。相关 Bug 地址:https://github.com/electron/electron/issues/15538
1.2 设备访问权限
- Mac 下未做摄像头、麦克风授权,直接访问时,可能导致 Electron 应用奔溃。针对此问题,可参照 腾讯云实时音视频 官网场景问题规避。
1.3 C 层导致的奔溃
存在 Node.js C add-on 相关的代码时,这一层导致应用程序奔溃的可能行极大,常见原因有:
- 空指针访问
- 数组越界
- Node.js C add-on API 错误调用、参数错误等
2 Electron 应用奔溃处理方法
2.1 JavaScript 层导致奔溃
针对 JavaScritpt 导致奔溃,需要找到奔溃出现路径,一步步调试基本可以发现问题原因,做一些防御性编程就可以规避。
2.2 Node.js C add-on 层导致的奔溃
这一次导致的奔溃问题,一般比较难排查,特别是针对前端开发人员,这里给出的解决方案是:(1)开起 Electron Crash Reporter 功能,获取奔溃堆栈,分析堆栈内容;(2)监听 Electron crash 相关事件,记录crash 日志。
2.2.1 开启 Electron Crash Reporter
开起后,可以收集 Electron 应用的奔溃堆栈,Electron Crash Reporter 支持将奔溃堆栈上传到在线的第三方服务平台,用户也可以通过配置上传自己的服务器(服务端需要自己开发),也可以只生成奔溃堆栈文件在本地,用于排查奔溃问题。下面将只介绍如何生成奔溃堆栈文件到本地。
2.2.1.1 开启奔溃堆栈文件生成,并获取奔溃文件存放路径
需要在 main 进程的 JavaScript 代码中,在一开始的位置添加如下代码,开启 Electron Crash Reporter 捕获功能。
代码语言:txt复制const { app, BrowserWindow, crashReporter, ipcMain, systemPreferences } = require('electron');
const path = require('path');
// 获取奔溃堆栈文件存放路径
let crashFilePath = '';
let crashDumpsDir = '';
try {
// electron 低版本
crashFilePath = path.join(app.getPath('temp'), app.getName() ' Crashes');
console.log('————————crash path:', crashFilePath);
// electron 高版本
crashDumpsDir = app.getPath('crashDumps');
console.log('————————crashDumpsDir:', crashDumpsDir);
} catch (e) {
console.error('获取奔溃文件路径失败', e);
}
// 开启crash捕获
crashReporter.start({
productName: 'Your-Application-Name',
companyName: 'Your-Company-Name',
submitURL: 'https://www.xxx.com', // 上传到服务器的地址
uploadToServer: false, // 不上传服务器
ignoreSystemCrashHandler: false, // 不忽略系统自带的奔溃处理,为 true 时表示忽略,奔溃时不会生成奔溃堆栈文件
});
以上代码不能保证每次奔溃,都收集到奔溃堆栈,但如果奔溃较频繁,很可能在某次奔溃时生成,如果发现生成了奔溃堆栈,一定不要视而不见,对于偶现的奔溃问题,奔溃堆栈文件对定位排查问题很有帮助。
2.2.1.2 将奔溃堆栈文件存放目录写到渲染进程日志
通过安装包执行的应用,Electron 主进程的日志通常看不到或者不好查阅(可借助 Node.js 文件 API 写本地日志文件),可以将奔溃堆栈文件的存放路径打印到渲染进程的控制台,方便查询。实现方式参阅下方代码。
- 主进程 窗口加载完页面后,增加如下代码:
mainWindow.webContents.on('did-finish-load', function(event){
mainWindow.webContents.send('crash-file-path', `${crashFilePath} or ${crashDumpsDir}`);
});
- 渲染进程 preload 中增加如下代码:
const { ipcRenderer } = require('electron');
ipcRenderer.on('crash-file-path', (event, args) => {
console.warn('crash-file-path:', args);
});
- 奔溃文件示例及奔溃文件路径日志示例 如下图,奔溃文件可能在奔溃文件存放目录下的 new、completed、pending 目录下:
2.2.2 监听 Electron 渲染进程和 GPU 进程奔溃事件
Electron 提供了监听渲染进程和 GPU 进程奔溃的事件接口,监听这些事件,可以知道何时发生了奔溃,但奔溃的具体原因一般看不出来,需要获取奔溃堆栈的 dump 文件。
在 Electron main 进程的启动脚本,增加如下代码,监听奔溃事件,可以把这些日志写入本地文件。
注意:此时渲染进程可能已经奔溃,不能发送给渲染进程打印到窗口的控制台,奔溃事件的日志最好写到本地文件或者发送个服务端。
代码语言:txt复制app.on('gpu-process-crashed', (event, kill) => {
console.warn('app:gpu-process-crashed', event, kill);
});
app.on('renderer-process-crashed', (event, webContents, kill) => {
console.warn('app:renderer-process-crashed', event, webContents, kill);
});
app.on('render-process-gone', (event, webContents, details) => {
console.warn('app:render-process-gone', event, webContents, details);
});
app.on('child-process-gone', (event, details) => {
console.warn('app:child-process-gone', event, details);
});
注意:event 和 webContents 对象直接写文件,可以 JSON.stringify() 后写入。
2.2.3 奔溃堆栈文件分析
奔溃堆栈文件的分析,需要 Node.js C add-on 程序编译时的符号文件,WIndows下为 pdb 文件,Mac 下为 dSYM 文件,需要找相关的 C 开发人员处理。针对 腾讯云实时音视频 SDK 的奔溃,可以通过 QQ 群:695855795 ,联系 腾讯云实时音视频 开发人员,帮忙分析。分析奔溃堆栈文件需要提供:奔溃堆栈文件、SDK 版本号、操作系统平台信息、SDK本地日志(非必须,最好提供).
- SDK 本地日志路径,可以参阅相关 API 文档。
- QQ 群:695855795