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
This commit is contained in:
Josh Gao 2021-03-01 23:13:13 -08:00
parent 8b0a9e06ba
commit dbb83de0d5
4 changed files with 33 additions and 1 deletions

View file

@ -238,6 +238,7 @@ cc_library_static {
"gwp_asan_crash_handler",
"libscudo",
"libtombstone_proto",
"libprocinfo",
"libprotobuf-cpp-lite",
],

View file

@ -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);

View file

@ -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();

View file

@ -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 {