feat: support crashpad on linux (#29719)

This commit is contained in:
Jeremy Rose 2021-07-19 10:11:10 -07:00 committed by GitHub
parent 612361c4da
commit c9ba0d02d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 547 additions and 455 deletions

View file

@ -153,6 +153,9 @@ bool ElectronCrashReporterClient::GetCrashDumpLocation(
base::FilePath* crash_dir) {
bool result = base::PathService::Get(electron::DIR_CRASH_DUMPS, crash_dir);
{
// If the DIR_CRASH_DUMPS path is overridden with
// app.setPath('crashDumps', ...) then the directory might not have been
// created.
base::ThreadRestrictions::ScopedAllowIO allow_io;
if (result && !base::PathExists(*crash_dir)) {
return base::CreateDirectory(*crash_dir);
@ -162,13 +165,6 @@ bool ElectronCrashReporterClient::GetCrashDumpLocation(
}
#endif
#if defined(OS_MAC) || defined(OS_LINUX)
bool ElectronCrashReporterClient::GetCrashMetricsLocation(
base::FilePath* metrics_dir) {
return base::PathService::Get(chrome::DIR_USER_DATA, metrics_dir);
}
#endif // OS_MAC || OS_LINUX
bool ElectronCrashReporterClient::IsRunningUnattended() {
return !collect_stats_consent_;
}

View file

@ -52,10 +52,6 @@ class ElectronCrashReporterClient : public crash_reporter::CrashReporterClient {
bool GetCrashDumpLocation(base::FilePath* crash_dir) override;
#endif
#if defined(OS_MAC) || defined(OS_LINUX)
bool GetCrashMetricsLocation(base::FilePath* metrics_dir) override;
#endif
bool IsRunningUnattended() override;
bool GetCollectStatsConsent() override;

View file

@ -58,7 +58,8 @@
#endif
#if !defined(MAS_BUILD)
#include "components/crash/core/app/crashpad.h" // nogncheck
#include "components/crash/core/app/crash_switches.h" // nogncheck
#include "components/crash/core/app/crashpad.h" // nogncheck
#include "components/crash/core/common/crash_key.h"
#include "components/crash/core/common/crash_keys.h"
#include "shell/app/electron_crash_reporter_client.h"
@ -369,9 +370,19 @@ void ElectronMainDelegate::PreSandboxStartup() {
#endif
#if defined(OS_LINUX)
// Zygote needs to call InitCrashReporter() in RunZygote().
if (process_type != ::switches::kZygoteProcess && !process_type.empty()) {
ElectronCrashReporterClient::Create();
breakpad::InitCrashReporter(process_type);
if (crash_reporter::IsCrashpadEnabled()) {
if (command_line->HasSwitch(
crash_reporter::switches::kCrashpadHandlerPid)) {
crash_reporter::InitializeCrashpad(false, process_type);
crash_reporter::SetFirstChanceExceptionHandler(
v8::TryHandleWebAssemblyTrapPosix);
}
} else {
breakpad::InitCrashReporter(process_type);
}
}
#endif
@ -466,7 +477,16 @@ void ElectronMainDelegate::ZygoteForked() {
base::CommandLine::ForCurrentProcess();
std::string process_type =
command_line->GetSwitchValueASCII(::switches::kProcessType);
breakpad::InitCrashReporter(process_type);
if (crash_reporter::IsCrashpadEnabled()) {
if (command_line->HasSwitch(
crash_reporter::switches::kCrashpadHandlerPid)) {
crash_reporter::InitializeCrashpad(false, process_type);
crash_reporter::SetFirstChanceExceptionHandler(
v8::TryHandleWebAssemblyTrapPosix);
}
} else {
breakpad::InitCrashReporter(process_type);
}
// Reset the command line for the newly spawned process.
crash_keys::SetCrashKeysFromCommandLine(*command_line);

View file

@ -44,6 +44,7 @@
#include "base/guid.h"
#include "components/crash/core/app/breakpad_linux.h"
#include "components/crash/core/common/crash_keys.h"
#include "components/upload_list/combining_upload_list.h"
#include "v8/include/v8-wasm-trap-handler-posix.h"
#include "v8/include/v8.h"
#endif
@ -150,16 +151,29 @@ void Start(const std::string& submit_url,
? "node"
: command_line->GetSwitchValueASCII(::switches::kProcessType);
#if defined(OS_LINUX)
::crash_keys::SetMetricsClientIdFromGUID(GetClientId());
auto& global_crash_keys = GetGlobalCrashKeysMutable();
for (const auto& pair : global_extra) {
global_crash_keys[pair.first] = pair.second;
if (::crash_reporter::IsCrashpadEnabled()) {
for (const auto& pair : extra)
electron::crash_keys::SetCrashKey(pair.first, pair.second);
{
base::ThreadRestrictions::ScopedAllowIO allow_io;
::crash_reporter::InitializeCrashpad(process_type.empty(), process_type);
}
if (ignore_system_crash_handler) {
crashpad::CrashpadInfo::GetCrashpadInfo()
->set_system_crash_reporter_forwarding(crashpad::TriState::kDisabled);
}
} else {
::crash_keys::SetMetricsClientIdFromGUID(GetClientId());
auto& global_crash_keys = GetGlobalCrashKeysMutable();
for (const auto& pair : global_extra) {
global_crash_keys[pair.first] = pair.second;
}
for (const auto& pair : extra)
electron::crash_keys::SetCrashKey(pair.first, pair.second);
for (const auto& pair : global_extra)
electron::crash_keys::SetCrashKey(pair.first, pair.second);
breakpad::InitCrashReporter(process_type);
}
for (const auto& pair : extra)
electron::crash_keys::SetCrashKey(pair.first, pair.second);
for (const auto& pair : global_extra)
electron::crash_keys::SetCrashKey(pair.first, pair.second);
breakpad::InitCrashReporter(process_type);
#elif defined(OS_MAC)
for (const auto& pair : extra)
electron::crash_keys::SetCrashKey(pair.first, pair.second);
@ -203,7 +217,20 @@ scoped_refptr<UploadList> CreateCrashUploadList() {
base::PathService::Get(electron::DIR_CRASH_DUMPS, &crash_dir_path);
base::FilePath upload_log_path =
crash_dir_path.AppendASCII(CrashUploadList::kReporterLogFilename);
return base::MakeRefCounted<TextLogUploadList>(upload_log_path);
scoped_refptr<UploadList> result =
base::MakeRefCounted<TextLogUploadList>(upload_log_path);
if (crash_reporter::IsCrashpadEnabled()) {
// Crashpad keeps the records of C++ crashes (segfaults, etc) in its
// internal database. The JavaScript error reporter writes JS error upload
// records to the older text format. Combine the two to present a complete
// list to the user.
// TODO(nornagon): what is "The JavaScript error reporter", and do we care
// about it?
std::vector<scoped_refptr<UploadList>> uploaders = {
base::MakeRefCounted<CrashUploadListCrashpad>(), std::move(result)};
result = base::MakeRefCounted<CombiningUploadList>(std::move(uploaders));
}
return result;
#endif // defined(OS_MAC) || defined(OS_WIN)
}

View file

@ -298,6 +298,12 @@ breakpad::CrashHandlerHostLinux* CreateCrashHandlerHost(
}
int GetCrashSignalFD(const base::CommandLine& command_line) {
if (crash_reporter::IsCrashpadEnabled()) {
int fd;
pid_t pid;
return crash_reporter::GetHandlerSocket(&fd, &pid) ? fd : -1;
}
// Extensions have the same process type as renderers.
if (command_line.HasSwitch(extensions::switches::kExtensionProcess)) {
static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
@ -526,20 +532,37 @@ void ElectronBrowserClient::AppendExtraCommandLineSwitches(
#if defined(OS_LINUX)
bool enable_crash_reporter = false;
enable_crash_reporter = breakpad::IsCrashReporterEnabled();
if (crash_reporter::IsCrashpadEnabled()) {
command_line->AppendSwitch(::switches::kEnableCrashpad);
enable_crash_reporter = true;
int fd;
pid_t pid;
if (crash_reporter::GetHandlerSocket(&fd, &pid)) {
command_line->AppendSwitchASCII(
crash_reporter::switches::kCrashpadHandlerPid,
base::NumberToString(pid));
}
} else {
enable_crash_reporter = breakpad::IsCrashReporterEnabled();
}
if (enable_crash_reporter) {
std::string switch_value =
api::crash_reporter::GetClientId() + ",no_channel";
command_line->AppendSwitchASCII(::switches::kEnableCrashReporter,
switch_value);
for (const auto& pair : api::crash_reporter::GetGlobalCrashKeys()) {
if (!switch_value.empty())
switch_value += ",";
switch_value += pair.first;
switch_value += "=";
switch_value += pair.second;
if (!crash_reporter::IsCrashpadEnabled()) {
for (const auto& pair : api::crash_reporter::GetGlobalCrashKeys()) {
if (!switch_value.empty())
switch_value += ",";
switch_value += pair.first;
switch_value += "=";
switch_value += pair.second;
}
command_line->AppendSwitchASCII(switches::kGlobalCrashKeys, switch_value);
}
command_line->AppendSwitchASCII(switches::kGlobalCrashKeys, switch_value);
}
#endif