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 #include "event_log_task.h"
16
17 #include <unistd.h>
18
19 #include "securec.h"
20
21 #include "common_utils.h"
22 #include "logger.h"
23 #include "string_util.h"
24 #include "parameter_ex.h"
25
26 #include "binder_catcher.h"
27 #include "open_stacktrace_catcher.h"
28 #include "peer_binder_catcher.h"
29 #include "dmesg_catcher.h"
30 #include "shell_catcher.h"
31 namespace OHOS {
32 namespace HiviewDFX {
33 namespace {
34 const std::string SYSTEM_STACK[] = {
35 "foundation",
36 };
37 }
38 DEFINE_LOG_LABEL(0xD002D01, "EventLogger-EventLogTask");
EventLogTask(int fd,std::shared_ptr<SysEvent> event)39 EventLogTask::EventLogTask(int fd, std::shared_ptr<SysEvent> event)
40 : targetFd_(fd),
41 event_(event),
42 maxLogSize_(DEFAULT_LOG_SIZE),
43 taskLogSize_(0),
44 status_(Status::TASK_RUNNABLE)
45 {
46 int pid = event_->GetEventIntValue("PID");
47 pid_ = pid ? pid : event_->GetPid();
48 captureList_.insert(std::pair<std::string, capture>("s", std::bind(&EventLogTask::AppStackCapture, this)));
49 captureList_.insert(std::pair<std::string, capture>("S", std::bind(&EventLogTask::SystemStackCapture, this)));
50 captureList_.insert(std::pair<std::string, capture>("b", std::bind(&EventLogTask::BinderLogCapture, this)));
51 captureList_.insert(std::pair<std::string, capture>("cmd:c", std::bind(&EventLogTask::CpuUsageCapture, this)));
52 captureList_.insert(std::pair<std::string, capture>("cmd:m", std::bind(&EventLogTask::MemoryUsageCapture, this)));
53 captureList_.insert(std::pair<std::string, capture>("cmd:w", std::bind(&EventLogTask::WMSUsageCapture, this)));
54 captureList_.insert(std::pair<std::string, capture>("cmd:a", std::bind(&EventLogTask::AMSUsageCapture, this)));
55 captureList_.insert(std::pair<std::string, capture>("cmd:p", std::bind(&EventLogTask::PMSUsageCapture, this)));
56 captureList_.insert(std::pair<std::string, capture>("cmd:d", std::bind(&EventLogTask::DPMSUsageCapture, this)));
57 captureList_.insert(std::pair<std::string, capture>("T", std::bind(&EventLogTask::HilogCapture, this)));
58 captureList_.insert(std::pair<std::string, capture>("e", std::bind(&EventLogTask::DmesgCapture, this)));
59 captureList_.insert(std::pair<std::string, capture>("k:SysRq",
60 std::bind(&EventLogTask::SysrqCapture, this, false)));
61 captureList_.insert(std::pair<std::string, capture>("k:SysRqFile",
62 std::bind(&EventLogTask::SysrqCapture, this, true)));
63 }
64
AddLog(const std::string & cmd)65 void EventLogTask::AddLog(const std::string &cmd)
66 {
67 if (tasks_.size() == 0) {
68 status_ = Status::TASK_RUNNABLE;
69 }
70
71 if (captureList_.find(cmd) != captureList_.end()) {
72 captureList_[cmd]();
73 return;
74 }
75 PeerBinderCapture(cmd);
76 }
77
StartCompose()78 EventLogTask::Status EventLogTask::StartCompose()
79 {
80 // nothing to do, return success
81 if (status_ != Status::TASK_RUNNABLE) {
82 return status_;
83 }
84 status_ = Status::TASK_RUNNING;
85 // nothing to do, return success
86 if (tasks_.size() == 0) {
87 return Status::TASK_SUCCESS;
88 }
89
90 auto dupedFd = dup(targetFd_);
91 uint32_t catcherIndex = 0;
92 for (auto& catcher : tasks_) {
93 catcherIndex++;
94 if (dupedFd < 0) {
95 status_ = Status::TASK_FAIL;
96 AddStopReason(targetFd_, catcher, "Fail to dup file descriptor, exit!");
97 return TASK_FAIL;
98 }
99
100 AddSeparator(dupedFd, catcher);
101 int curLogSize = catcher->Catch(dupedFd);
102 if (ShouldStopLogTask(dupedFd, catcherIndex, curLogSize, catcher)) {
103 break;
104 }
105 }
106 close(dupedFd);
107
108 if (status_ == Status::TASK_RUNNING) {
109 status_ = Status::TASK_SUCCESS;
110 }
111 return status_;
112 }
113
ShouldStopLogTask(int fd,uint32_t curTaskIndex,int curLogSize,std::shared_ptr<EventLogCatcher> catcher)114 bool EventLogTask::ShouldStopLogTask(int fd, uint32_t curTaskIndex, int curLogSize,
115 std::shared_ptr<EventLogCatcher> catcher)
116 {
117 if (status_ == Status::TASK_TIMEOUT) {
118 HIVIEW_LOGE("Break Log task, parent has timeout.");
119 return true;
120 }
121
122 bool encounterErr = (curLogSize < 0);
123 bool hasFinished = (curTaskIndex == tasks_.size());
124 if (!encounterErr) {
125 taskLogSize_ += curLogSize;
126 }
127
128 if (taskLogSize_ > maxLogSize_ && !hasFinished) {
129 AddStopReason(fd, catcher, "Exceed max log size");
130 status_ = Status::TASK_EXCEED_SIZE;
131 return true;
132 }
133
134 if (encounterErr) {
135 AddStopReason(fd, catcher, "Log catcher not successful");
136 HIVIEW_LOGE("catcher %{public}s, Log catcher not successful", catcher->GetDescription().c_str());
137 }
138 return false;
139 }
140
AddStopReason(int fd,std::shared_ptr<EventLogCatcher> catcher,const std::string & reason)141 void EventLogTask::AddStopReason(int fd, std::shared_ptr<EventLogCatcher> catcher, const std::string& reason)
142 {
143 char buf[BUF_SIZE_512] = {0};
144 int ret = -1;
145 if (catcher != nullptr) {
146 catcher->Stop();
147 // sleep 1s for syncing log to the fd, then we could append failure reason ?
148 sleep(1);
149 std::string summary = catcher->GetDescription();
150 ret = snprintf_s(buf, BUF_SIZE_512, BUF_SIZE_512 - 1, "\nTask stopped when running catcher:%s, Reason:%s \n",
151 summary.c_str(), reason.c_str());
152 } else {
153 ret = snprintf_s(buf, BUF_SIZE_512, BUF_SIZE_512 - 1, "\nTask stopped, Reason:%s \n", reason.c_str());
154 }
155
156 if (ret > 0) {
157 write(fd, buf, strnlen(buf, BUF_SIZE_512));
158 fsync(fd);
159 }
160 }
161
AddSeparator(int fd,std::shared_ptr<EventLogCatcher> catcher) const162 void EventLogTask::AddSeparator(int fd, std::shared_ptr<EventLogCatcher> catcher) const
163 {
164 char buf[BUF_SIZE_512] = {0};
165 std::string summary = catcher->GetDescription();
166 if (summary.empty()) {
167 HIVIEW_LOGE("summary.empty() catcher is %{public}s", catcher->GetName().c_str());
168 return;
169 }
170
171 int ret = snprintf_s(buf, BUF_SIZE_512, BUF_SIZE_512 - 1, "\n%s\n", summary.c_str());
172 if (ret > 0) {
173 write(fd, buf, strnlen(buf, BUF_SIZE_512));
174 fsync(fd);
175 }
176 }
177
GetTaskStatus() const178 EventLogTask::Status EventLogTask::GetTaskStatus() const
179 {
180 return status_;
181 }
182
GetLogSize() const183 long EventLogTask::GetLogSize() const
184 {
185 return taskLogSize_;
186 }
187
AppStackCapture()188 void EventLogTask::AppStackCapture()
189 {
190 auto capture = std::make_shared<OpenStacktraceCatcher>();
191 capture->Initialize(event_->GetEventValue("PACKAGE_NAME"), pid_, 0);
192 tasks_.push_back(capture);
193 }
194
SystemStackCapture()195 void EventLogTask::SystemStackCapture()
196 {
197 for (auto packageName : SYSTEM_STACK) {
198 auto capture = std::make_shared<OpenStacktraceCatcher>();
199 capture->Initialize(packageName, 0, 0);
200 tasks_.push_back(capture);
201 }
202 }
203
BinderLogCapture()204 void EventLogTask::BinderLogCapture()
205 {
206 auto capture = std::make_shared<BinderCatcher>();
207 capture->Initialize("", 0, 0);
208 tasks_.push_back(capture);
209 }
210
PeerBinderCapture(const std::string & cmd)211 bool EventLogTask::PeerBinderCapture(const std::string &cmd)
212 {
213 auto find = cmd.find("pb");
214 if (find == cmd.npos) {
215 return false;
216 }
217
218 std::vector<std::string> cmdList;
219 StringUtil::SplitStr(cmd, ":", cmdList, true);
220 if (cmdList.size() != PeerBinderCatcher::BP_CMD_SZ || cmdList.front() != "pb") {
221 return false;
222 }
223
224 auto capture = std::make_shared<PeerBinderCatcher>();
225 capture->Initialize(cmdList[PeerBinderCatcher::BP_CMD_PERF_TYPE_INDEX],
226 StringUtil::StrToInt(cmdList[PeerBinderCatcher::BP_CMD_LAYER_INDEX]), pid_);
227 capture->Init(event_, "");
228 tasks_.push_back(capture);
229 return true;
230 }
231
WMSUsageCapture()232 void EventLogTask::WMSUsageCapture()
233 {
234 auto capture = std::make_shared<ShellCatcher>();
235 capture->Initialize("hidumper -s WindowManagerService -a -a", ShellCatcher::CATCHER_WMS, pid_);
236 tasks_.push_back(capture);
237 }
238
AMSUsageCapture()239 void EventLogTask::AMSUsageCapture()
240 {
241 auto capture = std::make_shared<ShellCatcher>();
242 capture->Initialize("hidumper -s AbilityManagerService -a -a", ShellCatcher::CATCHER_AMS, pid_);
243 tasks_.push_back(capture);
244 }
245
CpuUsageCapture()246 void EventLogTask::CpuUsageCapture()
247 {
248 auto capture = std::make_shared<ShellCatcher>();
249 capture->Initialize("hidumper --cpuusage", ShellCatcher::CATCHER_CPU, pid_);
250 tasks_.push_back(capture);
251 }
252
MemoryUsageCapture()253 void EventLogTask::MemoryUsageCapture()
254 {
255 auto capture = std::make_shared<ShellCatcher>();
256 capture->Initialize("hidumper --mem", ShellCatcher::CATCHER_MEM, pid_);
257 tasks_.push_back(capture);
258 }
259
PMSUsageCapture()260 void EventLogTask::PMSUsageCapture()
261 {
262 auto capture = std::make_shared<ShellCatcher>();
263 capture->Initialize("hidumper -s PowerManagerService -a -s", ShellCatcher::CATCHER_PMS, pid_);
264 tasks_.push_back(capture);
265 }
266
DPMSUsageCapture()267 void EventLogTask::DPMSUsageCapture()
268 {
269 auto capture = std::make_shared<ShellCatcher>();
270 capture->Initialize("hidumper -s DisplayPowerManagerService", ShellCatcher::CATCHER_DPMS, pid_);
271 tasks_.push_back(capture);
272 }
273
HilogCapture()274 void EventLogTask::HilogCapture()
275 {
276 auto capture = std::make_shared<ShellCatcher>();
277 capture->Initialize("hilog -x", ShellCatcher::CATCHER_HILOG, 0);
278 tasks_.push_back(capture);
279 }
280
DmesgCapture()281 void EventLogTask::DmesgCapture()
282 {
283 auto capture = std::make_shared<DmesgCatcher>();
284 capture->Initialize("", 0, 0);
285 capture->Init(event_);
286 tasks_.push_back(capture);
287 }
288
SysrqCapture(bool isWriteNewFile)289 void EventLogTask::SysrqCapture(bool isWriteNewFile)
290 {
291 auto capture = std::make_shared<DmesgCatcher>();
292 capture->Initialize("", isWriteNewFile, 1);
293 capture->Init(event_);
294 tasks_.push_back(capture);
295 }
296 } // namespace HiviewDFX
297 } // namespace OHOS
298