@@ -49,6 +49,29 @@ enum class ProcessState {
4949 TracedOrStopped,
5050 Zombie,
5151};
52+
53+ constexpr int task_comm_len = 16 ;
54+
55+ struct StatFields {
56+ ::pid_t pid = LLDB_INVALID_PROCESS_ID;
57+ char comm[task_comm_len];
58+ char state;
59+ ::pid_t ppid = LLDB_INVALID_PROCESS_ID;
60+ ::pid_t pgrp = LLDB_INVALID_PROCESS_ID;
61+ ::pid_t session = LLDB_INVALID_PROCESS_ID;
62+ int tty_nr;
63+ int tpgid;
64+ unsigned flags;
65+ long unsigned minflt;
66+ long unsigned cminflt;
67+ long unsigned majflt;
68+ long unsigned cmajflt;
69+ long unsigned utime;
70+ long unsigned stime;
71+ long cutime;
72+ long cstime;
73+ // .... other things. We don't need them below
74+ };
5275}
5376
5477namespace lldb_private {
@@ -60,11 +83,92 @@ static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo,
6083 ::pid_t &Tgid) {
6184 Log *log = GetLog (LLDBLog::Host);
6285
63- auto BufferOrError = getProcFile (Pid, " status " );
86+ auto BufferOrError = getProcFile (Pid, " stat " );
6487 if (!BufferOrError)
6588 return false ;
6689
6790 llvm::StringRef Rest = BufferOrError.get ()->getBuffer ();
91+ if (Rest.empty ())
92+ return false ;
93+ StatFields stat_fields;
94+ if (sscanf (Rest.data (),
95+ " %d %s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu %ld %ld" ,
96+ &stat_fields.pid , stat_fields.comm , &stat_fields.state ,
97+ &stat_fields.ppid , &stat_fields.pgrp , &stat_fields.session ,
98+ &stat_fields.tty_nr , &stat_fields.tpgid , &stat_fields.flags ,
99+ &stat_fields.minflt , &stat_fields.cminflt , &stat_fields.majflt ,
100+ &stat_fields.cmajflt , &stat_fields.utime , &stat_fields.stime ,
101+ &stat_fields.cutime , &stat_fields.cstime ) < 0 ) {
102+ return false ;
103+ }
104+
105+ auto convert = [sc_clk_ticks = sysconf (_SC_CLK_TCK)](auto time_in_ticks) {
106+ ProcessInstanceInfo::timespec ts;
107+ if (sc_clk_ticks <= 0 ) {
108+ return ts;
109+ }
110+ ts.tv_sec = time_in_ticks / sc_clk_ticks;
111+ double remainder =
112+ (static_cast <double >(time_in_ticks) / sc_clk_ticks) - ts.tv_sec ;
113+ ts.tv_usec =
114+ std::chrono::microseconds{std::lround (1e+6 * remainder)}.count ();
115+ return ts;
116+ };
117+
118+ ProcessInfo.SetParentProcessID (stat_fields.ppid );
119+ ProcessInfo.SetProcessGroupID (stat_fields.pgrp );
120+ ProcessInfo.SetProcessSessionID (stat_fields.session );
121+ ProcessInfo.SetUserTime (convert (stat_fields.utime ));
122+ ProcessInfo.SetSystemTime (convert (stat_fields.stime ));
123+ ProcessInfo.SetCumulativeUserTime (convert (stat_fields.cutime ));
124+ ProcessInfo.SetCumulativeSystemTime (convert (stat_fields.cstime ));
125+ switch (stat_fields.state ) {
126+ case ' R' :
127+ State = ProcessState::Running;
128+ break ;
129+ case ' S' :
130+ State = ProcessState::Sleeping;
131+ break ;
132+ case ' D' :
133+ State = ProcessState::DiskSleep;
134+ break ;
135+ case ' Z' :
136+ State = ProcessState::Zombie;
137+ break ;
138+ case ' X' :
139+ State = ProcessState::Dead;
140+ break ;
141+ case ' P' :
142+ State = ProcessState::Parked;
143+ break ;
144+ case ' W' :
145+ State = ProcessState::Paging;
146+ break ;
147+ case ' I' :
148+ State = ProcessState::Idle;
149+ break ;
150+ case ' T' : // Stopped on a signal or (before Linux 2.6.33) trace stopped
151+ [[fallthrough]];
152+ case ' t' :
153+ State = ProcessState::TracedOrStopped;
154+ break ;
155+ default :
156+ State = ProcessState::Unknown;
157+ break ;
158+ }
159+
160+ if (State == ProcessState::Unknown) {
161+ LLDB_LOG (log, " Unknown process state {0}" , stat_fields.state );
162+ }
163+
164+ BufferOrError = getProcFile (Pid, " status" );
165+ if (!BufferOrError)
166+ return false ;
167+
168+ Rest = BufferOrError.get ()->getBuffer ();
169+ if (Rest.empty ())
170+ return false ;
171+
68172 while (!Rest.empty ()) {
69173 llvm::StringRef Line;
70174 std::tie (Line, Rest) = Rest.split (' \n ' );
@@ -89,25 +193,6 @@ static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo,
89193
90194 ProcessInfo.SetUserID (RUid);
91195 ProcessInfo.SetEffectiveUserID (EUid);
92- } else if (Line.consume_front (" PPid:" )) {
93- ::pid_t PPid;
94- Line.ltrim ().consumeInteger (10 , PPid);
95- ProcessInfo.SetParentProcessID (PPid);
96- } else if (Line.consume_front (" State:" )) {
97- State = llvm::StringSwitch<ProcessState>(Line.ltrim ().take_front (1 ))
98- .Case (" D" , ProcessState::DiskSleep)
99- .Case (" I" , ProcessState::Idle)
100- .Case (" R" , ProcessState::Running)
101- .Case (" S" , ProcessState::Sleeping)
102- .CaseLower (" T" , ProcessState::TracedOrStopped)
103- .Case (" W" , ProcessState::Paging)
104- .Case (" P" , ProcessState::Parked)
105- .Case (" X" , ProcessState::Dead)
106- .Case (" Z" , ProcessState::Zombie)
107- .Default (ProcessState::Unknown);
108- if (State == ProcessState::Unknown) {
109- LLDB_LOG (log, " Unknown process state {0}" , Line);
110- }
111196 } else if (Line.consume_front (" TracerPid:" )) {
112197 Line = Line.ltrim ();
113198 Line.consumeInteger (10 , TracerPid);
0 commit comments