chore: add V8 crash information to crashReporter (#24771)
* feat: add V8 crash information to crashReporter * Address review feedback
This commit is contained in:
parent
d93bb34ac4
commit
948cc08265
4 changed files with 61 additions and 0 deletions
|
@ -128,6 +128,16 @@ std::vector<v8::Local<v8::Value>> GetWeaklyTrackedValues(v8::Isolate* isolate) {
|
||||||
}
|
}
|
||||||
return locals;
|
return locals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This causes a fatal error by creating a circular extension dependency.
|
||||||
|
void TriggerFatalErrorForTesting(v8::Isolate* isolate) {
|
||||||
|
static const char* aDeps[] = {"B"};
|
||||||
|
v8::RegisterExtension(std::make_unique<v8::Extension>("A", "", 1, aDeps));
|
||||||
|
static const char* bDeps[] = {"A"};
|
||||||
|
v8::RegisterExtension(std::make_unique<v8::Extension>("B", "", 1, bDeps));
|
||||||
|
v8::ExtensionConfiguration config(1, bDeps);
|
||||||
|
v8::Context::New(isolate, &config);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Initialize(v8::Local<v8::Object> exports,
|
void Initialize(v8::Local<v8::Object> exports,
|
||||||
|
@ -144,6 +154,7 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||||
&RequestGarbageCollectionForTesting);
|
&RequestGarbageCollectionForTesting);
|
||||||
dict.SetMethod("isSameOrigin", &IsSameOrigin);
|
dict.SetMethod("isSameOrigin", &IsSameOrigin);
|
||||||
#ifdef DCHECK_IS_ON
|
#ifdef DCHECK_IS_ON
|
||||||
|
dict.SetMethod("triggerFatalErrorForTesting", &TriggerFatalErrorForTesting);
|
||||||
dict.SetMethod("getWeaklyTrackedValues", &GetWeaklyTrackedValues);
|
dict.SetMethod("getWeaklyTrackedValues", &GetWeaklyTrackedValues);
|
||||||
dict.SetMethod("clearWeaklyTrackedValues", &ClearWeaklyTrackedValues);
|
dict.SetMethod("clearWeaklyTrackedValues", &ClearWeaklyTrackedValues);
|
||||||
dict.SetMethod("weaklyTrackValue", &WeaklyTrackValue);
|
dict.SetMethod("weaklyTrackValue", &WeaklyTrackValue);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "content/public/browser/browser_thread.h"
|
#include "content/public/browser/browser_thread.h"
|
||||||
#include "content/public/common/content_paths.h"
|
#include "content/public/common/content_paths.h"
|
||||||
#include "electron/buildflags/buildflags.h"
|
#include "electron/buildflags/buildflags.h"
|
||||||
|
#include "shell/common/api/electron_bindings.h"
|
||||||
#include "shell/common/electron_command_line.h"
|
#include "shell/common/electron_command_line.h"
|
||||||
#include "shell/common/gin_converters/file_path_converter.h"
|
#include "shell/common/gin_converters/file_path_converter.h"
|
||||||
#include "shell/common/gin_helper/dictionary.h"
|
#include "shell/common/gin_helper/dictionary.h"
|
||||||
|
@ -33,6 +34,10 @@
|
||||||
#include "shell/common/mac/main_application_bundle.h"
|
#include "shell/common/mac/main_application_bundle.h"
|
||||||
#include "shell/common/node_includes.h"
|
#include "shell/common/node_includes.h"
|
||||||
|
|
||||||
|
#if !defined(MAS_BUILD)
|
||||||
|
#include "shell/common/crash_keys.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ELECTRON_BUILTIN_MODULES(V) \
|
#define ELECTRON_BUILTIN_MODULES(V) \
|
||||||
V(electron_browser_app) \
|
V(electron_browser_app) \
|
||||||
V(electron_browser_auto_updater) \
|
V(electron_browser_auto_updater) \
|
||||||
|
@ -132,6 +137,18 @@ bool IsPackagedApp() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void V8FatalErrorCallback(const char* location, const char* message) {
|
||||||
|
LOG(ERROR) << "Fatal error in V8: " << location << " " << message;
|
||||||
|
|
||||||
|
#if !defined(MAS_BUILD)
|
||||||
|
electron::crash_keys::SetCrashKey("electron.v8-fatal.message", message);
|
||||||
|
electron::crash_keys::SetCrashKey("electron.v8-fatal.location", location);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
volatile int* zero = nullptr;
|
||||||
|
*zero = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize Node.js cli options to pass to Node.js
|
// Initialize Node.js cli options to pass to Node.js
|
||||||
// See https://nodejs.org/api/cli.html#cli_options
|
// See https://nodejs.org/api/cli.html#cli_options
|
||||||
void SetNodeCliFlags() {
|
void SetNodeCliFlags() {
|
||||||
|
@ -397,6 +414,10 @@ node::Environment* NodeBindings::CreateEnvironment(
|
||||||
|
|
||||||
node::IsolateSettings is;
|
node::IsolateSettings is;
|
||||||
|
|
||||||
|
// Use a custom fatal error callback to allow us to add
|
||||||
|
// crash message and location to CrashReports.
|
||||||
|
is.fatal_error_callback = V8FatalErrorCallback;
|
||||||
|
|
||||||
if (browser_env_ == BrowserEnvironment::BROWSER) {
|
if (browser_env_ == BrowserEnvironment::BROWSER) {
|
||||||
// Node.js requires that microtask checkpoints be explicitly invoked.
|
// Node.js requires that microtask checkpoints be explicitly invoked.
|
||||||
is.policy = v8::MicrotasksPolicy::kExplicit;
|
is.policy = v8::MicrotasksPolicy::kExplicit;
|
||||||
|
|
|
@ -28,6 +28,8 @@ type CrashInfo = {
|
||||||
globalParam: 'globalValue' | undefined
|
globalParam: 'globalValue' | undefined
|
||||||
addedThenRemoved: 'to-be-removed' | undefined
|
addedThenRemoved: 'to-be-removed' | undefined
|
||||||
longParam: string | undefined
|
longParam: string | undefined
|
||||||
|
'electron.v8-fatal.location': string | undefined
|
||||||
|
'electron.v8-fatal.message': string | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkCrash (expectedProcessType: string, fields: CrashInfo) {
|
function checkCrash (expectedProcessType: string, fields: CrashInfo) {
|
||||||
|
@ -192,6 +194,32 @@ ifdescribe(!isLinuxOnArm && !process.mas && !process.env.DISABLE_CRASH_REPORTER_
|
||||||
expect(crash.rendererSpecific).to.equal('rs');
|
expect(crash.rendererSpecific).to.equal('rs');
|
||||||
expect(crash.addedThenRemoved).to.be.undefined();
|
expect(crash.addedThenRemoved).to.be.undefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('contains v8 crash keys when a v8 crash occurs', async () => {
|
||||||
|
const { remotely } = await startRemoteControlApp();
|
||||||
|
const { port, waitForCrash } = await startServer();
|
||||||
|
|
||||||
|
await remotely((port: number) => {
|
||||||
|
require('electron').crashReporter.start({
|
||||||
|
submitURL: `http://127.0.0.1:${port}`,
|
||||||
|
ignoreSystemCrashHandler: true
|
||||||
|
});
|
||||||
|
}, [port]);
|
||||||
|
|
||||||
|
remotely(() => {
|
||||||
|
const { BrowserWindow } = require('electron');
|
||||||
|
const bw = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } });
|
||||||
|
bw.loadURL('about:blank');
|
||||||
|
bw.webContents.executeJavaScript('process._linkedBinding(\'electron_common_v8_util\').triggerFatalErrorForTesting()');
|
||||||
|
});
|
||||||
|
|
||||||
|
const crash = await waitForCrash();
|
||||||
|
expect(crash.prod).to.equal('Electron');
|
||||||
|
expect(crash._productName).to.equal('remote-control');
|
||||||
|
expect(crash.process_type).to.equal('renderer');
|
||||||
|
expect(crash['electron.v8-fatal.location']).to.equal('v8::Context::New()');
|
||||||
|
expect(crash['electron.v8-fatal.message']).to.equal('Circular extension dependency');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
1
typings/internal-ambient.d.ts
vendored
1
typings/internal-ambient.d.ts
vendored
|
@ -44,6 +44,7 @@ declare namespace NodeJS {
|
||||||
clearWeaklyTrackedValues(): void;
|
clearWeaklyTrackedValues(): void;
|
||||||
getWeaklyTrackedValues(): any[];
|
getWeaklyTrackedValues(): any[];
|
||||||
addRemoteObjectRef(contextId: string, id: number): void;
|
addRemoteObjectRef(contextId: string, id: number): void;
|
||||||
|
triggerFatalErrorForTesting(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
type AsarFileInfo = {
|
type AsarFileInfo = {
|
||||||
|
|
Loading…
Reference in a new issue