From dbb83de0d509fa1e8209f70c3f04d9da0476da41 Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Mon, 1 Mar 2021 23:13:13 -0800 Subject: [PATCH] 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 --- debuggerd/Android.bp | 1 + debuggerd/libdebuggerd/tombstone_proto.cpp | 27 +++++++++++++++++++ .../libdebuggerd/tombstone_proto_to_text.cpp | 1 + debuggerd/proto/tombstone.proto | 5 +++- 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp index fb274ec03..7b6f6c067 100644 --- a/debuggerd/Android.bp +++ b/debuggerd/Android.bp @@ -238,6 +238,7 @@ cc_library_static { "gwp_asan_crash_handler", "libscudo", "libtombstone_proto", + "libprocinfo", "libprotobuf-cpp-lite", ], diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp index bb3c7eae0..2ed9ea5da 100644 --- a/debuggerd/libdebuggerd/tombstone_proto.cpp +++ b/debuggerd/libdebuggerd/tombstone_proto.cpp @@ -29,10 +29,12 @@ #include #include +#include #include #include +#include #include #include #include @@ -44,6 +46,7 @@ #include #include +#include #include #include #include @@ -422,6 +425,14 @@ static void dump_logcat(Tombstone* tombstone, pid_t pid) { dump_log_file(tombstone, "main", pid); } +static std::optional 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& 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 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); diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp index 187379daf..d97dae767 100644 --- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp +++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp @@ -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(); diff --git a/debuggerd/proto/tombstone.proto b/debuggerd/proto/tombstone.proto index 2c7156bcb..57a3b3e62 100644 --- a/debuggerd/proto/tombstone.proto +++ b/debuggerd/proto/tombstone.proto @@ -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 {