Electron 应用崩溃问题排查与解决方法

1、常见的导致 Electron 应用崩溃原因

1.1 、JavaScript 层可能导致的崩溃

1)传给 WebGL 渲染的ArrayBuffer,实际宽或高为零

2)图片宽或高为零,传给 Canvas 绘制

3)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 相关的代码时,这一层导致应用程序崩溃的可能行极大,常见原因有:

1)空指针访问

2)数组越界

3)Node.js C++ add-on API 错误调用、参数错误等

2、Electron 应用崩溃处理方法

2.1、JavaScript 层导致崩溃

针对 JavaScritpt 导致崩溃,需要找到崩溃出现路径,一步步调试基本可以发现问题原因,做一些防御性编程就可以规避。

2.2、Node.js C++ add-on 层导致的崩溃

这一次导致的崩溃问题,一般比较难排查,特别是针对前端开发人员,这里给出的解决方案是:

(1)开起 Electron Crash Reporter 功能,获取崩溃堆栈,分析堆栈内容;

扫描二维码关注公众号,回复: 16639773 查看本文章

(2)监听 Electron crash 相关事件,记录crash 日志。

2.2.1、开启 Electron Crash Reporter

开起后,可以收集 Electron 应用的崩溃堆栈,Electron Crash Reporter 支持将崩溃堆栈上传到在线的第三方服务平台,用户也可以通过配置上传自己的服务器(服务端需要自己开发),也可以只生成溃堆栈文件在本地,用于排查崩溃问题。下面将只介绍如何生成崩溃堆栈文件到本地。

2.2.1.1、开启崩溃堆栈文件生成,并获取崩溃文件存放路径

需要在 main 进程的 JavaScript 代码中,在一开始的位置添加如下代码,开启 Electron Crash Reporter 捕获功能。

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 进程的启动脚本,增加如下代码,监听奔溃事件,可以把这些日志写入本地文件。

注意:此时渲染进程可能已经溃,不能发送给渲染进程打印到窗口的控制台,溃事件的日志最好写到本地文件或者发送个服务端。

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 版本号、操作系统平台信息、SDK本地日志(非必须,最好提供)。

参考:Electron 应用奔溃问题排查与解决方法-腾讯云开发者社区-腾讯云

猜你喜欢

转载自blog.csdn.net/fuhanghang/article/details/132847072