• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <dirent.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <stdlib.h>
23 #include <sys/types.h>
24 #include <unistd.h>
25 
26 #include <memory>
27 #include <string>
28 #include <type_traits>
29 
30 #include <android-base/file.h>
31 #include <android-base/parseint.h>
32 #include <android-base/stringprintf.h>
33 #include <android-base/unique_fd.h>
34 
35 namespace android {
36 namespace procinfo {
37 
38 #if defined(__linux__)
39 
40 enum ProcessState {
41   kProcessStateUnknown,
42   kProcessStateRunning,
43   kProcessStateSleeping,
44   kProcessStateUninterruptibleWait,
45   kProcessStateStopped,
46   kProcessStateZombie,
47 };
48 
49 struct ProcessInfo {
50   std::string name;
51   ProcessState state;
52   pid_t tid;
53   pid_t pid;
54   pid_t ppid;
55   pid_t tracer;
56   uid_t uid;
57   uid_t gid;
58 
59   // Start time of the process since boot, measured in clock ticks.
60   uint64_t starttime;
61 };
62 
63 bool SetError(std::string* error, int errno_value, const char* fmt, ...);
64 
65 // Parse the contents of /proc/<tid>/status into |process_info|.
66 bool GetProcessInfo(pid_t tid, ProcessInfo* process_info, std::string* error = nullptr);
67 
68 // Parse the contents of <fd>/status into |process_info|.
69 // |fd| should be an fd pointing at a /proc/<pid> directory.
70 // |pid| is used for error messages.
71 bool GetProcessInfoFromProcPidFd(int fd, int pid, ProcessInfo* process_info, std::string* error = nullptr);
72 
73 // Fetch the list of threads from a given process's /proc/<pid> directory.
74 // |fd| should be an fd pointing at a /proc/<pid> directory.
75 template <typename Collection>
76 auto GetProcessTidsFromProcPidFd(int fd, Collection* out, std::string* error = nullptr) ->
77     typename std::enable_if<sizeof(typename Collection::value_type) >= sizeof(pid_t), bool>::type {
78   out->clear();
79 
80   int task_fd = openat(fd, "task", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
81   std::unique_ptr<DIR, int (*)(DIR*)> dir(fdopendir(task_fd), closedir);
82   if (!dir) {
83     return SetError(error, errno, "failed to open task directory");
84   }
85 
86   struct dirent* dent;
87   while ((dent = readdir(dir.get()))) {
88     if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0) {
89       pid_t tid;
90       if (!android::base::ParseInt(dent->d_name, &tid, 1, std::numeric_limits<pid_t>::max())) {
91         return SetError(error, 0, "failed to parse task id %s", dent->d_name);
92       }
93 
94       out->insert(out->end(), tid);
95     }
96   }
97 
98   return true;
99 }
100 
101 template <typename Collection>
102 auto GetProcessTids(pid_t pid, Collection* out, std::string* error = nullptr) ->
103     typename std::enable_if<sizeof(typename Collection::value_type) >= sizeof(pid_t), bool>::type {
104   char task_path[32];
105   snprintf(task_path, sizeof(task_path), "/proc/%d", pid);
106   android::base::unique_fd fd(open(task_path, O_DIRECTORY | O_RDONLY | O_CLOEXEC));
107   if (fd == -1) {
108     return SetError(error, errno, "failed to open %s", task_path);
109   }
110 
111   return GetProcessTidsFromProcPidFd(fd.get(), out, error);
112 }
113 
114 #endif
115 
116 } /* namespace procinfo */
117 } /* namespace android */
118