1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "lmks_utils.h"
17
18 #include <csignal>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22
23 #include "securec.h"
24 #include "hilog/log.h"
25
26 namespace OHOS {
27 namespace LMKS {
28 namespace {
29 constexpr int PROC_PATH_MAX = 256;
30 constexpr int PROC_LINE_MAX = 128;
31 } // namespace
32
33 using namespace OHOS::HiviewDFX;
34 static constexpr HiLogLabel LABEL = {LOG_CORE, 0, "LmksUtils"};
35
LmksUtils()36 LmksUtils::LmksUtils()
37 {}
38
~LmksUtils()39 LmksUtils::~LmksUtils()
40 {}
41
RemoveProcess(pid_t pid)42 int LmksUtils::RemoveProcess(pid_t pid)
43 {
44 auto procName = GetProcName(pid);
45 if (procName.empty()) {
46 HiLog::Error(LABEL, "pid %{public}d process name emptry", pid);
47 return -1;
48 }
49
50 auto procSize = GetProcSize(pid);
51 if (procSize <= 0) {
52 HiLog::Error(LABEL, "pid %{public}d process size error", pid);
53 return -1;
54 }
55
56 // kill process
57 int ret = kill(pid, SIGKILL);
58 if (ret) {
59 HiLog::Warn(LABEL, "kill pid %{public}d err %{public}s", pid, strerror(errno));
60 return (-errno);
61 } else {
62 HiLog::Info(
63 LABEL, "kill pid %{public}d success, name %{public}s size %{public}d", pid, procName.c_str(), procSize);
64 }
65
66 return 0;
67 }
68
GetProcName(pid_t pid)69 std::string LmksUtils::GetProcName(pid_t pid)
70 {
71 std::string name = "";
72
73 if (pid < 1) {
74 HiLog::Warn(LABEL, "invalid pid %{public}d.", pid);
75 return name;
76 }
77
78 char path[PROC_PATH_MAX];
79 char line[PROC_LINE_MAX];
80 int fd = -1;
81 ssize_t ret = -1;
82
83 if (memset_s(path, sizeof(path), 0x00, sizeof(path)) != 0) {
84 HiLog::Error(LABEL, "memset_s path err %{public}s", strerror(errno));
85 return name;
86 }
87
88 if (memset_s(line, sizeof(line), 0x00, sizeof(line)) != 0) {
89 HiLog::Error(LABEL, "memset_s line err %{public}s", strerror(errno));
90 return name;
91 }
92
93 if (snprintf_s(path, PROC_PATH_MAX, PROC_PATH_MAX - 1, "/proc/%d/cmdline", pid) < 0) {
94 HiLog::Error(LABEL, "snprintf_s cmdline err %{public}s", strerror(errno));
95 return name;
96 }
97
98 fd = open(path, O_RDONLY | O_CLOEXEC);
99 if (fd == -1) {
100 HiLog::Error(LABEL, "open path[%{public}s] err %{public}s", path, strerror(errno));
101 return name;
102 }
103
104 ret = ReadAll(fd, line, sizeof(line) - 1);
105 if (ret < 0) {
106 close(fd);
107 return name;
108 }
109
110 if (strlen(line) + 1 <= PROC_LINE_MAX && strlen(line) != 0) {
111 name = line;
112 } else {
113 HiLog::Error(LABEL, "cmdline no data");
114 }
115
116 close(fd);
117 return name;
118 }
119
GetProcSize(pid_t pid)120 int LmksUtils::GetProcSize(pid_t pid)
121 {
122 int rss = 0;
123
124 if (pid <= 0) {
125 HiLog::Error(LABEL, "invalid pid %{public}d.", pid);
126 return rss;
127 }
128
129 char path[PROC_PATH_MAX];
130 char line[PROC_LINE_MAX];
131 int fd = -1;
132 int total = -1;
133 ssize_t ret = -1;
134
135 if (memset_s(path, sizeof(path), 0x00, sizeof(path)) != 0) {
136 HiLog::Error(LABEL, "memset_s path err %{public}s", strerror(errno));
137 return -1;
138 }
139
140 if (memset_s(line, sizeof(line), 0x00, sizeof(line)) != 0) {
141 HiLog::Error(LABEL, "memset_s line err %{public}s", strerror(errno));
142 return -1;
143 }
144
145 if (snprintf_s(path, PROC_PATH_MAX, PROC_PATH_MAX - 1, "/proc/%d/statm", pid) < 0) {
146 HiLog::Error(LABEL, "snprintf_s statm err %{public}s", strerror(errno));
147 return rss;
148 }
149
150 fd = open(path, O_RDONLY | O_CLOEXEC);
151 if (fd == -1) {
152 HiLog::Error(LABEL, "open path[%{public}s] err %{public}s", path, strerror(errno));
153 return -1;
154 }
155
156 ret = ReadAll(fd, line, sizeof(line) - 1);
157 if (ret < 0) {
158 close(fd);
159 return -1;
160 }
161
162 if ((strlen(line) + 1 <= PROC_LINE_MAX && strlen(line) != 0) && (sscanf_s(line, "%d %d ", &total, &rss) > 0)) {
163 HiLog::Info(LABEL, "pid %{public}d total %{public}d rss %{public}d", pid, total, rss);
164 } else {
165 HiLog::Error(LABEL, "strlen or sscanf_s err %{public}s", strerror(errno));
166 rss = 0;
167 }
168
169 close(fd);
170 return rss;
171 }
172
ReadAll(int fd,char * buf,size_t maxLen)173 ssize_t LmksUtils::ReadAll(int fd, char *buf, size_t maxLen)
174 {
175 ssize_t ret = 0;
176 off_t offSet = 0;
177
178 while (maxLen > 0) {
179 ssize_t rc = TEMP_FAILURE_RETRY(pread(fd, buf, maxLen, offSet));
180 if (rc == 0) {
181 break;
182 }
183 if (rc == -1) {
184 HiLog::Error(LABEL, "pread err %{public}s", strerror(errno));
185 return -1;
186 }
187 ret += rc;
188 buf += rc;
189 offSet += rc;
190 maxLen -= rc;
191 }
192
193 return ret;
194 }
195 } // namespace LMKS
196 } // namespace OHOS
197