Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 55cb40aa authored by Daniel Erat's avatar Daniel Erat Committed by chrome-internal-fetch
Browse files

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: default avatarBen Chan <benchan@chromium.org>
Tested-by: default avatarDaniel Erat <derat@chromium.org>
Commit-Queue: Daniel Erat <derat@chromium.org>
parent c8cb4ac7
Loading
Loading
Loading
Loading
+60 −44
Original line number Diff line number Diff line
@@ -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";
+6 −0
Original line number Diff line number Diff line
@@ -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);
+4 −0
Original line number Diff line number Diff line
@@ -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