fix: enable crashpad for ELECTRON_RUN_AS_NODE processes (#36460)

* wip: enable crashpad for node processes

fix: add PID testing method

wip: plumb fd into child_process in node

* node::ProcessInitializationFlags::kNoDefaultSignalHandling

* chore: clean up debug logging

* chore: gate platform includes

* test: clean up node process test

* fix: pass pid in node_main

* chore: cleanup impl

* chore: fixup patch method definition

* fix: expose bound methods to node_main

* fix: remove bound methods

* fix: crashpad connection for all ELECTRON_RUN_AS_NODE processes

* chore: fix typo

* chore: address review feedback

* chore: delay crashpad initialization

* chore: ensure options.env, code hygiene

* chore: add argv test, check for process.env over {}

* fix: fix test, return options.env immutability

Co-authored-by: VerteDinde <keeleymhammond@gmail.com>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
Co-authored-by: VerteDinde <vertedinde@electronjs.org>
This commit is contained in:
Robo 2022-11-30 00:33:54 +09:00 committed by GitHub
parent 16a7bd7102
commit 2c723d7e84
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 194 additions and 12 deletions

View file

@ -34,6 +34,14 @@
#include "chrome/child/v8_crashpad_support_win.h"
#endif
#if BUILDFLAG(IS_LINUX)
#include "base/environment.h"
#include "base/posix/global_descriptors.h"
#include "base/strings/string_number_conversions.h"
#include "components/crash/core/app/crash_switches.h" // nogncheck
#include "content/public/common/content_descriptors.h"
#endif
#if !IS_MAS_BUILD()
#include "components/crash/core/app/crashpad.h" // nogncheck
#include "shell/app/electron_crash_reporter_client.h"
@ -110,15 +118,20 @@ int NodeMain(int argc, char* argv[]) {
v8_crashpad_support::SetUp();
#endif
// TODO(deepak1556): Enable crashpad support on linux for
// ELECTRON_RUN_AS_NODE processes.
// Refs https://github.com/electron/electron/issues/36030
#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_MAC) && !IS_MAS_BUILD())
ElectronCrashReporterClient::Create();
crash_reporter::InitializeCrashpad(false, "node");
crash_keys::SetCrashKeysFromCommandLine(
*base::CommandLine::ForCurrentProcess());
crash_keys::SetPlatformCrashKey();
#if BUILDFLAG(IS_LINUX)
auto os_env = base::Environment::Create();
std::string fd_string, pid_string;
if (os_env->GetVar("CRASHDUMP_SIGNAL_FD", &fd_string) &&
os_env->GetVar("CRASHPAD_HANDLER_PID", &pid_string)) {
int fd = -1, pid = -1;
DCHECK(base::StringToInt(fd_string, &fd));
DCHECK(base::StringToInt(pid_string, &pid));
base::GlobalDescriptors::GetInstance()->Set(kCrashDumpSignal, fd);
// Following API is unsafe in multi-threaded scenario, but at this point
// we are still single threaded.
os_env->UnSetVar("CRASHDUMP_SIGNAL_FD");
os_env->UnSetVar("CRASHPAD_HANDLER_PID");
}
#endif
int exit_code = 1;
@ -158,6 +171,29 @@ int NodeMain(int argc, char* argv[]) {
return result->exit_code();
}
#if BUILDFLAG(IS_LINUX)
// On Linux, initialize crashpad after Nodejs init phase so that
// crash and termination signal handlers can be set by the crashpad client.
if (!pid_string.empty()) {
auto* command_line = base::CommandLine::ForCurrentProcess();
command_line->AppendSwitchASCII(
crash_reporter::switches::kCrashpadHandlerPid, pid_string);
ElectronCrashReporterClient::Create();
crash_reporter::InitializeCrashpad(false, "node");
crash_keys::SetCrashKeysFromCommandLine(
*base::CommandLine::ForCurrentProcess());
crash_keys::SetPlatformCrashKey();
// Ensure the flags and env variable does not propagate to userland.
command_line->RemoveSwitch(crash_reporter::switches::kCrashpadHandlerPid);
}
#elif BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_MAC) && !IS_MAS_BUILD())
ElectronCrashReporterClient::Create();
crash_reporter::InitializeCrashpad(false, "node");
crash_keys::SetCrashKeysFromCommandLine(
*base::CommandLine::ForCurrentProcess());
crash_keys::SetPlatformCrashKey();
#endif
gin::V8Initializer::LoadV8Snapshot(
gin::V8SnapshotFileType::kWithAdditionalContext);

View file

@ -0,0 +1,39 @@
// Copyright (c) 2022 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/node_includes.h"
#if BUILDFLAG(IS_LINUX)
#include "components/crash/core/app/crashpad.h" // nogncheck
#endif
namespace {
#if BUILDFLAG(IS_LINUX)
int GetCrashdumpSignalFD() {
int fd;
return crash_reporter::GetHandlerSocket(&fd, nullptr) ? fd : -1;
}
int GetCrashpadHandlerPID() {
int pid;
return crash_reporter::GetHandlerSocket(nullptr, &pid) ? pid : -1;
}
#endif
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
gin_helper::Dictionary dict(context->GetIsolate(), exports);
#if BUILDFLAG(IS_LINUX)
dict.SetMethod("getCrashdumpSignalFD", &GetCrashdumpSignalFD);
dict.SetMethod("getCrashpadHandlerPID", &GetCrashpadHandlerPID);
#endif
}
} // namespace
NODE_LINKED_MODULE_CONTEXT_AWARE(electron_common_crashpad_support, Initialize)

View file

@ -80,6 +80,7 @@
V(electron_common_asar) \
V(electron_common_clipboard) \
V(electron_common_command_line) \
V(electron_common_crashpad_support) \
V(electron_common_environment) \
V(electron_common_features) \
V(electron_common_native_image) \