• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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