summaryrefslogtreecommitdiff
path: root/runtime/exec_utils.cc
diff options
context:
space:
mode:
author Jiakai Zhang <jiakaiz@google.com> 2023-12-06 14:58:01 +0000
committer Jiakai Zhang <jiakaiz@google.com> 2023-12-07 15:27:50 +0000
commitd358b579a98f8dcc5e1ba6678649543df51f7af5 (patch)
treebb5b6186696c67483d04875f0ffb3d97663ee99c /runtime/exec_utils.cc
parent27e688ccbaa6dfc8260e7c2905df98e6b86ec764 (diff)
Make ProcessStat collection more robust.
- Handle the case where start time is 0. - Handle the case where getting uptime failed. - Use 64bit int. (32bit is enough to record a time less than 24 days, but just in case.) Bug: 315061143 Test: m test-art-host-gtest-art_runtime_tests Change-Id: I3ac546f6921b8d6add2491170b5d8f50cc7169c1
Diffstat (limited to 'runtime/exec_utils.cc')
-rw-r--r--runtime/exec_utils.cc26
1 files changed, 19 insertions, 7 deletions
diff --git a/runtime/exec_utils.cc b/runtime/exec_utils.cc
index 1021429460..b4d6553279 100644
--- a/runtime/exec_utils.cc
+++ b/runtime/exec_utils.cc
@@ -21,9 +21,6 @@
#include <sys/wait.h>
#include <unistd.h>
-#include <ctime>
-#include <string_view>
-
#ifdef __BIONIC__
#include <sys/pidfd.h>
#endif
@@ -32,8 +29,12 @@
#include <climits>
#include <condition_variable>
#include <cstdint>
+#include <cstring>
+#include <ctime>
#include <mutex>
+#include <optional>
#include <string>
+#include <string_view>
#include <thread>
#include <vector>
@@ -232,6 +233,11 @@ bool ParseProcStat(const std::string& stat_content,
!ParseInt(stat_fields[21 - kSkippedFields], &starttime)) {
return false;
}
+ if (starttime == 0) {
+ // The start time is the time the process started after system boot, so it's not supposed to be
+ // zero unless the process is `init`.
+ return false;
+ }
stat->cpu_time_ms = (utime + stime + cutime + cstime) * 1000 / ticks_per_sec;
stat->wall_time_ms = uptime_ms - starttime * 1000 / ticks_per_sec;
return true;
@@ -338,9 +344,12 @@ std::string ExecUtils::GetProcStat(pid_t pid) const {
return stat_content;
}
-int64_t ExecUtils::GetUptimeMs() const {
+std::optional<int64_t> ExecUtils::GetUptimeMs(std::string* error_msg) const {
timespec t;
- clock_gettime(CLOCK_MONOTONIC, &t);
+ if (clock_gettime(CLOCK_MONOTONIC, &t) != 0) {
+ *error_msg = ART_FORMAT("Failed to get uptime: {}", strerror(errno));
+ return std::nullopt;
+ }
return t.tv_sec * 1000 + t.tv_nsec / 1000000;
}
@@ -349,14 +358,17 @@ int64_t ExecUtils::GetTicksPerSec() const { return sysconf(_SC_CLK_TCK); }
bool ExecUtils::GetStat(pid_t pid,
/*out*/ ProcessStat* stat,
/*out*/ std::string* error_msg) const {
- int64_t uptime_ms = GetUptimeMs();
+ std::optional<int64_t> uptime_ms = GetUptimeMs(error_msg);
+ if (!uptime_ms.has_value()) {
+ return false;
+ }
std::string stat_content = GetProcStat(pid);
if (stat_content.empty()) {
*error_msg = StringPrintf("Failed to read /proc/%d/stat: %s", pid, strerror(errno));
return false;
}
int64_t ticks_per_sec = GetTicksPerSec();
- if (!ParseProcStat(stat_content, uptime_ms, ticks_per_sec, stat)) {
+ if (!ParseProcStat(stat_content, *uptime_ms, ticks_per_sec, stat)) {
*error_msg = StringPrintf("Failed to parse /proc/%d/stat '%s'", pid, stat_content.c_str());
return false;
}