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 @@ ...@@ -431,6 +431,7 @@
#include "chromeos/services/network_config/public/mojom/constants.mojom.h" #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/public/mojom/constants.mojom.h"
#include "chromeos/services/secure_channel/secure_channel_service.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 "components/user_manager/user_manager.h"
#include "services/service_manager/public/mojom/interface_provider_spec.mojom.h" #include "services/service_manager/public/mojom/interface_provider_spec.mojom.h"
#elif defined(OS_LINUX) #elif defined(OS_LINUX)
...@@ -2301,6 +2302,16 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches( ...@@ -2301,6 +2302,16 @@ void ChromeContentBrowserClient::AppendExtraCommandLineSwitches(
command_line->AppendSwitch(switches::kDisableBreakpad); 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( StackSamplingConfiguration::Get()->AppendCommandLineSwitchForChildProcess(
process_type, process_type,
command_line); command_line);
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
namespace crash_keys { 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 bool IsBoringSwitch(const std::string& flag) {
static const char* const kIgnoreSwitches[] = { static const char* const kIgnoreSwitches[] = {
switches::kEnableLogging, switches::kEnableLogging,
...@@ -38,6 +39,10 @@ static bool IsBoringSwitch(const std::string& flag) { ...@@ -38,6 +39,10 @@ static bool IsBoringSwitch(const std::string& flag) {
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
switches::kMetricsClientID, switches::kMetricsClientID,
#elif defined(OS_CHROMEOS) #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::kPpapiFlashArgs,
switches::kPpapiFlashPath, switches::kPpapiFlashPath,
switches::kRegisterPepperPlugins, switches::kRegisterPepperPlugins,
......
...@@ -81,7 +81,10 @@ static_library("app") { ...@@ -81,7 +81,10 @@ static_library("app") {
] ]
if (is_linux) { if (is_linux) {
deps += [ "//third_party/breakpad:client" ] deps += [
"//content/public/common",
"//third_party/breakpad:client",
]
} }
} }
......
...@@ -6,7 +6,9 @@ include_rules = [ ...@@ -6,7 +6,9 @@ include_rules = [
"+components/gwp_asan/buildflags/buildflags.h", "+components/gwp_asan/buildflags/buildflags.h",
"+components/gwp_asan/crash_handler/crash_handler.h", "+components/gwp_asan/crash_handler/crash_handler.h",
"+content/public/common/content_descriptors.h", "+content/public/common/content_descriptors.h",
"+content/public/common/content_switches.h",
"+content/public/common/result_codes.h", "+content/public/common/result_codes.h",
"+services/service_manager/embedder/switches.h",
"+third_party/crashpad", "+third_party/crashpad",
"+third_party/lss/linux_syscall_support.h", "+third_party/lss/linux_syscall_support.h",
] ]
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include "base/posix/eintr_wrapper.h" #include "base/posix/eintr_wrapper.h"
#include "base/posix/global_descriptors.h" #include "base/posix/global_descriptors.h"
#include "base/process/memory.h" #include "base/process/memory.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/threading/thread_checker.h" #include "base/threading/thread_checker.h"
...@@ -44,6 +45,8 @@ ...@@ -44,6 +45,8 @@
#include "components/crash/content/app/crash_reporter_client.h" #include "components/crash/content/app/crash_reporter_client.h"
#include "components/crash/core/common/crash_keys.h" #include "components/crash/core/common/crash_keys.h"
#include "content/public/common/content_descriptors.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/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/handler/exception_handler.h"
#include "third_party/breakpad/breakpad/src/client/linux/minidump_writer/directory_reader.h" #include "third_party/breakpad/breakpad/src/client/linux/minidump_writer/directory_reader.h"
...@@ -87,7 +90,16 @@ namespace breakpad { ...@@ -87,7 +90,16 @@ namespace breakpad {
namespace { 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"; const char kUploadURL[] = "https://clients2.google.com/cr/report";
#endif #endif
...@@ -1131,11 +1143,35 @@ void InitCrashKeys() { ...@@ -1131,11 +1143,35 @@ void InitCrashKeys() {
g_crash_key_white_list = GetCrashReporterClient()->GetCrashKeyWhiteList(); 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 // Miscellaneous initialization functions to call after Breakpad has been
// enabled. // enabled.
void PostEnableBreakpadInitialization() { void PostEnableBreakpadInitialization(
const std::string& process_type,
const base::CommandLine& parsed_command_line) {
SetProcessStartTime(); SetProcessStartTime();
g_pid = getpid(); g_pid = getpid();
SetCrashLoopBeforeTime(process_type, parsed_command_line);
base::debug::SetDumpWithoutCrashingFunction(&DumpProcess); base::debug::SetDumpWithoutCrashingFunction(&DumpProcess);
#if defined(ADDRESS_SANITIZER) #if defined(ADDRESS_SANITIZER)
...@@ -1265,13 +1301,20 @@ void ExecUploadProcessOrTerminate(const BreakpadInfo& info, ...@@ -1265,13 +1301,20 @@ void ExecUploadProcessOrTerminate(const BreakpadInfo& info,
my_strlcat(exe_flag, kExeBuf, buf_len); my_strlcat(exe_flag, kExeBuf, buf_len);
my_strlcat(exe_flag, exe_buf, 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[] = { const char* args[] = {
kCrashReporterBinary, kCrashReporterBinary,
chrome_flag, chrome_flag,
pid_flag, pid_flag,
uid_flag, uid_flag,
exe_flag, exe_flag,
nullptr, crash_loop_before_flag, // Leave last, might be nullptr.
nullptr,
}; };
static const char msg[] = "Cannot upload crash dump: cannot exec " static const char msg[] = "Cannot upload crash dump: cannot exec "
"/sbin/crash_reporter\n"; "/sbin/crash_reporter\n";
...@@ -1509,7 +1552,7 @@ const char* GetCrashingProcessName(const BreakpadInfo& info, ...@@ -1509,7 +1552,7 @@ const char* GetCrashingProcessName(const BreakpadInfo& info,
// Either way too long, or a read error. // Either way too long, or a read error.
return "chrome-crash-unknown-process"; return "chrome-crash-unknown-process";
} }
#endif #endif // defined(OS_CHROMEOS)
// Attempts to close all open file descriptors other than stdin, stdout and // Attempts to close all open file descriptors other than stdin, stdout and
// stderr (0, 1, and 2). // stderr (0, 1, and 2).
...@@ -2024,7 +2067,7 @@ void InitCrashReporter(const std::string& process_type) { ...@@ -2024,7 +2067,7 @@ void InitCrashReporter(const std::string& process_type) {
#endif // #if defined(OS_ANDROID) #endif // #if defined(OS_ANDROID)
} }
PostEnableBreakpadInitialization(); PostEnableBreakpadInitialization(process_type, parsed_command_line);
} }
void SetChannelCrashKey(const std::string& channel) { void SetChannelCrashKey(const std::string& channel) {
...@@ -2118,6 +2161,21 @@ void SuppressDumpGeneration() { ...@@ -2118,6 +2161,21 @@ void SuppressDumpGeneration() {
} }
#endif // OS_ANDROID #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() { bool IsCrashReporterEnabled() {
return g_is_crash_reporter_enabled; return g_is_crash_reporter_enabled;
} }
......
...@@ -58,6 +58,13 @@ extern void AddGpuFingerprintToMicrodumpCrashHandler( ...@@ -58,6 +58,13 @@ extern void AddGpuFingerprintToMicrodumpCrashHandler(
extern void SuppressDumpGeneration(); extern void SuppressDumpGeneration();
#endif // defined(OS_ANDROID) #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 // Checks if crash reporting is enabled. Note that this is not the same as
// being opted into metrics reporting (and crash reporting), which controls // being opted into metrics reporting (and crash reporting), which controls
// whether InitCrashReporter() is called. // whether InitCrashReporter() is called.
......
...@@ -962,6 +962,14 @@ const char kEnableAutomation[] = "enable-automation"; ...@@ -962,6 +962,14 @@ const char kEnableAutomation[] = "enable-automation";
const char kEnableSpeechDispatcher[] = "enable-speech-dispatcher"; const char kEnableSpeechDispatcher[] = "enable-speech-dispatcher";
#endif #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) #if defined(OS_WIN)
// /prefetch:# arguments to use when launching various process types. It has // /prefetch:# arguments to use when launching various process types. It has
// been observed that when file reads are consistent for 3 process launches with // been observed that when file reads are consistent for 3 process launches with
......
...@@ -271,6 +271,10 @@ CONTENT_EXPORT extern const char kRendererWaitForJavaDebugger[]; ...@@ -271,6 +271,10 @@ CONTENT_EXPORT extern const char kRendererWaitForJavaDebugger[];
CONTENT_EXPORT extern const char kEnableSpeechDispatcher[]; CONTENT_EXPORT extern const char kEnableSpeechDispatcher[];
#endif #endif
#if defined(OS_CHROMEOS)
CONTENT_EXPORT extern const char kCrashLoopBefore[];
#endif
#if defined(OS_WIN) #if defined(OS_WIN)
CONTENT_EXPORT extern const char kPrefetchArgumentRenderer[]; CONTENT_EXPORT extern const char kPrefetchArgumentRenderer[];
CONTENT_EXPORT extern const char kPrefetchArgumentGpu[]; 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