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>
diff --git a/crash_reporter/chrome_collector.cc b/crash_reporter/chrome_collector.cc
index 438ecbc..21cc852 100644
--- a/crash_reporter/chrome_collector.cc
+++ b/crash_reporter/chrome_collector.cc
@@ -42,8 +42,25 @@
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 @@
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 @@
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 @@
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 @@
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";
diff --git a/crash_reporter/chrome_collector.h b/crash_reporter/chrome_collector.h
index d8602b9..67b5aab 100644
--- a/crash_reporter/chrome_collector.h
+++ b/crash_reporter/chrome_collector.h
@@ -48,6 +48,12 @@
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);
diff --git a/crash_reporter/crash_reporter_logs.conf b/crash_reporter/crash_reporter_logs.conf
index e4ad207..db0c116 100644
--- a/crash_reporter/crash_reporter_logs.conf
+++ b/crash_reporter/crash_reporter_logs.conf
@@ -20,6 +20,10 @@
# 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