crash-reporter: Attach Chrome logs to crash reports.

When Chrome crashes, gather the last 20 lines of each of the
latest two log files in /var/log/chrome and
/home/chronos/user/log and include them in the archive file
that's attached to crash reports.

BUG=chromium:405732
TEST=triggered crashes at the login screen and after logging
     in and verified that logs were included in crash
     reports: bdf766f0d6d1e066, a9d410e1a86f996b

Change-Id: I09e3cee23af108dc216d64aae85d78751d5649d4
Reviewed-on: https://chromium-review.googlesource.com/216427
Reviewed-by: Ben Chan <benchan@chromium.org>
Tested-by: Daniel Erat <derat@chromium.org>
Commit-Queue: Daniel Erat <derat@chromium.org>
This commit is contained in:
Daniel Erat 2014-09-02 17:06:24 -07:00 committed by chrome-internal-fetch
parent c8cb4ac7ba
commit 55cb40aa95
3 changed files with 70 additions and 44 deletions

View File

@ -42,8 +42,25 @@ bool GetDelimitedString(const std::string &str, char ch, size_t offset,
return true;
}
bool GetDriErrorState(const chromeos::dbus::Proxy &proxy,
const FilePath &error_state_path) {
// 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) {
chromeos::dbus::BusConnection dbus = chromeos::dbus::GetSystemBusConnection();
if (!dbus.HasConnection()) {
LOG(ERROR) << "Error connecting to system D-Bus";
return false;
}
chromeos::dbus::Proxy proxy(dbus,
debugd::kDebugdServiceName,
debugd::kDebugdServicePath,
debugd::kDebugdInterface);
if (!proxy) {
LOG(ERROR) << "Error creating D-Bus proxy to interface "
<< "'" << debugd::kDebugdServiceName << "'";
return false;
}
chromeos::glib::ScopedError error;
gchar *error_state = NULL;
if (!dbus_g_proxy_call(proxy.gproxy(), debugd::kGetLog,
@ -88,46 +105,6 @@ bool GetDriErrorState(const chromeos::dbus::Proxy &proxy,
return true;
}
bool GetAdditionalLogs(const FilePath &log_path) {
chromeos::dbus::BusConnection dbus = chromeos::dbus::GetSystemBusConnection();
if (!dbus.HasConnection()) {
LOG(ERROR) << "Error connecting to system D-Bus";
return false;
}
chromeos::dbus::Proxy proxy(dbus,
debugd::kDebugdServiceName,
debugd::kDebugdServicePath,
debugd::kDebugdInterface);
if (!proxy) {
LOG(ERROR) << "Error creating D-Bus proxy to interface "
<< "'" << debugd::kDebugdServiceName << "'";
return false;
}
FilePath error_state_path =
log_path.DirName().Append("i915_error_state.log.xz");
if (!GetDriErrorState(proxy, error_state_path))
return false;
chromeos::ProcessImpl tar_process;
tar_process.AddArg(kTarPath);
tar_process.AddArg("cfJ");
tar_process.AddArg(log_path.value());
tar_process.AddStringOption("-C", log_path.DirName().value());
tar_process.AddArg(error_state_path.BaseName().value());
int res = tar_process.Run();
base::DeleteFile(error_state_path, false);
if (res || !base::PathExists(log_path)) {
LOG(ERROR) << "Could not tar file " << log_path.value();
return false;
}
return true;
}
} // namespace
@ -158,7 +135,7 @@ bool ChromeCollector::HandleCrash(const FilePath &file_path,
std::string dump_basename = FormatDumpBasename(exe_name, time(NULL), pid);
FilePath meta_path = GetCrashPath(dir, dump_basename, "meta");
FilePath minidump_path = GetCrashPath(dir, dump_basename, "dmp");
FilePath log_path = GetCrashPath(dir, dump_basename, "log.tar.xz");
FilePath log_path = GetCrashPath(dir, dump_basename, "log.tar.gz");
std::string data;
if (!base::ReadFileToString(file_path, &data)) {
@ -171,7 +148,7 @@ bool ChromeCollector::HandleCrash(const FilePath &file_path,
return false;
}
if (GetAdditionalLogs(log_path)) {
if (GetAdditionalLogs(log_path, exe_name)) {
int64_t minidump_size = 0;
int64_t log_size = 0;
if (base::GetFileSize(minidump_path, &minidump_size) &&
@ -295,5 +272,44 @@ bool ChromeCollector::ParseCrashLog(const std::string &data,
return at == data.size();
}
bool ChromeCollector::GetAdditionalLogs(const FilePath &log_path,
const std::string &exe_name) {
std::vector<base::FilePath> logs_to_compress;
// Run the command specified by the config file to gather logs.
const FilePath gathered_logs_path =
log_path.DirName().Append("gathered_logs.txt");
if (GetLogContents(log_config_path_, exe_name, gathered_logs_path))
logs_to_compress.push_back(gathered_logs_path);
// Now get the GPU state from debugd.
const FilePath dri_error_state_path =
log_path.DirName().Append("i915_error_state.log.xz");
if (GetDriErrorState(dri_error_state_path))
logs_to_compress.push_back(dri_error_state_path);
if (logs_to_compress.empty())
return false;
chromeos::ProcessImpl tar_process;
tar_process.AddArg(kTarPath);
tar_process.AddArg("cfz");
tar_process.AddArg(log_path.value());
tar_process.AddStringOption("-C", log_path.DirName().value());
for (size_t i = 0; i < logs_to_compress.size(); ++i)
tar_process.AddArg(logs_to_compress[i].BaseName().value());
int res = tar_process.Run();
for (size_t i = 0; i < logs_to_compress.size(); ++i)
base::DeleteFile(logs_to_compress[i], false);
if (res || !base::PathExists(log_path)) {
LOG(ERROR) << "Could not create tar archive " << log_path.value();
return false;
}
return true;
}
// static
const char ChromeCollector::kSuccessMagic[] = "_sys_cr_finished";

View File

@ -48,6 +48,12 @@ class ChromeCollector : public CrashCollector {
const base::FilePath &minidump,
const std::string &basename);
// Gathers additional logs for |exe_name| and compresses them into a .tar.gz
// archive at |log_path|. Returns true if the log archive was created
// successfully.
bool GetAdditionalLogs(const base::FilePath &log_path,
const std::string &exe_name);
FILE *output_file_ptr_;
DISALLOW_COPY_AND_ASSIGN(ChromeCollector);

View File

@ -20,6 +20,10 @@ update_engine:cat $(ls -1tr /var/log/update_engine | tail -5 | sed s.^./var/log/
# so it is handled in the same way as update_engine.
cros_installer:cat $(ls -1tr /var/log/update_engine | tail -5 | sed s.^./var/log/update_engine/.) | tail -c 50000
# Dump the last 20 lines of the last two files in Chrome's system and user log
# directories.
chrome:for f in $(ls -1rt /var/log/chrome/chrome_[0-9]* | tail -2) $(ls -1rt /home/chronos/u-*/log/chrome_[0-9]* | tail -2); do echo "===$f (tail)==="; tail -20 $f; echo EOF; done
# The following rule is used for generating additional diagnostics when
# collection of user crashes fails. This output should not be too large
# as it is stored in memory. The output format specified for 'ps' is the