@@ -49,6 +49,29 @@ enum class ProcessState {
49
49
TracedOrStopped,
50
50
Zombie,
51
51
};
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
+ };
52
75
}
53
76
54
77
namespace lldb_private {
@@ -60,11 +83,92 @@ static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo,
60
83
::pid_t &Tgid) {
61
84
Log *log = GetLog (LLDBLog::Host);
62
85
63
- auto BufferOrError = getProcFile (Pid, " status " );
86
+ auto BufferOrError = getProcFile (Pid, " stat " );
64
87
if (!BufferOrError)
65
88
return false ;
66
89
67
90
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
+
68
172
while (!Rest.empty ()) {
69
173
llvm::StringRef Line;
70
174
std::tie (Line, Rest) = Rest.split (' \n ' );
@@ -89,25 +193,6 @@ static bool GetStatusInfo(::pid_t Pid, ProcessInstanceInfo &ProcessInfo,
89
193
90
194
ProcessInfo.SetUserID (RUid);
91
195
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
- }
111
196
} else if (Line.consume_front (" TracerPid:" )) {
112
197
Line = Line.ltrim ();
113
198
Line.consumeInteger (10 , TracerPid);
0 commit comments