[Lldb-commits] [lldb] [lldb] Adds additional fields to ProcessInfo (PR #91544)

via lldb-commits lldb-commits at lists.llvm.org
Wed May 8 15:40:38 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Fred Grim (feg208)

<details>
<summary>Changes</summary>

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

---
Full diff: https://github.com/llvm/llvm-project/pull/91544.diff


4 Files Affected:

- (modified) lldb/include/lldb/Utility/ProcessInfo.h (+33) 
- (modified) lldb/source/Host/linux/Host.cpp (+15-14) 
- (modified) lldb/source/Utility/ProcessInfo.cpp (+5) 
- (modified) lldb/unittests/Host/linux/HostTest.cpp (+21) 


``````````diff
diff --git a/lldb/include/lldb/Utility/ProcessInfo.h b/lldb/include/lldb/Utility/ProcessInfo.h
index 54ac000dc7fc2..ddaa93c6d5c91 100644
--- a/lldb/include/lldb/Utility/ProcessInfo.h
+++ b/lldb/include/lldb/Utility/ProcessInfo.h
@@ -144,6 +144,19 @@ class ProcessInstanceInfo : public ProcessInfo {
     long int tv_usec = 0;
   };
 
+  enum class ProcessState {
+    Unknown,
+    Dead,
+    DiskSleep,
+    Idle,
+    Paging,
+    Parked,
+    Running,
+    Sleeping,
+    TracedOrStopped,
+    Zombie,
+  };
+
   ProcessInstanceInfo() = default;
 
   ProcessInstanceInfo(const char *name, const ArchSpec &arch, lldb::pid_t pid)
@@ -237,6 +250,24 @@ class ProcessInstanceInfo : public ProcessInfo {
            m_cumulative_system_time.tv_usec > 0;
   }
 
+  int8_t GetNiceValue() const {
+    return m_nice_value;
+  }
+
+  void SetNiceValue(int8_t nice_value) {
+    m_nice_value = nice_value;
+  }
+
+  bool NiceValueIsValid() const;
+
+  void SetIsZombie() {
+    m_zombie = true;
+  }
+
+  bool IsZombie() const {
+    return m_zombie;
+  }
+
   void Dump(Stream &s, UserIDResolver &resolver) const;
 
   static void DumpTableHeader(Stream &s, bool show_args, bool verbose);
@@ -254,6 +285,8 @@ class ProcessInstanceInfo : public ProcessInfo {
   struct timespec m_system_time {};
   struct timespec m_cumulative_user_time {};
   struct timespec m_cumulative_system_time {};
+  int8_t m_nice_value = INT8_MAX;
+  bool m_zombie = false;
 };
 
 typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList;
diff --git a/lldb/source/Host/linux/Host.cpp b/lldb/source/Host/linux/Host.cpp
index c6490f2fc9e2f..c12bd259c5a7d 100644
--- a/lldb/source/Host/linux/Host.cpp
+++ b/lldb/source/Host/linux/Host.cpp
@@ -37,18 +37,8 @@ using namespace lldb;
 using namespace lldb_private;
 
 namespace {
-enum class ProcessState {
-  Unknown,
-  Dead,
-  DiskSleep,
-  Idle,
-  Paging,
-  Parked,
-  Running,
-  Sleeping,
-  TracedOrStopped,
-  Zombie,
-};
+
+using ProcessState = typename ProcessInstanceInfo::ProcessState;
 
 constexpr int task_comm_len = 16;
 
@@ -70,6 +60,8 @@ struct StatFields {
   long unsigned stime;
   long cutime;
   long cstime;
+  long priority;
+  long nice;
   // .... other things. We don't need them below
 };
 }
@@ -92,13 +84,14 @@ static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo,
     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",
+             "%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) < 0) {
+             &stat_fields.cutime, &stat_fields.cstime, &stat_fields.priority,
+             &stat_fields.nice) < 0) {
     return false;
   }
 
@@ -115,6 +108,12 @@ static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo,
     return ts;
   };
 
+  // nice values run from 19 to -20 inclusive (in linux). In the prpsinfo struct
+  // pr_nice is a char
+  auto nice_value = static_cast<int8_t>(
+    (stat_fields.nice < 0 ? 0x80 : 0x00) | (stat_fields.nice & 0x7f)
+  );
+
   ProcessInfo.SetParentProcessID(stat_fields.ppid);
   ProcessInfo.SetProcessGroupID(stat_fields.pgrp);
   ProcessInfo.SetProcessSessionID(stat_fields.session);
@@ -122,6 +121,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.SetNiceValue(nice_value);
   switch (stat_fields.state) {
   case 'R':
     State = ProcessState::Running;
@@ -134,6 +134,7 @@ static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo,
     break;
   case 'Z':
     State = ProcessState::Zombie;
+    ProcessInfo.SetIsZombie();
     break;
   case 'X':
     State = ProcessState::Dead;
diff --git a/lldb/source/Utility/ProcessInfo.cpp b/lldb/source/Utility/ProcessInfo.cpp
index 6b2a7114dfb4c..de9992ec12f77 100644
--- a/lldb/source/Utility/ProcessInfo.cpp
+++ b/lldb/source/Utility/ProcessInfo.cpp
@@ -15,6 +15,7 @@
 #include "lldb/Utility/UserIDResolver.h"
 #include "llvm/ADT/SmallString.h"
 
+#include <sys/resource.h>
 #include <climits>
 #include <optional>
 
@@ -117,6 +118,10 @@ bool ProcessInfo::IsScriptedProcess() const {
   return m_scripted_metadata_sp && *m_scripted_metadata_sp;
 }
 
+bool ProcessInstanceInfo::NiceValueIsValid() const {
+  return m_nice_value >= PRIO_MIN && m_nice_value <= PRIO_MAX;
+}
+
 void ProcessInstanceInfo::Dump(Stream &s, UserIDResolver &resolver) const {
   if (m_pid != LLDB_INVALID_PROCESS_ID)
     s.Printf("    pid = %" PRIu64 "\n", m_pid);
diff --git a/lldb/unittests/Host/linux/HostTest.cpp b/lldb/unittests/Host/linux/HostTest.cpp
index 8ecaf3ec0decb..310e6fe3e6ed5 100644
--- a/lldb/unittests/Host/linux/HostTest.cpp
+++ b/lldb/unittests/Host/linux/HostTest.cpp
@@ -12,6 +12,10 @@
 #include "lldb/Utility/ProcessInfo.h"
 #include "gtest/gtest.h"
 
+#include <iostream>
+#include <cerrno>
+#include <sys/resource.h>
+
 using namespace lldb_private;
 
 namespace {
@@ -86,4 +90,21 @@ 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.GetNiceValue(), 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_EQ(Info.GetNiceValue(), prio - 1);
+    EXPECT_EQ(setpriority(PRIO_PROCESS, PRIO_PROCESS, prio), 0);
+  }
+  ASSERT_FALSE(Info.IsZombie());
 }

``````````

</details>


https://github.com/llvm/llvm-project/pull/91544


More information about the lldb-commits mailing list