xref: /aosp_15_r20/system/extras/memtrack/memtrack.cpp (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker  * Copyright 2013 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker  *
4*288bf522SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker  *
8*288bf522SAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker  *
10*288bf522SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker  * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker  */
16*288bf522SAndroid Build Coastguard Worker #define LOG_TAG "MemTracker"
17*288bf522SAndroid Build Coastguard Worker 
18*288bf522SAndroid Build Coastguard Worker #include "memtrack.h"
19*288bf522SAndroid Build Coastguard Worker 
20*288bf522SAndroid Build Coastguard Worker #include <ctype.h>
21*288bf522SAndroid Build Coastguard Worker #include <dirent.h>
22*288bf522SAndroid Build Coastguard Worker #include <fcntl.h>
23*288bf522SAndroid Build Coastguard Worker #include <limits.h>
24*288bf522SAndroid Build Coastguard Worker #include <signal.h>
25*288bf522SAndroid Build Coastguard Worker #include <stdio.h>
26*288bf522SAndroid Build Coastguard Worker #include <stdlib.h>
27*288bf522SAndroid Build Coastguard Worker #include <sys/stat.h>
28*288bf522SAndroid Build Coastguard Worker #include <sys/types.h>
29*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
30*288bf522SAndroid Build Coastguard Worker 
31*288bf522SAndroid Build Coastguard Worker #include <algorithm>
32*288bf522SAndroid Build Coastguard Worker #include <vector>
33*288bf522SAndroid Build Coastguard Worker 
34*288bf522SAndroid Build Coastguard Worker #include <log/log.h>
35*288bf522SAndroid Build Coastguard Worker 
FileData(char * filename,char * buffer,size_t buffer_len)36*288bf522SAndroid Build Coastguard Worker FileData::FileData(char *filename, char *buffer, size_t buffer_len)
37*288bf522SAndroid Build Coastguard Worker     : data_(buffer), max_(buffer_len), cur_idx_(0), len_(0),
38*288bf522SAndroid Build Coastguard Worker       read_complete_(false) {
39*288bf522SAndroid Build Coastguard Worker   fd_ = open(filename, O_RDONLY);
40*288bf522SAndroid Build Coastguard Worker   if (fd_ < 0) {
41*288bf522SAndroid Build Coastguard Worker     read_complete_ = true;
42*288bf522SAndroid Build Coastguard Worker   }
43*288bf522SAndroid Build Coastguard Worker }
44*288bf522SAndroid Build Coastguard Worker 
~FileData()45*288bf522SAndroid Build Coastguard Worker FileData::~FileData() {
46*288bf522SAndroid Build Coastguard Worker   if (fd_ >= 0) {
47*288bf522SAndroid Build Coastguard Worker     close(fd_);
48*288bf522SAndroid Build Coastguard Worker   }
49*288bf522SAndroid Build Coastguard Worker }
50*288bf522SAndroid Build Coastguard Worker 
isAvail(size_t bytes_needed)51*288bf522SAndroid Build Coastguard Worker bool FileData::isAvail(size_t bytes_needed) {
52*288bf522SAndroid Build Coastguard Worker   if (cur_idx_ + bytes_needed < len_) {
53*288bf522SAndroid Build Coastguard Worker     return true;
54*288bf522SAndroid Build Coastguard Worker   }
55*288bf522SAndroid Build Coastguard Worker 
56*288bf522SAndroid Build Coastguard Worker   if (read_complete_) {
57*288bf522SAndroid Build Coastguard Worker     return false;
58*288bf522SAndroid Build Coastguard Worker   }
59*288bf522SAndroid Build Coastguard Worker 
60*288bf522SAndroid Build Coastguard Worker   if (cur_idx_ != len_) {
61*288bf522SAndroid Build Coastguard Worker     // Copy the leftover to the front of the buffer.
62*288bf522SAndroid Build Coastguard Worker     len_ = len_ - cur_idx_;
63*288bf522SAndroid Build Coastguard Worker     memcpy(data_, data_ + cur_idx_, len_);
64*288bf522SAndroid Build Coastguard Worker   }
65*288bf522SAndroid Build Coastguard Worker 
66*288bf522SAndroid Build Coastguard Worker   ssize_t bytes;
67*288bf522SAndroid Build Coastguard Worker   cur_idx_ = 0;
68*288bf522SAndroid Build Coastguard Worker   while (cur_idx_ + bytes_needed >= len_) {
69*288bf522SAndroid Build Coastguard Worker     bytes = read(fd_, data_ + len_, max_ - len_);
70*288bf522SAndroid Build Coastguard Worker     if (bytes == 0 || bytes == -1) {
71*288bf522SAndroid Build Coastguard Worker       read_complete_ = true;
72*288bf522SAndroid Build Coastguard Worker       break;
73*288bf522SAndroid Build Coastguard Worker     }
74*288bf522SAndroid Build Coastguard Worker     len_ += bytes;
75*288bf522SAndroid Build Coastguard Worker   }
76*288bf522SAndroid Build Coastguard Worker 
77*288bf522SAndroid Build Coastguard Worker   return cur_idx_ + bytes_needed < len_;
78*288bf522SAndroid Build Coastguard Worker }
79*288bf522SAndroid Build Coastguard Worker 
getPss(size_t * pss)80*288bf522SAndroid Build Coastguard Worker bool FileData::getPss(size_t *pss) {
81*288bf522SAndroid Build Coastguard Worker   size_t value;
82*288bf522SAndroid Build Coastguard Worker   while (true) {
83*288bf522SAndroid Build Coastguard Worker     if (!isAvail(4)) {
84*288bf522SAndroid Build Coastguard Worker       return false;
85*288bf522SAndroid Build Coastguard Worker     }
86*288bf522SAndroid Build Coastguard Worker 
87*288bf522SAndroid Build Coastguard Worker     if (data_[cur_idx_] != 'P' || data_[cur_idx_+1] != 's' ||
88*288bf522SAndroid Build Coastguard Worker         data_[cur_idx_+2] != 's' || data_[cur_idx_+3] != ':') {
89*288bf522SAndroid Build Coastguard Worker       // Consume the rest of the line.
90*288bf522SAndroid Build Coastguard Worker       while (isAvail(1) && data_[cur_idx_++] != '\n');
91*288bf522SAndroid Build Coastguard Worker     } else {
92*288bf522SAndroid Build Coastguard Worker       cur_idx_ += 4;
93*288bf522SAndroid Build Coastguard Worker       while (isAvail(1) && isspace(data_[cur_idx_])) {
94*288bf522SAndroid Build Coastguard Worker         cur_idx_++;
95*288bf522SAndroid Build Coastguard Worker       }
96*288bf522SAndroid Build Coastguard Worker 
97*288bf522SAndroid Build Coastguard Worker       value = 0;
98*288bf522SAndroid Build Coastguard Worker       while (isAvail(1) && isdigit(data_[cur_idx_])) {
99*288bf522SAndroid Build Coastguard Worker         value = value * 10 + data_[cur_idx_] - '0';
100*288bf522SAndroid Build Coastguard Worker         cur_idx_++;
101*288bf522SAndroid Build Coastguard Worker       }
102*288bf522SAndroid Build Coastguard Worker       *pss = value;
103*288bf522SAndroid Build Coastguard Worker 
104*288bf522SAndroid Build Coastguard Worker       // Consume the rest of the line.
105*288bf522SAndroid Build Coastguard Worker       while (isAvail(1) && data_[cur_idx_++] != '\n');
106*288bf522SAndroid Build Coastguard Worker 
107*288bf522SAndroid Build Coastguard Worker       return true;
108*288bf522SAndroid Build Coastguard Worker     }
109*288bf522SAndroid Build Coastguard Worker   }
110*288bf522SAndroid Build Coastguard Worker }
111*288bf522SAndroid Build Coastguard Worker 
112*288bf522SAndroid Build Coastguard Worker const char *ProcessInfo::kProc = "/proc/";
113*288bf522SAndroid Build Coastguard Worker const char *ProcessInfo::kCmdline = "/cmdline";
114*288bf522SAndroid Build Coastguard Worker const char *ProcessInfo::kSmaps = "/smaps";
115*288bf522SAndroid Build Coastguard Worker 
ProcessInfo()116*288bf522SAndroid Build Coastguard Worker ProcessInfo::ProcessInfo() {
117*288bf522SAndroid Build Coastguard Worker   memcpy(proc_file_, kProc, kProcLen);
118*288bf522SAndroid Build Coastguard Worker }
119*288bf522SAndroid Build Coastguard Worker 
~ProcessInfo()120*288bf522SAndroid Build Coastguard Worker ProcessInfo::~ProcessInfo() {
121*288bf522SAndroid Build Coastguard Worker }
122*288bf522SAndroid Build Coastguard Worker 
getInformation(int pid,char * pid_str,size_t pid_str_len)123*288bf522SAndroid Build Coastguard Worker bool ProcessInfo::getInformation(int pid, char *pid_str, size_t pid_str_len) {
124*288bf522SAndroid Build Coastguard Worker   memcpy(proc_file_ + kProcLen, pid_str, pid_str_len);
125*288bf522SAndroid Build Coastguard Worker   memcpy(proc_file_ + kProcLen + pid_str_len, kCmdline, kCmdlineLen);
126*288bf522SAndroid Build Coastguard Worker 
127*288bf522SAndroid Build Coastguard Worker   // Read the cmdline for the process.
128*288bf522SAndroid Build Coastguard Worker   int fd = open(proc_file_, O_RDONLY);
129*288bf522SAndroid Build Coastguard Worker   if (fd < 0) {
130*288bf522SAndroid Build Coastguard Worker     return false;
131*288bf522SAndroid Build Coastguard Worker   }
132*288bf522SAndroid Build Coastguard Worker 
133*288bf522SAndroid Build Coastguard Worker   ssize_t bytes = read(fd, cmd_name_, sizeof(cmd_name_));
134*288bf522SAndroid Build Coastguard Worker   close(fd);
135*288bf522SAndroid Build Coastguard Worker   if (bytes == -1 || bytes == 0) {
136*288bf522SAndroid Build Coastguard Worker     return false;
137*288bf522SAndroid Build Coastguard Worker   }
138*288bf522SAndroid Build Coastguard Worker 
139*288bf522SAndroid Build Coastguard Worker   memcpy(proc_file_ + kProcLen + pid_str_len, kSmaps, kSmapsLen);
140*288bf522SAndroid Build Coastguard Worker   FileData smaps(proc_file_, buffer_, sizeof(buffer_));
141*288bf522SAndroid Build Coastguard Worker 
142*288bf522SAndroid Build Coastguard Worker   cur_process_info_t process_info;
143*288bf522SAndroid Build Coastguard Worker   size_t pss_kb;
144*288bf522SAndroid Build Coastguard Worker   process_info.pss_kb = 0;
145*288bf522SAndroid Build Coastguard Worker   while (smaps.getPss(&pss_kb)) {
146*288bf522SAndroid Build Coastguard Worker     process_info.pss_kb += pss_kb;
147*288bf522SAndroid Build Coastguard Worker   }
148*288bf522SAndroid Build Coastguard Worker 
149*288bf522SAndroid Build Coastguard Worker   if (cur_.count(cmd_name_) == 0) {
150*288bf522SAndroid Build Coastguard Worker     cur_[cmd_name_] = process_info;
151*288bf522SAndroid Build Coastguard Worker   } else {
152*288bf522SAndroid Build Coastguard Worker     cur_[cmd_name_].pss_kb += process_info.pss_kb;
153*288bf522SAndroid Build Coastguard Worker   }
154*288bf522SAndroid Build Coastguard Worker   cur_[cmd_name_].pids.push_back(pid);
155*288bf522SAndroid Build Coastguard Worker 
156*288bf522SAndroid Build Coastguard Worker   return true;
157*288bf522SAndroid Build Coastguard Worker }
158*288bf522SAndroid Build Coastguard Worker 
scan()159*288bf522SAndroid Build Coastguard Worker void ProcessInfo::scan() {
160*288bf522SAndroid Build Coastguard Worker   DIR *proc_dir = opendir(kProc);
161*288bf522SAndroid Build Coastguard Worker   if (proc_dir == NULL) {
162*288bf522SAndroid Build Coastguard Worker     perror("Cannot open directory.\n");
163*288bf522SAndroid Build Coastguard Worker     exit(1);
164*288bf522SAndroid Build Coastguard Worker   }
165*288bf522SAndroid Build Coastguard Worker 
166*288bf522SAndroid Build Coastguard Worker   // Clear any current pids.
167*288bf522SAndroid Build Coastguard Worker   for (processes_t::iterator it = all_.begin(); it != all_.end(); ++it) {
168*288bf522SAndroid Build Coastguard Worker     it->second.pids.clear();
169*288bf522SAndroid Build Coastguard Worker   }
170*288bf522SAndroid Build Coastguard Worker 
171*288bf522SAndroid Build Coastguard Worker   struct dirent *dir_data;
172*288bf522SAndroid Build Coastguard Worker   int len;
173*288bf522SAndroid Build Coastguard Worker   bool is_pid;
174*288bf522SAndroid Build Coastguard Worker   size_t pid;
175*288bf522SAndroid Build Coastguard Worker   cur_.clear();
176*288bf522SAndroid Build Coastguard Worker   while ((dir_data = readdir(proc_dir))) {
177*288bf522SAndroid Build Coastguard Worker     // Check if the directory entry represents a pid.
178*288bf522SAndroid Build Coastguard Worker     len = strlen(dir_data->d_name);
179*288bf522SAndroid Build Coastguard Worker     is_pid = true;
180*288bf522SAndroid Build Coastguard Worker     pid = 0;
181*288bf522SAndroid Build Coastguard Worker     for (int i = 0; i < len; i++) {
182*288bf522SAndroid Build Coastguard Worker       if (!isdigit(dir_data->d_name[i])) {
183*288bf522SAndroid Build Coastguard Worker         is_pid = false;
184*288bf522SAndroid Build Coastguard Worker         break;
185*288bf522SAndroid Build Coastguard Worker       }
186*288bf522SAndroid Build Coastguard Worker       pid = pid * 10 + dir_data->d_name[i] - '0';
187*288bf522SAndroid Build Coastguard Worker     }
188*288bf522SAndroid Build Coastguard Worker     if (is_pid) {
189*288bf522SAndroid Build Coastguard Worker       getInformation(pid, dir_data->d_name, len);
190*288bf522SAndroid Build Coastguard Worker     }
191*288bf522SAndroid Build Coastguard Worker   }
192*288bf522SAndroid Build Coastguard Worker   closedir(proc_dir);
193*288bf522SAndroid Build Coastguard Worker 
194*288bf522SAndroid Build Coastguard Worker   // Loop through the current processes and add them into our real list.
195*288bf522SAndroid Build Coastguard Worker   for (cur_processes_t::const_iterator it = cur_.begin();
196*288bf522SAndroid Build Coastguard Worker        it != cur_.end(); ++it) {
197*288bf522SAndroid Build Coastguard Worker 
198*288bf522SAndroid Build Coastguard Worker     if (all_.count(it->first) == 0) {
199*288bf522SAndroid Build Coastguard Worker       // Initialize all of the variables.
200*288bf522SAndroid Build Coastguard Worker       all_[it->first].num_samples = 0;
201*288bf522SAndroid Build Coastguard Worker       all_[it->first].name = it->first;
202*288bf522SAndroid Build Coastguard Worker       all_[it->first].avg_pss_kb = 0;
203*288bf522SAndroid Build Coastguard Worker       all_[it->first].min_pss_kb = 0;
204*288bf522SAndroid Build Coastguard Worker       all_[it->first].max_pss_kb = 0;
205*288bf522SAndroid Build Coastguard Worker     }
206*288bf522SAndroid Build Coastguard Worker 
207*288bf522SAndroid Build Coastguard Worker     if (it->second.pids.size() > all_[it->first].max_num_pids) {
208*288bf522SAndroid Build Coastguard Worker       all_[it->first].max_num_pids = it->second.pids.size();
209*288bf522SAndroid Build Coastguard Worker     }
210*288bf522SAndroid Build Coastguard Worker 
211*288bf522SAndroid Build Coastguard Worker     all_[it->first].pids = it->second.pids;
212*288bf522SAndroid Build Coastguard Worker 
213*288bf522SAndroid Build Coastguard Worker     if (it->second.pss_kb > all_[it->first].max_pss_kb) {
214*288bf522SAndroid Build Coastguard Worker       all_[it->first].max_pss_kb = it->second.pss_kb;
215*288bf522SAndroid Build Coastguard Worker     }
216*288bf522SAndroid Build Coastguard Worker 
217*288bf522SAndroid Build Coastguard Worker     if (all_[it->first].min_pss_kb == 0 ||
218*288bf522SAndroid Build Coastguard Worker         it->second.pss_kb < all_[it->first].min_pss_kb) {
219*288bf522SAndroid Build Coastguard Worker       all_[it->first].min_pss_kb = it->second.pss_kb;
220*288bf522SAndroid Build Coastguard Worker     }
221*288bf522SAndroid Build Coastguard Worker 
222*288bf522SAndroid Build Coastguard Worker     all_[it->first].last_pss_kb = it->second.pss_kb;
223*288bf522SAndroid Build Coastguard Worker 
224*288bf522SAndroid Build Coastguard Worker     computeAvg(&all_[it->first].avg_pss_kb, it->second.pss_kb,
225*288bf522SAndroid Build Coastguard Worker                all_[it->first].num_samples);
226*288bf522SAndroid Build Coastguard Worker     all_[it->first].num_samples++;
227*288bf522SAndroid Build Coastguard Worker   }
228*288bf522SAndroid Build Coastguard Worker }
229*288bf522SAndroid Build Coastguard Worker 
comparePss(const process_info_t * first,const process_info_t * second)230*288bf522SAndroid Build Coastguard Worker bool comparePss(const process_info_t *first, const process_info_t *second) {
231*288bf522SAndroid Build Coastguard Worker   return first->max_pss_kb > second->max_pss_kb;
232*288bf522SAndroid Build Coastguard Worker }
233*288bf522SAndroid Build Coastguard Worker 
dumpToLog()234*288bf522SAndroid Build Coastguard Worker void ProcessInfo::dumpToLog() {
235*288bf522SAndroid Build Coastguard Worker   list_.clear();
236*288bf522SAndroid Build Coastguard Worker   for (processes_t::const_iterator it = all_.begin(); it != all_.end(); ++it) {
237*288bf522SAndroid Build Coastguard Worker     list_.push_back(&it->second);
238*288bf522SAndroid Build Coastguard Worker   }
239*288bf522SAndroid Build Coastguard Worker 
240*288bf522SAndroid Build Coastguard Worker   // Now sort the list.
241*288bf522SAndroid Build Coastguard Worker   std::sort(list_.begin(), list_.end(), comparePss);
242*288bf522SAndroid Build Coastguard Worker 
243*288bf522SAndroid Build Coastguard Worker   ALOGI("Dumping process list");
244*288bf522SAndroid Build Coastguard Worker   for (std::vector<const process_info_t *>::const_iterator it = list_.begin();
245*288bf522SAndroid Build Coastguard Worker        it != list_.end(); ++it) {
246*288bf522SAndroid Build Coastguard Worker     ALOGI("  Name: %s", (*it)->name.c_str());
247*288bf522SAndroid Build Coastguard Worker     ALOGI("    Max running processes: %zu", (*it)->max_num_pids);
248*288bf522SAndroid Build Coastguard Worker     if ((*it)->pids.size() > 0) {
249*288bf522SAndroid Build Coastguard Worker       ALOGI("    Currently running pids:");
250*288bf522SAndroid Build Coastguard Worker       for (std::vector<int>::const_iterator pid_it = (*it)->pids.begin();
251*288bf522SAndroid Build Coastguard Worker            pid_it != (*it)->pids.end(); ++pid_it) {
252*288bf522SAndroid Build Coastguard Worker         ALOGI("      %d", *pid_it);
253*288bf522SAndroid Build Coastguard Worker       }
254*288bf522SAndroid Build Coastguard Worker     }
255*288bf522SAndroid Build Coastguard Worker 
256*288bf522SAndroid Build Coastguard Worker     ALOGI("    Min  PSS %0.4fM", (*it)->min_pss_kb/1024.0);
257*288bf522SAndroid Build Coastguard Worker     ALOGI("    Avg  PSS %0.4fM", (*it)->avg_pss_kb/1024.0);
258*288bf522SAndroid Build Coastguard Worker     ALOGI("    Max  PSS %0.4fM", (*it)->max_pss_kb/1024.0);
259*288bf522SAndroid Build Coastguard Worker     ALOGI("    Last PSS %0.4fM", (*it)->last_pss_kb/1024.0);
260*288bf522SAndroid Build Coastguard Worker   }
261*288bf522SAndroid Build Coastguard Worker }
262*288bf522SAndroid Build Coastguard Worker 
usage()263*288bf522SAndroid Build Coastguard Worker void usage() {
264*288bf522SAndroid Build Coastguard Worker   printf("Usage: memtrack [--verbose | --quiet] [--scan_delay TIME_SECS]\n");
265*288bf522SAndroid Build Coastguard Worker   printf("  --scan_delay TIME_SECS\n");
266*288bf522SAndroid Build Coastguard Worker   printf("    The amount of delay in seconds between scans.\n");
267*288bf522SAndroid Build Coastguard Worker   printf("  --verbose\n");
268*288bf522SAndroid Build Coastguard Worker   printf("    Print information about the scans to stdout only.\n");
269*288bf522SAndroid Build Coastguard Worker   printf("  --quiet\n");
270*288bf522SAndroid Build Coastguard Worker   printf("    Nothing will be printed to stdout.\n");
271*288bf522SAndroid Build Coastguard Worker   printf("  All scan data is dumped to the android log using the tag %s\n",
272*288bf522SAndroid Build Coastguard Worker          LOG_TAG);
273*288bf522SAndroid Build Coastguard Worker }
274*288bf522SAndroid Build Coastguard Worker 
275*288bf522SAndroid Build Coastguard Worker int SignalReceived = 0;
276*288bf522SAndroid Build Coastguard Worker 
277*288bf522SAndroid Build Coastguard Worker int SignalsToHandle[] = {
278*288bf522SAndroid Build Coastguard Worker   SIGTSTP,
279*288bf522SAndroid Build Coastguard Worker   SIGINT,
280*288bf522SAndroid Build Coastguard Worker   SIGHUP,
281*288bf522SAndroid Build Coastguard Worker   SIGPIPE,
282*288bf522SAndroid Build Coastguard Worker   SIGUSR1,
283*288bf522SAndroid Build Coastguard Worker };
284*288bf522SAndroid Build Coastguard Worker 
handleSignal(int signo)285*288bf522SAndroid Build Coastguard Worker void handleSignal(int signo) {
286*288bf522SAndroid Build Coastguard Worker   if (SignalReceived == 0) {
287*288bf522SAndroid Build Coastguard Worker     SignalReceived = signo;
288*288bf522SAndroid Build Coastguard Worker   }
289*288bf522SAndroid Build Coastguard Worker }
290*288bf522SAndroid Build Coastguard Worker 
main(int argc,char ** argv)291*288bf522SAndroid Build Coastguard Worker int main(int argc, char **argv) {
292*288bf522SAndroid Build Coastguard Worker   if (geteuid() != 0) {
293*288bf522SAndroid Build Coastguard Worker     printf("Must be run as root.\n");
294*288bf522SAndroid Build Coastguard Worker     exit(1);
295*288bf522SAndroid Build Coastguard Worker   }
296*288bf522SAndroid Build Coastguard Worker 
297*288bf522SAndroid Build Coastguard Worker   bool verbose = false;
298*288bf522SAndroid Build Coastguard Worker   bool quiet = false;
299*288bf522SAndroid Build Coastguard Worker   unsigned int scan_delay_sec = DEFAULT_SLEEP_DELAY_SECONDS;
300*288bf522SAndroid Build Coastguard Worker   for (int i = 1; i < argc; i++) {
301*288bf522SAndroid Build Coastguard Worker     if (strcmp(argv[i], "--verbose") == 0) {
302*288bf522SAndroid Build Coastguard Worker       verbose = true;
303*288bf522SAndroid Build Coastguard Worker     } else if (strcmp(argv[i], "--quiet") == 0) {
304*288bf522SAndroid Build Coastguard Worker       quiet = true;
305*288bf522SAndroid Build Coastguard Worker     } else if (strcmp(argv[i], "--scan_delay") == 0) {
306*288bf522SAndroid Build Coastguard Worker       if (i+1 == argc) {
307*288bf522SAndroid Build Coastguard Worker         printf("The %s options requires a single argument.\n", argv[i]);
308*288bf522SAndroid Build Coastguard Worker         usage();
309*288bf522SAndroid Build Coastguard Worker         exit(1);
310*288bf522SAndroid Build Coastguard Worker       }
311*288bf522SAndroid Build Coastguard Worker       scan_delay_sec = atoi(argv[++i]);
312*288bf522SAndroid Build Coastguard Worker     } else {
313*288bf522SAndroid Build Coastguard Worker       printf("Unknown option %s\n", argv[i]);
314*288bf522SAndroid Build Coastguard Worker       usage();
315*288bf522SAndroid Build Coastguard Worker       exit(1);
316*288bf522SAndroid Build Coastguard Worker     }
317*288bf522SAndroid Build Coastguard Worker   }
318*288bf522SAndroid Build Coastguard Worker   if (quiet && verbose) {
319*288bf522SAndroid Build Coastguard Worker     printf("Both --quiet and --verbose cannot be specified.\n");
320*288bf522SAndroid Build Coastguard Worker     usage();
321*288bf522SAndroid Build Coastguard Worker     exit(1);
322*288bf522SAndroid Build Coastguard Worker   }
323*288bf522SAndroid Build Coastguard Worker 
324*288bf522SAndroid Build Coastguard Worker   // Set up the signal handlers.
325*288bf522SAndroid Build Coastguard Worker   for (size_t i = 0; i < sizeof(SignalsToHandle)/sizeof(int); i++) {
326*288bf522SAndroid Build Coastguard Worker     if (signal(SignalsToHandle[i], handleSignal) == SIG_ERR) {
327*288bf522SAndroid Build Coastguard Worker       printf("Unable to handle signal %d\n", SignalsToHandle[i]);
328*288bf522SAndroid Build Coastguard Worker       exit(1);
329*288bf522SAndroid Build Coastguard Worker     }
330*288bf522SAndroid Build Coastguard Worker   }
331*288bf522SAndroid Build Coastguard Worker 
332*288bf522SAndroid Build Coastguard Worker   ProcessInfo proc_info;
333*288bf522SAndroid Build Coastguard Worker 
334*288bf522SAndroid Build Coastguard Worker   if (!quiet) {
335*288bf522SAndroid Build Coastguard Worker     printf("Hit Ctrl-Z or send SIGUSR1 to pid %d to print the current list of\n",
336*288bf522SAndroid Build Coastguard Worker            getpid());
337*288bf522SAndroid Build Coastguard Worker     printf("processes.\n");
338*288bf522SAndroid Build Coastguard Worker     printf("Hit Ctrl-C to print the list of processes and terminate.\n");
339*288bf522SAndroid Build Coastguard Worker   }
340*288bf522SAndroid Build Coastguard Worker 
341*288bf522SAndroid Build Coastguard Worker   struct timespec t;
342*288bf522SAndroid Build Coastguard Worker   unsigned long long nsecs;
343*288bf522SAndroid Build Coastguard Worker   while (true) {
344*288bf522SAndroid Build Coastguard Worker     if (verbose) {
345*288bf522SAndroid Build Coastguard Worker       memset(&t, 0, sizeof(t));
346*288bf522SAndroid Build Coastguard Worker       clock_gettime(CLOCK_MONOTONIC, &t);
347*288bf522SAndroid Build Coastguard Worker       nsecs = (unsigned long long)t.tv_sec*NS_PER_SEC + t.tv_nsec;
348*288bf522SAndroid Build Coastguard Worker     }
349*288bf522SAndroid Build Coastguard Worker     proc_info.scan();
350*288bf522SAndroid Build Coastguard Worker     if (verbose) {
351*288bf522SAndroid Build Coastguard Worker       memset(&t, 0, sizeof(t));
352*288bf522SAndroid Build Coastguard Worker       clock_gettime(CLOCK_MONOTONIC, &t);
353*288bf522SAndroid Build Coastguard Worker       nsecs = ((unsigned long long)t.tv_sec*NS_PER_SEC + t.tv_nsec) - nsecs;
354*288bf522SAndroid Build Coastguard Worker       printf("Scan Time %0.4f\n", ((double)nsecs)/NS_PER_SEC);
355*288bf522SAndroid Build Coastguard Worker     }
356*288bf522SAndroid Build Coastguard Worker 
357*288bf522SAndroid Build Coastguard Worker     if (SignalReceived != 0) {
358*288bf522SAndroid Build Coastguard Worker       proc_info.dumpToLog();
359*288bf522SAndroid Build Coastguard Worker       if (SignalReceived != SIGUSR1 && SignalReceived != SIGTSTP) {
360*288bf522SAndroid Build Coastguard Worker         if (!quiet) {
361*288bf522SAndroid Build Coastguard Worker           printf("Terminating...\n");
362*288bf522SAndroid Build Coastguard Worker         }
363*288bf522SAndroid Build Coastguard Worker         exit(1);
364*288bf522SAndroid Build Coastguard Worker       }
365*288bf522SAndroid Build Coastguard Worker       SignalReceived = 0;
366*288bf522SAndroid Build Coastguard Worker     }
367*288bf522SAndroid Build Coastguard Worker     sleep(scan_delay_sec);
368*288bf522SAndroid Build Coastguard Worker   }
369*288bf522SAndroid Build Coastguard Worker }
370