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/logging.h> 32 #include <android-base/parseint.h> 33 #include <android-base/stringprintf.h> 34 #include <android-base/unique_fd.h> 35 36 namespace android { 37 namespace procinfo { 38 39 #if defined(__linux__) 40 41 enum ProcessState { 42 kProcessStateUnknown, 43 kProcessStateRunning, 44 kProcessStateSleeping, 45 kProcessStateUninterruptibleWait, 46 kProcessStateStopped, 47 kProcessStateZombie, 48 }; 49 50 struct ProcessInfo { 51 std::string name; 52 ProcessState state; 53 pid_t tid; 54 pid_t pid; 55 pid_t ppid; 56 pid_t tracer; 57 uid_t uid; 58 uid_t gid; 59 60 // Start time of the process since boot, measured in clock ticks. 61 uint64_t starttime; 62 }; 63 64 bool SetError(std::string* error, int errno_value, const char* fmt, ...); 65 66 // Parse the contents of /proc/<tid>/status into |process_info|. 67 bool GetProcessInfo(pid_t tid, ProcessInfo* process_info, std::string* error = nullptr); 68 69 // Parse the contents of <fd>/status into |process_info|. 70 // |fd| should be an fd pointing at a /proc/<pid> directory. 71 // |pid| is used for error messages. 72 bool GetProcessInfoFromProcPidFd(int fd, int pid, ProcessInfo* process_info, std::string* error = nullptr); 73 74 // Fetch the list of threads from a given process's /proc/<pid> directory. 75 // |fd| should be an fd pointing at a /proc/<pid> directory. 76 template <typename Collection> 77 auto GetProcessTidsFromProcPidFd(int fd, Collection* out, std::string* error = nullptr) -> 78 typename std::enable_if<sizeof(typename Collection::value_type) >= sizeof(pid_t), bool>::type { 79 out->clear(); 80 81 int task_fd = openat(fd, "task", O_DIRECTORY | O_RDONLY | O_CLOEXEC); 82 std::unique_ptr<DIR, int (*)(DIR*)> dir(fdopendir(task_fd), closedir); 83 if (!dir) { 84 return SetError(error, errno, "failed to open task directory"); 85 } 86 87 struct dirent* dent; 88 while ((dent = readdir(dir.get()))) { 89 if (strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0) { 90 pid_t tid; 91 if (!android::base::ParseInt(dent->d_name, &tid, 1, std::numeric_limits<pid_t>::max())) { 92 return SetError(error, 0, "failed to parse task id %s", dent->d_name); 93 } 94 95 out->insert(out->end(), tid); 96 } 97 } 98 99 return true; 100 } 101 102 template <typename Collection> 103 auto GetProcessTids(pid_t pid, Collection* out, std::string* error = nullptr) -> 104 typename std::enable_if<sizeof(typename Collection::value_type) >= sizeof(pid_t), bool>::type { 105 char task_path[32]; 106 snprintf(task_path, sizeof(task_path), "/proc/%d", pid); 107 android::base::unique_fd fd(open(task_path, O_DIRECTORY | O_RDONLY | O_CLOEXEC)); 108 if (fd == -1) { 109 return SetError(error, errno, "failed to open %s", task_path); 110 } 111 112 return GetProcessTidsFromProcPidFd(fd.get(), out, error); 113 } 114 115 #endif 116 117 } /* namespace procinfo */ 118 } /* namespace android */ 119