Merge "crash_reporter: Remove Chrome collector, CrOS build files, DBus"

This commit is contained in:
Gaurav Shah 2015-08-10 22:41:26 +00:00 committed by Gerrit Code Review
commit b889d7e420
11 changed files with 7 additions and 1013 deletions

View file

@ -1,335 +0,0 @@
// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome_collector.h"
#include <pcrecpp.h>
#include <stdint.h>
#include <map>
#include <string>
#include <vector>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <chromeos/data_encoding.h>
#include <chromeos/dbus/service_constants.h>
#include <chromeos/process.h>
#include <chromeos/syslog_logging.h>
using base::FilePath;
using base::StringPrintf;
namespace {
const char kDefaultMinidumpName[] = "upload_file_minidump";
// Path to the gzip binary.
const char kGzipPath[] = "/bin/gzip";
// Filenames for logs attached to crash reports. Also used as metadata keys.
const char kChromeLogFilename[] = "chrome.txt";
const char kGpuStateFilename[] = "i915_error_state.log.xz";
// From //net/crash/collector/collector.h
const int kDefaultMaxUploadBytes = 1024 * 1024;
// Extract a string delimited by the given character, from the given offset
// into a source string. Returns false if the string is zero-sized or no
// delimiter was found.
bool GetDelimitedString(const std::string &str, char ch, size_t offset,
std::string *substr) {
size_t at = str.find_first_of(ch, offset);
if (at == std::string::npos || at == offset)
return false;
*substr = str.substr(offset, at - offset);
return true;
}
// Gets the GPU's error state from debugd and writes it to |error_state_path|.
// Returns true on success.
bool GetDriErrorState(const FilePath &error_state_path,
org::chromium::debugdProxy *proxy) {
chromeos::ErrorPtr error;
std::string error_state_str;
proxy->GetLog("i915_error_state", &error_state_str, &error);
if (error) {
LOG(ERROR) << "Error calling D-Bus proxy call to interface "
<< "'" << proxy->GetObjectPath().value() << "':"
<< error->GetMessage();
return false;
}
if (error_state_str == "<empty>")
return false;
const char kBase64Header[] = "<base64>: ";
const size_t kBase64HeaderLength = sizeof(kBase64Header) - 1;
if (error_state_str.compare(0, kBase64HeaderLength, kBase64Header)) {
LOG(ERROR) << "i915_error_state is missing base64 header";
return false;
}
std::string decoded_error_state;
if (!chromeos::data_encoding::Base64Decode(
error_state_str.c_str() + kBase64HeaderLength,
&decoded_error_state)) {
LOG(ERROR) << "Could not decode i915_error_state";
return false;
}
int written = base::WriteFile(error_state_path,
decoded_error_state.c_str(),
decoded_error_state.length());
if (written < 0 ||
static_cast<size_t>(written) != decoded_error_state.length()) {
LOG(ERROR) << "Could not write file " << error_state_path.value()
<< " Written: " << written << " Len: "
<< decoded_error_state.length();
base::DeleteFile(error_state_path, false);
return false;
}
return true;
}
// Gzip-compresses |path|, removes the original file, and returns the path of
// the new file. On failure, the original file is left alone and an empty path
// is returned.
FilePath GzipFile(const FilePath& path) {
chromeos::ProcessImpl proc;
proc.AddArg(kGzipPath);
proc.AddArg(path.value());
const int res = proc.Run();
if (res != 0) {
LOG(ERROR) << "Failed to gzip " << path.value();
return FilePath();
}
return path.AddExtension(".gz");
}
} // namespace
ChromeCollector::ChromeCollector() : output_file_ptr_(stdout) {}
ChromeCollector::~ChromeCollector() {}
bool ChromeCollector::HandleCrash(const FilePath &file_path,
const std::string &pid_string,
const std::string &uid_string,
const std::string &exe_name) {
if (!is_feedback_allowed_function_())
return true;
LOG(WARNING) << "Received crash notification for " << exe_name << "["
<< pid_string << "] user " << uid_string << " (called directly)";
if (exe_name.find('/') != std::string::npos) {
LOG(ERROR) << "exe_name contains illegal characters: " << exe_name;
return false;
}
FilePath dir;
uid_t uid = atoi(uid_string.c_str());
pid_t pid = atoi(pid_string.c_str());
if (!GetCreatedCrashDirectoryByEuid(uid, &dir, nullptr)) {
LOG(ERROR) << "Can't create crash directory for uid " << uid;
return false;
}
std::string dump_basename = FormatDumpBasename(exe_name, time(nullptr), pid);
FilePath meta_path = GetCrashPath(dir, dump_basename, "meta");
FilePath minidump_path = GetCrashPath(dir, dump_basename, "dmp");
std::string data;
if (!base::ReadFileToString(file_path, &data)) {
LOG(ERROR) << "Can't read crash log: " << file_path.value();
return false;
}
if (!ParseCrashLog(data, dir, minidump_path, dump_basename)) {
LOG(ERROR) << "Failed to parse Chrome's crash log";
return false;
}
int64_t report_size = 0;
base::GetFileSize(minidump_path, &report_size);
// Keyed by crash metadata key name.
const std::map<std::string, base::FilePath> additional_logs =
GetAdditionalLogs(dir, dump_basename, exe_name);
for (auto it : additional_logs) {
int64_t file_size = 0;
if (!base::GetFileSize(it.second, &file_size)) {
PLOG(WARNING) << "Unable to get size of " << it.second.value();
continue;
}
if (report_size + file_size > kDefaultMaxUploadBytes) {
LOG(INFO) << "Skipping upload of " << it.second.value() << "("
<< file_size << "B) because report size would exceed limit ("
<< kDefaultMaxUploadBytes << "B)";
continue;
}
VLOG(1) << "Adding metadata: " << it.first << " -> " << it.second.value();
// Call AddCrashMetaUploadFile() rather than AddCrashMetaData() here. The
// former adds a prefix to the key name; without the prefix, only the key
// "logs" appears to be displayed on the crash server.
AddCrashMetaUploadFile(it.first, it.second.value());
report_size += file_size;
}
// We're done.
WriteCrashMetaData(meta_path, exe_name, minidump_path.value());
fprintf(output_file_ptr_, "%s", kSuccessMagic);
fflush(output_file_ptr_);
return true;
}
void ChromeCollector::SetUpDBus() {
CrashCollector::SetUpDBus();
debugd_proxy_.reset(
new org::chromium::debugdProxy(bus_, debugd::kDebugdServiceName));
}
bool ChromeCollector::ParseCrashLog(const std::string &data,
const FilePath &dir,
const FilePath &minidump,
const std::string &basename) {
size_t at = 0;
while (at < data.size()) {
// Look for a : followed by a decimal number, followed by another :
// followed by N bytes of data.
std::string name, size_string;
if (!GetDelimitedString(data, ':', at, &name)) {
LOG(ERROR) << "Can't find : after name @ offset " << at;
break;
}
at += name.size() + 1; // Skip the name & : delimiter.
if (!GetDelimitedString(data, ':', at, &size_string)) {
LOG(ERROR) << "Can't find : after size @ offset " << at;
break;
}
at += size_string.size() + 1; // Skip the size & : delimiter.
size_t size;
if (!base::StringToSizeT(size_string, &size)) {
LOG(ERROR) << "String not convertible to integer: " << size_string;
break;
}
// Data would run past the end, did we get a truncated file?
if (at + size > data.size()) {
LOG(ERROR) << "Overrun, expected " << size << " bytes of data, got "
<< (data.size() - at);
break;
}
if (name.find("filename") != std::string::npos) {
// File.
// Name will be in a semi-MIME format of
// <descriptive name>"; filename="<name>"
// Descriptive name will be upload_file_minidump for the dump.
std::string desc, filename;
pcrecpp::RE re("(.*)\" *; *filename=\"(.*)\"");
if (!re.FullMatch(name.c_str(), &desc, &filename)) {
LOG(ERROR) << "Filename was not in expected format: " << name;
break;
}
if (desc.compare(kDefaultMinidumpName) == 0) {
// The minidump.
WriteNewFile(minidump, data.c_str() + at, size);
} else {
// Some other file.
FilePath path = GetCrashPath(dir, basename + "-" + filename, "other");
if (WriteNewFile(path, data.c_str() + at, size) >= 0) {
AddCrashMetaUploadFile(desc, path.value());
}
}
} else {
// Other attribute.
std::string value_str;
value_str.reserve(size);
// Since metadata is one line/value the values must be escaped properly.
for (size_t i = at; i < at + size; i++) {
switch (data[i]) {
case '"':
case '\\':
value_str.push_back('\\');
value_str.push_back(data[i]);
break;
case '\r':
value_str += "\\r";
break;
case '\n':
value_str += "\\n";
break;
case '\t':
value_str += "\\t";
break;
case '\0':
value_str += "\\0";
break;
default:
value_str.push_back(data[i]);
break;
}
}
AddCrashMetaUploadData(name, value_str);
}
at += size;
}
return at == data.size();
}
std::map<std::string, base::FilePath> ChromeCollector::GetAdditionalLogs(
const FilePath &dir,
const std::string &basename,
const std::string &exe_name) {
std::map<std::string, base::FilePath> logs;
// Run the command specified by the config file to gather logs.
const FilePath chrome_log_path =
GetCrashPath(dir, basename, kChromeLogFilename);
if (GetLogContents(log_config_path_, exe_name, chrome_log_path)) {
const FilePath compressed_path = GzipFile(chrome_log_path);
if (!compressed_path.empty())
logs[kChromeLogFilename] = compressed_path;
else
base::DeleteFile(chrome_log_path, false /* recursive */);
}
// For unit testing, debugd_proxy_ isn't initialized, so skip attempting to
// get the GPU error state from debugd.
if (debugd_proxy_) {
const FilePath dri_error_state_path =
GetCrashPath(dir, basename, kGpuStateFilename);
if (GetDriErrorState(dri_error_state_path, debugd_proxy_.get()))
logs[kGpuStateFilename] = dri_error_state_path;
}
return logs;
}
// static
const char ChromeCollector::kSuccessMagic[] = "_sys_cr_finished";

View file

@ -1,72 +0,0 @@
// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CRASH_REPORTER_CHROME_COLLECTOR_H_
#define CRASH_REPORTER_CHROME_COLLECTOR_H_
#include <map>
#include <string>
#include <base/files/file_path.h>
#include <base/macros.h>
#include <gtest/gtest_prod.h> // for FRIEND_TEST
#include "crash_collector.h"
#include "debugd/dbus-proxies.h"
class SystemLogging;
// Chrome crash collector.
class ChromeCollector : public CrashCollector {
public:
ChromeCollector();
~ChromeCollector() override;
// Magic string to let Chrome know the crash report succeeded.
static const char kSuccessMagic[];
// Handle a specific chrome crash. Returns true on success.
bool HandleCrash(const base::FilePath &file_path,
const std::string &pid_string,
const std::string &uid_string,
const std::string &exe_name);
protected:
void SetUpDBus() override;
private:
friend class ChromeCollectorTest;
FRIEND_TEST(ChromeCollectorTest, GoodValues);
FRIEND_TEST(ChromeCollectorTest, BadValues);
FRIEND_TEST(ChromeCollectorTest, Newlines);
FRIEND_TEST(ChromeCollectorTest, File);
FRIEND_TEST(ChromeCollectorTest, HandleCrash);
// Crashes are expected to be in a TLV-style format of:
// <name>:<length>:<value>
// Length is encoded as a decimal number. It can be zero, but must consist of
// at least one character
// For file values, name actually contains both a description and a filename,
// in a fixed format of: <description>"; filename="<filename>"
bool ParseCrashLog(const std::string &data, const base::FilePath &dir,
const base::FilePath &minidump,
const std::string &basename);
// Writes additional logs for |exe_name| to files based on |basename| within
// |dir|. Crash report metadata key names and the corresponding file paths are
// returned.
std::map<std::string, base::FilePath> GetAdditionalLogs(
const base::FilePath &dir,
const std::string &basename,
const std::string &exe_name);
FILE *output_file_ptr_;
// D-Bus proxy for debugd interface. Unset in unit tests.
std::unique_ptr<org::chromium::debugdProxy> debugd_proxy_;
DISALLOW_COPY_AND_ASSIGN(ChromeCollector);
};
#endif // CRASH_REPORTER_CHROME_COLLECTOR_H_

View file

@ -1,150 +0,0 @@
// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome_collector.h"
#include <stdio.h>
#include <base/auto_reset.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <chromeos/syslog_logging.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
using base::FilePath;
namespace {
const char kCrashFormatGood[] = "value1:10:abcdefghijvalue2:5:12345";
const char kCrashFormatEmbeddedNewline[] =
"value1:10:abcd\r\nghijvalue2:5:12\n34";
const char kCrashFormatBad1[] = "value1:10:abcdefghijvalue2:6=12345";
const char kCrashFormatBad2[] = "value1:10:abcdefghijvalue2:512345";
const char kCrashFormatBad3[] = "value1:10::abcdefghijvalue2:5=12345";
const char kCrashFormatBad4[] = "value1:10:abcdefghijvalue2:4=12345";
const char kCrashFormatWithFile[] =
"value1:10:abcdefghijvalue2:5:12345"
"some_file\"; filename=\"foo.txt\":15:12345\n789\n12345"
"value3:2:ok";
void CountCrash() {
}
bool s_allow_crash = false;
bool IsMetrics() {
return s_allow_crash;
}
} // namespace
class ChromeCollectorMock : public ChromeCollector {
public:
MOCK_METHOD0(SetUpDBus, void());
};
class ChromeCollectorTest : public ::testing::Test {
protected:
void ExpectFileEquals(const char *golden,
const FilePath &file_path) {
std::string contents;
EXPECT_TRUE(base::ReadFileToString(file_path, &contents));
EXPECT_EQ(golden, contents);
}
ChromeCollectorMock collector_;
private:
void SetUp() override {
EXPECT_CALL(collector_, SetUpDBus()).WillRepeatedly(testing::Return());
collector_.Initialize(CountCrash, IsMetrics);
chromeos::ClearLog();
}
};
TEST_F(ChromeCollectorTest, GoodValues) {
FilePath dir(".");
EXPECT_TRUE(collector_.ParseCrashLog(kCrashFormatGood,
dir, dir.Append("minidump.dmp"),
"base"));
// Check to see if the values made it in properly.
std::string meta = collector_.extra_metadata_;
EXPECT_TRUE(meta.find("value1=abcdefghij") != std::string::npos);
EXPECT_TRUE(meta.find("value2=12345") != std::string::npos);
}
TEST_F(ChromeCollectorTest, Newlines) {
FilePath dir(".");
EXPECT_TRUE(collector_.ParseCrashLog(kCrashFormatEmbeddedNewline,
dir, dir.Append("minidump.dmp"),
"base"));
// Check to see if the values were escaped.
std::string meta = collector_.extra_metadata_;
EXPECT_TRUE(meta.find("value1=abcd\\r\\nghij") != std::string::npos);
EXPECT_TRUE(meta.find("value2=12\\n34") != std::string::npos);
}
TEST_F(ChromeCollectorTest, BadValues) {
FilePath dir(".");
const struct {
const char *data;
} list[] = {
{kCrashFormatBad1, },
{kCrashFormatBad2, },
{kCrashFormatBad3, },
{kCrashFormatBad4, },
};
for (size_t i = 0; i < sizeof(list) / sizeof(list[0]); i++) {
chromeos::ClearLog();
EXPECT_FALSE(collector_.ParseCrashLog(list[i].data,
dir, dir.Append("minidump.dmp"),
"base"));
}
}
TEST_F(ChromeCollectorTest, File) {
base::ScopedTempDir scoped_temp_dir;
ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
const FilePath& dir = scoped_temp_dir.path();
EXPECT_TRUE(collector_.ParseCrashLog(kCrashFormatWithFile,
dir, dir.Append("minidump.dmp"),
"base"));
// Check to see if the values are still correct and that the file was
// written with the right data.
std::string meta = collector_.extra_metadata_;
EXPECT_TRUE(meta.find("value1=abcdefghij") != std::string::npos);
EXPECT_TRUE(meta.find("value2=12345") != std::string::npos);
EXPECT_TRUE(meta.find("value3=ok") != std::string::npos);
ExpectFileEquals("12345\n789\n12345", dir.Append("base-foo.txt.other"));
}
TEST_F(ChromeCollectorTest, HandleCrash) {
base::AutoReset<bool> auto_reset(&s_allow_crash, true);
base::ScopedTempDir scoped_temp_dir;
ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
const FilePath& dir = scoped_temp_dir.path();
FilePath dump_file = dir.Append("test.dmp");
ASSERT_EQ(strlen(kCrashFormatWithFile),
base::WriteFile(dump_file, kCrashFormatWithFile,
strlen(kCrashFormatWithFile)));
collector_.ForceCrashDirectory(dir);
FilePath log_file;
{
base::ScopedFILE output(
base::CreateAndOpenTemporaryFileInDir(dir, &log_file));
ASSERT_TRUE(output.get());
base::AutoReset<FILE*> auto_reset_file_ptr(&collector_.output_file_ptr_,
output.get());
EXPECT_TRUE(collector_.HandleCrash(dump_file, "123", "456", "chrome_test"));
}
ExpectFileEquals(ChromeCollector::kSuccessMagic, log_file);
}

View file

@ -1,147 +0,0 @@
{
# Shouldn't need this, but doesn't work otherwise.
# http://crbug.com/340086 and http://crbug.com/385186
# Note: the unused dependencies are optimized out by the compiler.
'target_defaults': {
'variables': {
'deps': [
'libchromeos-<(libbase_ver)',
],
},
},
'targets': [
{
'target_name': 'libcrash',
'type': 'static_library',
'variables': {
'exported_deps': [
'libchrome-<(libbase_ver)',
'libpcrecpp',
],
'deps': ['<@(exported_deps)'],
},
'all_dependent_settings': {
'variables': {
'deps': [
'<@(exported_deps)',
],
},
},
'sources': [
'chrome_collector.cc',
'crash_collector.cc',
'kernel_collector.cc',
'kernel_warning_collector.cc',
'udev_collector.cc',
'unclean_shutdown_collector.cc',
'user_collector.cc',
],
'actions': [
{
'action_name': 'generate-session-manager-proxies',
'variables': {
'proxy_output_file': 'include/session_manager/dbus-proxies.h'
},
'sources': [
'../login_manager/org.chromium.SessionManagerInterface.xml',
],
'includes': ['../common-mk/generate-dbus-proxies.gypi'],
},
{
'action_name': 'generate-debugd-proxies',
'variables': {
'proxy_output_file': 'include/debugd/dbus-proxies.h'
},
'sources': [
'../debugd/share/org.chromium.debugd.xml',
],
'includes': ['../common-mk/generate-dbus-proxies.gypi'],
},
],
},
{
'target_name': 'crash_reporter',
'type': 'executable',
'variables': {
'deps': [
'dbus-1',
'libmetrics-<(libbase_ver)',
],
},
'dependencies': [
'libcrash',
],
'sources': [
'crash_reporter.cc',
],
},
{
'target_name': 'list_proxies',
'type': 'executable',
'variables': {
'deps': [
'dbus-1',
'libchrome-<(libbase_ver)',
],
},
'sources': [
'list_proxies.cc',
],
'actions': [
{
'action_name': 'generate-lib-cros-service-proxies',
'variables': {
'proxy_output_file': 'include/libcrosservice/dbus-proxies.h'
},
'sources': [
'./dbus_bindings/org.chromium.LibCrosService.xml',
],
'includes': ['../common-mk/generate-dbus-proxies.gypi'],
},
],
},
{
'target_name': 'warn_collector',
'type': 'executable',
'variables': {
'lexer_out_dir': 'crash-reporter',
'deps': [
'libmetrics-<(libbase_ver)',
],
},
'link_settings': {
'libraries': [
'-lfl',
],
},
'sources': [
'warn_collector.l',
],
'includes': ['../common-mk/lex.gypi'],
},
],
'conditions': [
['USE_test == 1', {
'targets': [
{
'target_name': 'crash_reporter_test',
'type': 'executable',
'includes': ['../common-mk/common_test.gypi'],
'dependencies': ['libcrash'],
'sources': [
'chrome_collector_test.cc',
'crash_collector_test.cc',
'crash_collector_test.h',
'crash_reporter_logs_test.cc',
'kernel_collector_test.cc',
'kernel_collector_test.h',
'testrunner.cc',
'udev_collector_test.cc',
'unclean_shutdown_collector_test.cc',
'user_collector_test.cc',
],
},
],
}],
],
}

View file

@ -23,8 +23,6 @@
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <chromeos/cryptohome.h>
#include <chromeos/dbus/service_constants.h>
#include <chromeos/key_value_store.h>
#include <chromeos/process.h>
@ -87,8 +85,6 @@ CrashCollector::CrashCollector()
}
CrashCollector::~CrashCollector() {
if (bus_)
bus_->ShutdownAndBlock();
}
void CrashCollector::Initialize(
@ -99,21 +95,6 @@ void CrashCollector::Initialize(
count_crash_function_ = count_crash_function;
is_feedback_allowed_function_ = is_feedback_allowed_function;
SetUpDBus();
}
void CrashCollector::SetUpDBus() {
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
bus_ = new dbus::Bus(options);
CHECK(bus_->Connect());
session_manager_proxy_.reset(
new org::chromium::SessionManagerInterfaceProxy(
bus_,
login_manager::kSessionManagerServiceName));
}
int CrashCollector::WriteNewFile(const FilePath &filename,
@ -166,38 +147,6 @@ FilePath CrashCollector::GetCrashPath(const FilePath &crash_directory,
extension.c_str()));
}
bool CrashCollector::GetActiveUserSessions(
std::map<std::string, std::string> *sessions) {
chromeos::ErrorPtr error;
session_manager_proxy_->RetrieveActiveSessions(sessions, &error);
if (error) {
LOG(ERROR) << "Error calling D-Bus proxy call to interface "
<< "'" << session_manager_proxy_->GetObjectPath().value() << "':"
<< error->GetMessage();
return false;
}
return true;
}
FilePath CrashCollector::GetUserCrashPath() {
// In this multiprofile world, there is no one-specific user dir anymore.
// Ask the session manager for the active ones, then just run with the
// first result we get back.
FilePath user_path = FilePath(kFallbackUserCrashPath);
std::map<std::string, std::string> active_sessions;
if (!GetActiveUserSessions(&active_sessions) || active_sessions.empty()) {
LOG(ERROR) << "Could not get active user sessions, using default.";
return user_path;
}
user_path = chromeos::cryptohome::home::GetHashedUserPath(
active_sessions.begin()->second).Append("crash");
return user_path;
}
FilePath CrashCollector::GetCrashDirectoryInfo(
uid_t process_euid,
uid_t default_user_id,
@ -205,17 +154,11 @@ FilePath CrashCollector::GetCrashDirectoryInfo(
mode_t *mode,
uid_t *directory_owner,
gid_t *directory_group) {
// TODO(mkrebs): This can go away once Chrome crashes are handled
// normally (see crosbug.com/5872).
// Check if the user crash directory should be used. If we are
// collecting chrome crashes during autotesting, we want to put them in
// the system crash directory so they are outside the cryptohome -- in
// case we are being run during logout (see crosbug.com/18637).
if (process_euid == default_user_id && IsUserSpecificDirectoryEnabled()) {
if (process_euid == default_user_id) {
*mode = kUserCrashPathMode;
*directory_owner = default_user_id;
*directory_group = default_user_group;
return GetUserCrashPath();
return FilePath(kFallbackUserCrashPath);
} else {
*mode = kSystemCrashPathMode;
*directory_owner = kRootOwner;
@ -491,22 +434,3 @@ bool CrashCollector::IsDeveloperImage() {
return false;
return base::PathExists(FilePath(kLeaveCoreFile));
}
bool CrashCollector::ShouldHandleChromeCrashes() {
// If we're testing crash reporter itself, we don't want to allow an
// override for chrome crashes. And, let's be conservative and only
// allow an override for developer images.
if (!IsCrashTestInProgress() && IsDeveloperImage()) {
// Check if there's an override to indicate we should indeed collect
// chrome crashes. This allows the crashes to still be tracked when
// they occur in autotests. See "crosbug.com/17987".
if (base::PathExists(FilePath(kCollectChromeFile)))
return true;
}
// We default to ignoring chrome crashes.
return false;
}
bool CrashCollector::IsUserSpecificDirectoryEnabled() {
return !ShouldHandleChromeCrashes();
}

View file

@ -12,11 +12,8 @@
#include <base/files/file_path.h>
#include <base/macros.h>
#include <base/memory/scoped_ptr.h>
#include <gtest/gtest_prod.h> // for FRIEND_TEST
#include "session_manager/dbus-proxies.h"
// User crash collector.
class CrashCollector {
public:
@ -44,7 +41,6 @@ class CrashCollector {
FRIEND_TEST(CrashCollectorTest, ForkExecAndPipe);
FRIEND_TEST(CrashCollectorTest, FormatDumpBasename);
FRIEND_TEST(CrashCollectorTest, Initialize);
FRIEND_TEST(CrashCollectorTest, IsUserSpecificDirectoryEnabled);
FRIEND_TEST(CrashCollectorTest, MetaData);
FRIEND_TEST(CrashCollectorTest, Sanitize);
FRIEND_TEST(CrashCollectorTest, WriteNewFile);
@ -61,9 +57,6 @@ class CrashCollector {
// Set maximum enqueued crashes in a crash directory.
static const int kMaxCrashDirectorySize;
// Set up D-Bus.
virtual void SetUpDBus();
// Writes |data| of |size| to |filename|, which must be a new file.
// If the file already exists or writing fails, return a negative value.
// Otherwise returns the number of bytes written.
@ -79,9 +72,6 @@ class CrashCollector {
forced_crash_directory_ = forced_directory;
}
virtual bool GetActiveUserSessions(
std::map<std::string, std::string> *sessions);
base::FilePath GetUserCrashPath();
base::FilePath GetCrashDirectoryInfo(uid_t process_euid,
uid_t default_user_id,
gid_t default_user_group,
@ -154,10 +144,6 @@ class CrashCollector {
// Returns true if we should consider ourselves to be running on a
// developer image.
bool IsDeveloperImage();
// Returns true if chrome crashes should be handled.
bool ShouldHandleChromeCrashes();
// Returns true if user crash directory may be used.
bool IsUserSpecificDirectoryEnabled();
CountCrashFunction count_crash_function_;
IsFeedbackAllowedFunction is_feedback_allowed_function_;
@ -166,13 +152,7 @@ class CrashCollector {
std::string lsb_release_;
base::FilePath log_config_path_;
scoped_refptr<dbus::Bus> bus_;
private:
// D-Bus proxy for session manager interface.
std::unique_ptr<org::chromium::SessionManagerInterfaceProxy>
session_manager_proxy_;
DISALLOW_COPY_AND_ASSIGN(CrashCollector);
};

View file

@ -32,13 +32,6 @@ bool IsMetrics() {
return false;
}
bool GetActiveUserSessionsImpl(std::map<std::string, std::string> *sessions) {
char kUser[] = "chicken@butt.com";
char kHash[] = "hashcakes";
sessions->insert(std::pair<std::string, std::string>(kUser, kHash));
return true;
}
} // namespace
class CrashCollectorTest : public ::testing::Test {
@ -126,18 +119,13 @@ TEST_F(CrashCollectorTest, GetCrashDirectoryInfo) {
EXPECT_EQ(kRootUid, directory_owner);
EXPECT_EQ(kRootGid, directory_group);
EXPECT_CALL(collector_, GetActiveUserSessions(testing::_))
.WillOnce(Invoke(&GetActiveUserSessionsImpl));
EXPECT_EQ(collector_.IsUserSpecificDirectoryEnabled(), true);
path = collector_.GetCrashDirectoryInfo(kChronosUid,
kChronosUid,
kChronosGid,
&directory_mode,
&directory_owner,
&directory_group);
EXPECT_EQ("/home/user/hashcakes/crash", path.value());
EXPECT_EQ("/var/spool/crash", path.value());
EXPECT_EQ(kExpectedUserMode, directory_mode);
EXPECT_EQ(kChronosUid, directory_owner);
EXPECT_EQ(kChronosGid, directory_group);

View file

@ -16,7 +16,6 @@
#include <chromeos/syslog_logging.h>
#include <metrics/metrics_library.h>
#include "chrome_collector.h"
#include "kernel_collector.h"
#include "kernel_warning_collector.h"
#include "udev_collector.h"
@ -97,12 +96,6 @@ static void CountUserCrash() {
LOG_IF(WARNING, status != 0) << "dbus-send running failed";
}
static void CountChromeCrash() {
// For now, consider chrome crashes the same as user crashes for reporting
// purposes.
CountUserCrash();
}
static int Initialize(KernelCollector *kernel_collector,
UserCollector *user_collector,
@ -164,25 +157,6 @@ static int HandleUserCrash(UserCollector *user_collector,
return 0;
}
static int HandleChromeCrash(ChromeCollector *chrome_collector,
const std::string& chrome_dump_file,
const std::string& pid,
const std::string& uid,
const std::string& exe) {
CHECK(!chrome_dump_file.empty()) << "--chrome= must be set";
CHECK(!pid.empty()) << "--pid= must be set";
CHECK(!uid.empty()) << "--uid= must be set";
CHECK(!exe.empty()) << "--exe= must be set";
chromeos::LogToString(true);
bool handled = chrome_collector->HandleCrash(FilePath(chrome_dump_file),
pid, uid, exe);
chromeos::LogToString(false);
if (!handled)
return 1;
return 0;
}
static int HandleUdevCrash(UdevCollector *udev_collector,
const std::string& udev_event) {
// Handle a crash indicated by a udev event.
@ -258,7 +232,6 @@ int main(int argc, char *argv[]) {
DEFINE_bool(unclean_check, true, "Check for unclean shutdown");
DEFINE_string(udev, "", "Udev event description (type:device:subsystem)");
DEFINE_bool(kernel_warning, false, "Report collected kernel warning");
DEFINE_string(chrome, "", "Chrome crash dump file");
DEFINE_string(pid, "", "PID of crashing process");
DEFINE_string(uid, "", "UID of crashing process");
DEFINE_string(exe, "", "Executable name of crashing process");
@ -289,8 +262,6 @@ int main(int argc, char *argv[]) {
IsFeedbackAllowed);
UdevCollector udev_collector;
udev_collector.Initialize(CountUdevCrash, IsFeedbackAllowed);
ChromeCollector chrome_collector;
chrome_collector.Initialize(CountChromeCrash, IsFeedbackAllowed);
KernelWarningCollector kernel_warning_collector;
kernel_warning_collector.Initialize(CountUdevCrash, IsFeedbackAllowed);
@ -322,13 +293,5 @@ int main(int argc, char *argv[]) {
return HandleKernelWarning(&kernel_warning_collector);
}
if (!FLAGS_chrome.empty()) {
return HandleChromeCrash(&chrome_collector,
FLAGS_chrome,
FLAGS_pid,
FLAGS_uid,
FLAGS_exe);
}
return HandleUserCrash(&user_collector, FLAGS_user, FLAGS_crash_test);
}

View file

@ -13,14 +13,12 @@
#include <stdint.h>
#include <sys/types.h> // For getpwuid_r, getgrnam_r, WEXITSTATUS.
#include <set>
#include <string>
#include <vector>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/posix/eintr_wrapper.h>
#include <base/stl_util.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
@ -495,101 +493,11 @@ bool UserCollector::ParseCrashAttributes(const std::string &crash_attributes,
kernel_supplied_name);
}
// Returns true if the given executable name matches that of Chrome. This
// includes checks for threads that Chrome has renamed.
static bool IsChromeExecName(const std::string &exec) {
static const char *kChromeNames[] = {
"chrome",
// These are additional thread names seen in http://crash/
"MediaPipeline",
// These come from the use of base::PlatformThread::SetName() directly
"CrBrowserMain", "CrRendererMain", "CrUtilityMain", "CrPPAPIMain",
"CrPPAPIBrokerMain", "CrPluginMain", "CrWorkerMain", "CrGpuMain",
"BrokerEvent", "CrVideoRenderer", "CrShutdownDetector",
"UsbEventHandler", "CrNaClMain", "CrServiceMain",
// These thread names come from the use of base::Thread
"Gamepad polling thread", "Chrome_InProcGpuThread",
"Chrome_DragDropThread", "Renderer::FILE", "VC manager",
"VideoCaptureModuleImpl", "JavaBridge", "VideoCaptureManagerThread",
"Geolocation", "Geolocation_wifi_provider",
"Device orientation polling thread", "Chrome_InProcRendererThread",
"NetworkChangeNotifier", "Watchdog", "inotify_reader",
"cf_iexplore_background_thread", "BrowserWatchdog",
"Chrome_HistoryThread", "Chrome_SyncThread", "Chrome_ShellDialogThread",
"Printing_Worker", "Chrome_SafeBrowsingThread", "SimpleDBThread",
"D-Bus thread", "AudioThread", "NullAudioThread", "V4L2Thread",
"ChromotingClientDecodeThread", "Profiling_Flush",
"worker_thread_ticker", "AudioMixerAlsa", "AudioMixerCras",
"FakeAudioRecordingThread", "CaptureThread",
"Chrome_WebSocketproxyThread", "ProcessWatcherThread",
"Chrome_CameraThread", "import_thread", "NaCl_IOThread",
"Chrome_CloudPrintJobPrintThread", "Chrome_CloudPrintProxyCoreThread",
"DaemonControllerFileIO", "ChromotingMainThread",
"ChromotingEncodeThread", "ChromotingDesktopThread",
"ChromotingIOThread", "ChromotingFileIOThread",
"Chrome_libJingle_WorkerThread", "Chrome_ChildIOThread",
"GLHelperThread", "RemotingHostPlugin",
// "PAC thread #%d", // not easy to check because of "%d"
"Chrome_DBThread", "Chrome_WebKitThread", "Chrome_FileThread",
"Chrome_FileUserBlockingThread", "Chrome_ProcessLauncherThread",
"Chrome_CacheThread", "Chrome_IOThread", "Cache Thread", "File Thread",
"ServiceProcess_IO", "ServiceProcess_File",
"extension_crash_uploader", "gpu-process_crash_uploader",
"plugin_crash_uploader", "renderer_crash_uploader",
// These come from the use of webkit_glue::WebThreadImpl
"Compositor", "Browser Compositor",
// "WorkerPool/%d", // not easy to check because of "%d"
// These come from the use of base::Watchdog
"Startup watchdog thread Watchdog", "Shutdown watchdog thread Watchdog",
// These come from the use of AudioDeviceThread::Start
"AudioDevice", "AudioInputDevice", "AudioOutputDevice",
// These come from the use of MessageLoopFactory::GetMessageLoop
"GpuVideoDecoder", "RtcVideoDecoderThread", "PipelineThread",
"AudioDecoderThread", "VideoDecoderThread",
// These come from the use of MessageLoopFactory::GetMessageLoopProxy
"CaptureVideoDecoderThread", "CaptureVideoDecoder",
// These come from the use of base::SimpleThread
"LocalInputMonitor/%d", // "%d" gets lopped off for kernel-supplied
// These come from the use of base::DelegateSimpleThread
"ipc_channel_nacl reader thread/%d", "plugin_audio_input_thread/%d",
"plugin_audio_thread/%d",
// These come from the use of base::SequencedWorkerPool
"BrowserBlockingWorker%d/%d", // "%d" gets lopped off for kernel-supplied
};
static std::set<std::string> chrome_names;
// Initialize a set of chrome names, for efficient lookup
if (chrome_names.empty()) {
for (size_t i = 0; i < arraysize(kChromeNames); i++) {
std::string check_name(kChromeNames[i]);
chrome_names.insert(check_name);
// When checking a kernel-supplied name, it should be truncated to 15
// chars. See PR_SET_NAME in
// http://www.kernel.org/doc/man-pages/online/pages/man2/prctl.2.html,
// although that page misleads by saying "16 bytes".
chrome_names.insert("supplied_" + std::string(check_name, 0, 15));
}
}
return ContainsKey(chrome_names, exec);
}
bool UserCollector::ShouldDump(bool has_owner_consent,
bool is_developer,
bool handle_chrome_crashes,
const std::string &exec,
std::string *reason) {
reason->clear();
// Treat Chrome crashes as if the user opted-out. We stop counting Chrome
// crashes towards user crashes, so user crashes really mean non-Chrome
// user-space crashes.
if (!handle_chrome_crashes && IsChromeExecName(exec)) {
*reason = "ignoring call by kernel - chrome crash; "
"waiting for chrome to call us directly";
return false;
}
// For developer builds, we always want to keep the crash reports unless
// we're testing the crash facilities themselves. This overrides
// feedback. Crash sending still obeys consent.
@ -646,8 +554,6 @@ bool UserCollector::HandleCrash(const std::string &crash_attributes,
std::string reason;
bool dump = ShouldDump(is_feedback_allowed_function_(),
IsDeveloperImage(),
ShouldHandleChromeCrashes(),
exec,
&reason);
LOG(WARNING) << "Received crash notification for " << exec << "[" << pid

View file

@ -169,8 +169,6 @@ class UserCollector : public CrashCollector {
bool ShouldDump(bool has_owner_consent,
bool is_developer,
bool handle_chrome_crashes,
const std::string &exec,
std::string *reason);
bool generate_diagnostics_;

View file

@ -164,81 +164,20 @@ TEST_F(UserCollectorTest, ParseCrashAttributes) {
TEST_F(UserCollectorTest, ShouldDumpDeveloperImageOverridesConsent) {
std::string reason;
EXPECT_TRUE(collector_.ShouldDump(false, true, false,
"chrome-wm", &reason));
EXPECT_TRUE(collector_.ShouldDump(false, true, &reason));
EXPECT_EQ("developer build - not testing - always dumping", reason);
// When running a crash test, behave as normal.
EXPECT_FALSE(collector_.ShouldDump(false, false, false,
"chrome-wm", &reason));
EXPECT_FALSE(collector_.ShouldDump(false, false, &reason));
EXPECT_EQ("ignoring - no consent", reason);
}
TEST_F(UserCollectorTest, ShouldDumpChromeOverridesDeveloperImage) {
std::string reason;
// When running a crash test, behave as normal.
EXPECT_FALSE(collector_.ShouldDump(false, false, false,
"chrome", &reason));
EXPECT_EQ(kChromeIgnoreMsg, reason);
EXPECT_FALSE(collector_.ShouldDump(false, false, false,
"supplied_Compositor", &reason));
EXPECT_EQ(kChromeIgnoreMsg, reason);
EXPECT_FALSE(collector_.ShouldDump(false, false, false,
"supplied_PipelineThread", &reason));
EXPECT_EQ(kChromeIgnoreMsg, reason);
EXPECT_FALSE(collector_.ShouldDump(false, false, false,
"Chrome_ChildIOThread", &reason));
EXPECT_EQ(kChromeIgnoreMsg, reason);
EXPECT_FALSE(collector_.ShouldDump(false, false, false,
"supplied_Chrome_ChildIOT", &reason));
EXPECT_EQ(kChromeIgnoreMsg, reason);
EXPECT_FALSE(collector_.ShouldDump(false, false, false,
"supplied_ChromotingClien", &reason));
EXPECT_EQ(kChromeIgnoreMsg, reason);
EXPECT_FALSE(collector_.ShouldDump(false, false, false,
"supplied_LocalInputMonit", &reason));
EXPECT_EQ(kChromeIgnoreMsg, reason);
// When running a developer image, test that chrome crashes are handled
// when the "handle_chrome_crashes" flag is set.
EXPECT_TRUE(collector_.ShouldDump(false, true, true,
"chrome", &reason));
EXPECT_EQ("developer build - not testing - always dumping",
reason);
EXPECT_TRUE(collector_.ShouldDump(false, true, true,
"supplied_Compositor", &reason));
EXPECT_EQ("developer build - not testing - always dumping",
reason);
EXPECT_TRUE(collector_.ShouldDump(false, true, true,
"supplied_PipelineThread", &reason));
EXPECT_EQ("developer build - not testing - always dumping",
reason);
EXPECT_TRUE(collector_.ShouldDump(false, true, true,
"Chrome_ChildIOThread", &reason));
EXPECT_EQ("developer build - not testing - always dumping",
reason);
EXPECT_TRUE(collector_.ShouldDump(false, true, true,
"supplied_Chrome_ChildIOT", &reason));
EXPECT_EQ("developer build - not testing - always dumping",
reason);
EXPECT_TRUE(collector_.ShouldDump(false, true, true,
"supplied_ChromotingClien", &reason));
EXPECT_EQ("developer build - not testing - always dumping",
reason);
EXPECT_TRUE(collector_.ShouldDump(false, true, true,
"supplied_LocalInputMonit", &reason));
EXPECT_EQ("developer build - not testing - always dumping",
reason);
}
TEST_F(UserCollectorTest, ShouldDumpUseConsentProductionImage) {
std::string result;
EXPECT_FALSE(collector_.ShouldDump(false, false, false,
"chrome-wm", &result));
EXPECT_FALSE(collector_.ShouldDump(false, false, &result));
EXPECT_EQ("ignoring - no consent", result);
EXPECT_TRUE(collector_.ShouldDump(true, false, false,
"chrome-wm", &result));
EXPECT_TRUE(collector_.ShouldDump(true, false, &result));
EXPECT_EQ("handling", result);
}