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

Commit dbb83de0 authored by Josh Gao's avatar Josh Gao
Browse files

libdebuggerd: store process uptime.

Application developers would like to know how long their process has
been alive for to distinguish between crashes that happen immediately
upon startup and crashes in regular operation.

Test: manual
Change-Id: Ia31eeadfcced358b478c7a7c7bb2e8a0252e30f4
parent 8b0a9e06
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -238,6 +238,7 @@ cc_library_static {
        "gwp_asan_crash_handler",
        "libscudo",
        "libtombstone_proto",
        "libprocinfo",
        "libprotobuf-cpp-lite",
    ],

+27 −0
Original line number Diff line number Diff line
@@ -29,10 +29,12 @@
#include <time.h>

#include <memory>
#include <optional>
#include <string>

#include <async_safe/log.h>

#include <android-base/file.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -44,6 +46,7 @@
#include <log/logprint.h>
#include <private/android_filesystem_config.h>

#include <procinfo/process.h>
#include <unwindstack/Maps.h>
#include <unwindstack/Memory.h>
#include <unwindstack/Regs.h>
@@ -422,6 +425,14 @@ static void dump_logcat(Tombstone* tombstone, pid_t pid) {
  dump_log_file(tombstone, "main", pid);
}

static std::optional<uint64_t> read_uptime_secs() {
  std::string uptime;
  if (!android::base::ReadFileToString("/proc/uptime", &uptime)) {
    return {};
  }
  return strtoll(uptime.c_str(), nullptr, 10);
}

void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::Unwinder* unwinder,
                             const std::map<pid_t, ThreadInfo>& threads, pid_t target_thread,
                             const ProcessInfo& process_info, const OpenFilesList* open_files) {
@@ -432,6 +443,22 @@ void engrave_tombstone_proto(Tombstone* tombstone, unwindstack::Unwinder* unwind
  result.set_revision(android::base::GetProperty("ro.revision", "unknown"));
  result.set_timestamp(get_timestamp());

  std::optional<uint64_t> system_uptime = read_uptime_secs();
  if (system_uptime) {
    android::procinfo::ProcessInfo proc_info;
    std::string error;
    if (android::procinfo::GetProcessInfo(target_thread, &proc_info, &error)) {
      uint64_t starttime = proc_info.starttime / sysconf(_SC_CLK_TCK);
      result.set_process_uptime(*system_uptime - starttime);
    } else {
      async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to read process info: %s",
                            error.c_str());
    }
  } else {
    async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "failed to read /proc/uptime: %s",
                          strerror(errno));
  }

  const ThreadInfo& main_thread = threads.at(target_thread);
  result.set_pid(main_thread.pid);
  result.set_tid(main_thread.tid);
+1 −0
Original line number Diff line number Diff line
@@ -313,6 +313,7 @@ bool tombstone_proto_to_text(const Tombstone& tombstone, CallbackType callback)
  CBL("Revision: '%s'", tombstone.revision().c_str());
  CBL("ABI: '%s'", abi_string(tombstone));
  CBL("Timestamp: %s", tombstone.timestamp().c_str());
  CBL("Process uptime: %ds", tombstone.process_uptime());

  // Process header
  const auto& threads = tombstone.threads();
+4 −1
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ message Tombstone {

  string process_name = 9;

  // Process uptime in seconds.
  uint32 process_uptime = 20;

  Signal signal_info = 10;
  string abort_message = 14;
  Cause cause = 15;
@@ -28,7 +31,7 @@ message Tombstone {
  repeated LogBuffer log_buffers = 18;
  repeated FD open_fds = 19;

  reserved 20 to 999;
  reserved 21 to 999;
}

enum Architecture {