[Lldb-commits] [lldb] 8f74725 - [lldb] Adds additional fields to ProcessInfo (#91544)
via lldb-commits
lldb-commits at lists.llvm.org
Fri Jun 14 18:30:26 PDT 2024
Author: Fred Grim
Date: 2024-06-14T18:30:23-07:00
New Revision: 8f74725731bf431fb97929e1dd962e9a0db20865
URL: https://github.com/llvm/llvm-project/commit/8f74725731bf431fb97929e1dd962e9a0db20865
DIFF: https://github.com/llvm/llvm-project/commit/8f74725731bf431fb97929e1dd962e9a0db20865.diff
LOG: [lldb] Adds additional fields to ProcessInfo (#91544)
To implement SaveCore for elf binaries we need to populate some
additional fields in the prpsinfo struct. Those fields are the nice
value of the process whose core is to be taken as well as a boolean flag
indicating whether or not that process is a zombie. This commit adds
those as well as tests to ensure that the values are consistent with
expectations
Added:
Modified:
lldb/include/lldb/Utility/ProcessInfo.h
lldb/source/Host/linux/Host.cpp
lldb/source/Utility/ProcessInfo.cpp
lldb/unittests/Host/linux/HostTest.cpp
Removed:
################################################################################
diff --git a/lldb/include/lldb/Utility/ProcessInfo.h b/lldb/include/lldb/Utility/ProcessInfo.h
index 54ac000dc7fc2..78ade4bbb1ee6 100644
--- a/lldb/include/lldb/Utility/ProcessInfo.h
+++ b/lldb/include/lldb/Utility/ProcessInfo.h
@@ -15,6 +15,7 @@
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/NameMatches.h"
#include "lldb/Utility/StructuredData.h"
+#include <optional>
#include <vector>
namespace lldb_private {
@@ -147,8 +148,7 @@ class ProcessInstanceInfo : public ProcessInfo {
ProcessInstanceInfo() = default;
ProcessInstanceInfo(const char *name, const ArchSpec &arch, lldb::pid_t pid)
- : ProcessInfo(name, arch, pid), m_euid(UINT32_MAX), m_egid(UINT32_MAX),
- m_parent_pid(LLDB_INVALID_PROCESS_ID) {}
+ : ProcessInfo(name, arch, pid) {}
void Clear() {
ProcessInfo::Clear();
@@ -237,6 +237,16 @@ class ProcessInstanceInfo : public ProcessInfo {
m_cumulative_system_time.tv_usec > 0;
}
+ std::optional<int8_t> GetPriorityValue() const { return m_priority_value; }
+
+ void SetPriorityValue(int8_t priority_value) {
+ m_priority_value = priority_value;
+ }
+
+ void SetIsZombie(bool is_zombie) { m_zombie = is_zombie; }
+
+ std::optional<bool> IsZombie() const { return m_zombie; }
+
void Dump(Stream &s, UserIDResolver &resolver) const;
static void DumpTableHeader(Stream &s, bool show_args, bool verbose);
@@ -250,10 +260,12 @@ class ProcessInstanceInfo : public ProcessInfo {
lldb::pid_t m_parent_pid = LLDB_INVALID_PROCESS_ID;
lldb::pid_t m_process_group_id = LLDB_INVALID_PROCESS_ID;
lldb::pid_t m_process_session_id = LLDB_INVALID_PROCESS_ID;
- struct timespec m_user_time {};
- struct timespec m_system_time {};
- struct timespec m_cumulative_user_time {};
- struct timespec m_cumulative_system_time {};
+ struct timespec m_user_time;
+ struct timespec m_system_time;
+ struct timespec m_cumulative_user_time;
+ struct timespec m_cumulative_system_time;
+ std::optional<int8_t> m_priority_value = std::nullopt;
+ std::optional<bool> m_zombie = std::nullopt;
};
typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList;
diff --git a/lldb/source/Host/linux/Host.cpp b/lldb/source/Host/linux/Host.cpp
index c6490f2fc9e2f..5545f9ef4d70e 100644
--- a/lldb/source/Host/linux/Host.cpp
+++ b/lldb/source/Host/linux/Host.cpp
@@ -37,6 +37,7 @@ using namespace lldb;
using namespace lldb_private;
namespace {
+
enum class ProcessState {
Unknown,
Dead,
@@ -70,6 +71,12 @@ struct StatFields {
long unsigned stime;
long cutime;
long cstime;
+ // In proc_pid_stat(5) this field is specified as priority
+ // but documented as realtime priority. To keep with the adopted
+ // nomenclature in ProcessInstanceInfo, we adopt the documented
+ // naming here.
+ long realtime_priority;
+ long priority;
// .... other things. We don't need them below
};
}
@@ -91,14 +98,16 @@ static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo,
if (Rest.empty())
return false;
StatFields stat_fields;
- if (sscanf(Rest.data(),
- "%d %s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %ld %ld",
- &stat_fields.pid, stat_fields.comm, &stat_fields.state,
- &stat_fields.ppid, &stat_fields.pgrp, &stat_fields.session,
- &stat_fields.tty_nr, &stat_fields.tpgid, &stat_fields.flags,
- &stat_fields.minflt, &stat_fields.cminflt, &stat_fields.majflt,
- &stat_fields.cmajflt, &stat_fields.utime, &stat_fields.stime,
- &stat_fields.cutime, &stat_fields.cstime) < 0) {
+ if (sscanf(
+ Rest.data(),
+ "%d %s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld",
+ &stat_fields.pid, stat_fields.comm, &stat_fields.state,
+ &stat_fields.ppid, &stat_fields.pgrp, &stat_fields.session,
+ &stat_fields.tty_nr, &stat_fields.tpgid, &stat_fields.flags,
+ &stat_fields.minflt, &stat_fields.cminflt, &stat_fields.majflt,
+ &stat_fields.cmajflt, &stat_fields.utime, &stat_fields.stime,
+ &stat_fields.cutime, &stat_fields.cstime,
+ &stat_fields.realtime_priority, &stat_fields.priority) < 0) {
return false;
}
@@ -115,6 +124,11 @@ static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo,
return ts;
};
+ // Priority (nice) values run from 19 to -20 inclusive (in linux). In the
+ // prpsinfo struct pr_nice is a char.
+ auto priority_value = static_cast<int8_t>(
+ (stat_fields.priority < 0 ? 0x80 : 0x00) | (stat_fields.priority & 0x7f));
+
ProcessInfo.SetParentProcessID(stat_fields.ppid);
ProcessInfo.SetProcessGroupID(stat_fields.pgrp);
ProcessInfo.SetProcessSessionID(stat_fields.session);
@@ -122,6 +136,7 @@ static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo,
ProcessInfo.SetSystemTime(convert(stat_fields.stime));
ProcessInfo.SetCumulativeUserTime(convert(stat_fields.cutime));
ProcessInfo.SetCumulativeSystemTime(convert(stat_fields.cstime));
+ ProcessInfo.SetPriorityValue(priority_value);
switch (stat_fields.state) {
case 'R':
State = ProcessState::Running;
@@ -156,6 +171,7 @@ static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo,
State = ProcessState::Unknown;
break;
}
+ ProcessInfo.SetIsZombie(State == ProcessState::Zombie);
if (State == ProcessState::Unknown) {
LLDB_LOG(log, "Unknown process state {0}", stat_fields.state);
diff --git a/lldb/source/Utility/ProcessInfo.cpp b/lldb/source/Utility/ProcessInfo.cpp
index 6b2a7114dfb4c..845b337e246f1 100644
--- a/lldb/source/Utility/ProcessInfo.cpp
+++ b/lldb/source/Utility/ProcessInfo.cpp
@@ -121,8 +121,8 @@ void ProcessInstanceInfo::Dump(Stream &s, UserIDResolver &resolver) const {
if (m_pid != LLDB_INVALID_PROCESS_ID)
s.Printf(" pid = %" PRIu64 "\n", m_pid);
- if (m_parent_pid != LLDB_INVALID_PROCESS_ID)
- s.Printf(" parent = %" PRIu64 "\n", m_parent_pid);
+ if (ParentProcessIDIsValid())
+ s.Printf(" parent = %" PRIu64 "\n", GetParentProcessID());
if (m_executable) {
s.Printf(" name = %s\n", m_executable.GetFilename().GetCString());
@@ -193,7 +193,8 @@ void ProcessInstanceInfo::DumpTableHeader(Stream &s, bool show_args,
void ProcessInstanceInfo::DumpAsTableRow(Stream &s, UserIDResolver &resolver,
bool show_args, bool verbose) const {
if (m_pid != LLDB_INVALID_PROCESS_ID) {
- s.Printf("%-6" PRIu64 " %-6" PRIu64 " ", m_pid, m_parent_pid);
+ s.Printf("%-6" PRIu64 " %-6" PRIu64 " ", m_pid,
+ (ParentProcessIDIsValid()) ? GetParentProcessID() : 0);
StreamString arch_strm;
if (m_arch.IsValid())
diff --git a/lldb/unittests/Host/linux/HostTest.cpp b/lldb/unittests/Host/linux/HostTest.cpp
index 8ecaf3ec0decb..d6aefcc7faa25 100644
--- a/lldb/unittests/Host/linux/HostTest.cpp
+++ b/lldb/unittests/Host/linux/HostTest.cpp
@@ -12,6 +12,9 @@
#include "lldb/Utility/ProcessInfo.h"
#include "gtest/gtest.h"
+#include <cerrno>
+#include <sys/resource.h>
+
using namespace lldb_private;
namespace {
@@ -86,4 +89,23 @@ TEST_F(HostTest, GetProcessInfo) {
ProcessInstanceInfo::timespec next_user_time = Info.GetUserTime();
ASSERT_TRUE(user_time.tv_sec <= next_user_time.tv_sec ||
user_time.tv_usec <= next_user_time.tv_usec);
+
+ struct rlimit rlim;
+ EXPECT_EQ(getrlimit(RLIMIT_NICE, &rlim), 0);
+ // getpriority can return -1 so we zero errno first
+ errno = 0;
+ int prio = getpriority(PRIO_PROCESS, PRIO_PROCESS);
+ ASSERT_TRUE((prio < 0 && errno == 0) || prio >= 0);
+ ASSERT_EQ(Info.GetPriorityValue(), prio);
+ // If we can't raise our nice level then this test can't be performed.
+ int max_incr = PRIO_MAX - rlim.rlim_cur;
+ if (max_incr < prio) {
+ EXPECT_EQ(setpriority(PRIO_PROCESS, PRIO_PROCESS, prio - 1), 0);
+ ASSERT_TRUE(Host::GetProcessInfo(getpid(), Info));
+ ASSERT_TRUE(Info.GetPriorityValue().has_value());
+ ASSERT_EQ(Info.GetPriorityValue().value(), prio - 1);
+ EXPECT_EQ(setpriority(PRIO_PROCESS, PRIO_PROCESS, prio), 0);
+ }
+ ASSERT_TRUE(Info.IsZombie().has_value());
+ ASSERT_FALSE(Info.IsZombie().value());
}
More information about the lldb-commits
mailing list