Commit 550aae05 authored by Ian Barkley-Yeung's avatar Ian Barkley-Yeung Committed by Commit Bot

Pass "--crash_loop_before" flag through to crash_reporter

ChromeOS: If the --crash_loop_before flag is present, pass its value
through to crash_reporter if the program crashes. Also, pass flag down
to appropriate children.

BUG=chromium:857317
TEST=Ran with special session_manager that always set --crash-loop-before
Confirmed flag was passed to correct children. Confirmed crash_reporter
used crash loop mode if Chrome killed.

Change-Id: Ifc2e911c466d1aadf057c66bfbf922d42d56359b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1687108Reviewed-by: default avatarJeffrey Kardatzke <jkardatzke@google.com>
Reviewed-by: default avatarKen Rockot <rockot@google.com>
Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Reviewed-by: default avatarNasko Oskov <nasko@chromium.org>
Commit-Queue: Ken Rockot <rockot@google.com>
Auto-Submit: Ian Barkley-Yeung <iby@chromium.org>
Cr-Commit-Position: refs/heads/master@{#676197}
parent 9618f4eb
......@@ -431,6 +431,7 @@
#include "chromeos/services/network_config/public/mojom/constants.mojom.h"
#include "chromeos/services/secure_channel/public/mojom/constants.mojom.h"
#include "chromeos/services/secure_channel/secure_channel_service.h"
#include "components/crash/content/app/breakpad_linux.h"
#include "components/user_manager/user_manager.h"
#include "services/service_manager/public/mojom/interface_provider_spec.mojom.h"
#elif defined(OS_LINUX)
......@@ -2301,6 +2302,16 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches(
command_line->AppendSwitch(switches::kDisableBreakpad);
}
#if defined(OS_CHROMEOS)
if (breakpad::ShouldPassCrashLoopBefore(process_type)) {
static const char* const kSwitchNames[] = {
switches::kCrashLoopBefore,
};
command_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
base::size(kSwitchNames));
}
#endif
StackSamplingConfiguration::Get()->AppendCommandLineSwitchForChildProcess(
process_type,
command_line);
......
......@@ -26,6 +26,7 @@
namespace crash_keys {
// Return true if we DON'T want to upload this flag to the crash server.
static bool IsBoringSwitch(const std::string& flag) {
static const char* const kIgnoreSwitches[] = {
switches::kEnableLogging,
......@@ -38,6 +39,10 @@ static bool IsBoringSwitch(const std::string& flag) {
#if defined(OS_MACOSX)
switches::kMetricsClientID,
#elif defined(OS_CHROMEOS)
// --crash-loop-before is a "boring" switch because it is redundant;
// crash_reporter separately informs the crash server if it is doing
// crash-loop handling.
switches::kCrashLoopBefore,
switches::kPpapiFlashArgs,
switches::kPpapiFlashPath,
switches::kRegisterPepperPlugins,
......
......@@ -81,7 +81,10 @@ static_library("app") {
]
if (is_linux) {
deps += [ "//third_party/breakpad:client" ]
deps += [
"//content/public/common",
"//third_party/breakpad:client",
]
}
}
......
......@@ -6,7 +6,9 @@ include_rules = [
"+components/gwp_asan/buildflags/buildflags.h",
"+components/gwp_asan/crash_handler/crash_handler.h",
"+content/public/common/content_descriptors.h",
"+content/public/common/content_switches.h",
"+content/public/common/result_codes.h",
"+services/service_manager/embedder/switches.h",
"+third_party/crashpad",
"+third_party/lss/linux_syscall_support.h",
]
......@@ -36,6 +36,7 @@
#include "base/posix/eintr_wrapper.h"
#include "base/posix/global_descriptors.h"
#include "base/process/memory.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_checker.h"
......@@ -44,6 +45,8 @@
#include "components/crash/content/app/crash_reporter_client.h"
#include "components/crash/core/common/crash_keys.h"
#include "content/public/common/content_descriptors.h"
#include "content/public/common/content_switches.h"
#include "services/service_manager/embedder/switches.h"
#include "third_party/breakpad/breakpad/src/client/linux/crash_generation/crash_generation_client.h"
#include "third_party/breakpad/breakpad/src/client/linux/handler/exception_handler.h"
#include "third_party/breakpad/breakpad/src/client/linux/minidump_writer/directory_reader.h"
......@@ -87,7 +90,16 @@ namespace breakpad {
namespace {
#if !defined(OS_CHROMEOS)
#if defined(OS_CHROMEOS)
// An optional UNIX timestamp passed to us from session_manager. If set,
// session_manager thinks we are in a possible crash-loop and will log the user
// out if we crash again before the indicated time. We don't actually do much
// with this value, just pass it along to crash_reporter. This should really
// be a time_t, but it's basically an opaque value (we don't anything with it
// except pass it along) and we don't have functions to deal with time_t's well,
// while we do have functions to deal with uint64_t's.
uint64_t g_crash_loop_before_time = 0;
#else
const char kUploadURL[] = "https://clients2.google.com/cr/report";
#endif
......@@ -1131,11 +1143,35 @@ void InitCrashKeys() {
g_crash_key_white_list = GetCrashReporterClient()->GetCrashKeyWhiteList();
}
void SetCrashLoopBeforeTime(const std::string& process_type,
const base::CommandLine& parsed_command_line) {
#if defined(OS_CHROMEOS)
if (!ShouldPassCrashLoopBefore(process_type)) {
return;
}
std::string crash_loop_before =
parsed_command_line.GetSwitchValueASCII(switches::kCrashLoopBefore);
if (crash_loop_before.empty()) {
return;
}
if (!base::StringToUint64(crash_loop_before, &g_crash_loop_before_time)) {
LOG(WARNING) << "Could not convert --crash-loop-before="
<< crash_loop_before << " to integer";
g_crash_loop_before_time = 0;
}
#endif // defined(OS_CHROMEOS)
}
// Miscellaneous initialization functions to call after Breakpad has been
// enabled.
void PostEnableBreakpadInitialization() {
void PostEnableBreakpadInitialization(
const std::string& process_type,
const base::CommandLine& parsed_command_line) {
SetProcessStartTime();
g_pid = getpid();
SetCrashLoopBeforeTime(process_type, parsed_command_line);
base::debug::SetDumpWithoutCrashingFunction(&DumpProcess);
#if defined(ADDRESS_SANITIZER)
......@@ -1265,12 +1301,19 @@ void ExecUploadProcessOrTerminate(const BreakpadInfo& info,
my_strlcat(exe_flag, kExeBuf, buf_len);
my_strlcat(exe_flag, exe_buf, buf_len);
char* crash_loop_before_flag = nullptr;
if (g_crash_loop_before_time != 0) {
crash_loop_before_flag = StringFromPrefixAndUint(
"--crash_loop_before=", g_crash_loop_before_time, allocator);
}
const char* args[] = {
kCrashReporterBinary,
chrome_flag,
pid_flag,
uid_flag,
exe_flag,
crash_loop_before_flag, // Leave last, might be nullptr.
nullptr,
};
static const char msg[] = "Cannot upload crash dump: cannot exec "
......@@ -1509,7 +1552,7 @@ const char* GetCrashingProcessName(const BreakpadInfo& info,
// Either way too long, or a read error.
return "chrome-crash-unknown-process";
}
#endif
#endif // defined(OS_CHROMEOS)
// Attempts to close all open file descriptors other than stdin, stdout and
// stderr (0, 1, and 2).
......@@ -2024,7 +2067,7 @@ void InitCrashReporter(const std::string& process_type) {
#endif // #if defined(OS_ANDROID)
}
PostEnableBreakpadInitialization();
PostEnableBreakpadInitialization(process_type, parsed_command_line);
}
void SetChannelCrashKey(const std::string& channel) {
......@@ -2118,6 +2161,21 @@ void SuppressDumpGeneration() {
}
#endif // OS_ANDROID
#if defined(OS_CHROMEOS)
bool ShouldPassCrashLoopBefore(const std::string& process_type) {
if (process_type == ::switches::kRendererProcess ||
process_type == ::switches::kUtilityProcess ||
process_type == ::switches::kPpapiPluginProcess ||
process_type == service_manager::switches::kZygoteProcess) {
// These process types never cause a log-out, even if they crash. So the
// normal crash handling process should work fine; we shouldn't need to
// invoke the special crash-loop mode.
return false;
}
return true;
}
#endif // defined(OS_CHROMEOS)
bool IsCrashReporterEnabled() {
return g_is_crash_reporter_enabled;
}
......
......@@ -58,6 +58,13 @@ extern void AddGpuFingerprintToMicrodumpCrashHandler(
extern void SuppressDumpGeneration();
#endif // defined(OS_ANDROID)
#if defined(OS_CHROMEOS)
// If true, processes of this type should pass crash-loop-before down to the
// crash reporter and to their children (if the children's type is a process
// type that wants crash-loop-before).
bool ShouldPassCrashLoopBefore(const std::string& process_type);
#endif
// Checks if crash reporting is enabled. Note that this is not the same as
// being opted into metrics reporting (and crash reporting), which controls
// whether InitCrashReporter() is called.
......
......@@ -962,6 +962,14 @@ const char kEnableAutomation[] = "enable-automation";
const char kEnableSpeechDispatcher[] = "enable-speech-dispatcher";
#endif
#if defined(OS_CHROMEOS)
// A time_t. Passed by session_manager into the Chrome user session, indicating
// that if Chrome crashes before the indicated time, session_manager will
// consider this to be a crash-loop situation and log the user out. Chrome
// mostly just passes this to crash_reporter if it crashes.
const char kCrashLoopBefore[] = "crash-loop-before";
#endif
#if defined(OS_WIN)
// /prefetch:# arguments to use when launching various process types. It has
// been observed that when file reads are consistent for 3 process launches with
......
......@@ -271,6 +271,10 @@ CONTENT_EXPORT extern const char kRendererWaitForJavaDebugger[];
CONTENT_EXPORT extern const char kEnableSpeechDispatcher[];
#endif
#if defined(OS_CHROMEOS)
CONTENT_EXPORT extern const char kCrashLoopBefore[];
#endif
#if defined(OS_WIN)
CONTENT_EXPORT extern const char kPrefetchArgumentRenderer[];
CONTENT_EXPORT extern const char kPrefetchArgumentGpu[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment