• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "hichecker.h"
17 
18 #include <csignal>
19 #include <cerrno>
20 #include <sys/types.h>
21 #include <unistd.h>
22 #include <cstring>
23 #include <cstdio>
24 #include <cstdlib>
25 #include <parameter.h>
26 
27 #include "securec.h"
28 
29 #include "dfx_dump_catcher.h"
30 #include "hilog/log_c.h"
31 #include "hilog/log_cpp.h"
32 
33 namespace OHOS {
34 namespace HiviewDFX {
35 #define PARAM_BUF_LEN 128
36 #define QUERYNAME_LEN 80
37 #undef LOG_DOMAIN
38 #define LOG_DOMAIN 0xD002D0B
39 #undef LOG_TAG
40 #define LOG_TAG "HICHECKER"
41 
42 std::mutex HiChecker::mutexLock_;
43 volatile bool HiChecker::checkMode_;
44 volatile uint64_t HiChecker::processRules_;
45 thread_local uint64_t HiChecker::threadLocalRules_;
46 
AddRule(uint64_t rule)47 void HiChecker::AddRule(uint64_t rule)
48 {
49     std::lock_guard<std::mutex> lock(mutexLock_);
50     if (!CheckRule(rule)) {
51         return;
52     }
53     if ((Rule::RULE_CHECK_SLOW_EVENT & rule)) {
54         checkMode_ = true;
55     }
56     threadLocalRules_ |= (Rule::ALL_THREAD_RULES | Rule::ALL_CAUTION_RULES) & rule;
57     processRules_ |= (Rule::ALL_PROCESS_RULES | Rule::ALL_CAUTION_RULES) & rule;
58 }
59 
RemoveRule(uint64_t rule)60 void HiChecker::RemoveRule(uint64_t rule)
61 {
62     std::lock_guard<std::mutex> lock(mutexLock_);
63     if (!CheckRule(rule)) {
64         return;
65     }
66     if ((Rule::RULE_CHECK_SLOW_EVENT & rule)) {
67         checkMode_ = false;
68     }
69     threadLocalRules_ ^= threadLocalRules_ & rule;
70     processRules_ ^= processRules_ & rule;
71 }
72 
GetRule()73 uint64_t HiChecker::GetRule()
74 {
75     std::lock_guard<std::mutex> lock(mutexLock_);
76     return (threadLocalRules_ | processRules_);
77 }
78 
Contains(uint64_t rule)79 bool HiChecker::Contains(uint64_t rule)
80 {
81     std::lock_guard<std::mutex> lock(mutexLock_);
82     if (!CheckRule(rule)) {
83         return false;
84     }
85     return rule == (rule & (threadLocalRules_ | processRules_));
86 }
87 
NotifySlowProcess(const std::string & tag)88 void HiChecker::NotifySlowProcess(const std::string& tag)
89 {
90     if ((threadLocalRules_ & Rule::RULE_THREAD_CHECK_SLOW_PROCESS) == 0) {
91         return;
92     }
93     std::string stackTrace;
94     DumpStackTrace(stackTrace);
95     Caution caution(Rule::RULE_THREAD_CHECK_SLOW_PROCESS,
96         "trigger:RULE_THREAD_CHECK_SLOW_PROCESS," + tag, stackTrace);
97     HandleCaution(caution);
98 }
99 
NotifySlowEvent(const std::string & tag)100 void HiChecker::NotifySlowEvent(const std::string& tag)
101 {
102     if ((processRules_ & Rule::RULE_CHECK_SLOW_EVENT) == 0) {
103         return;
104     }
105     std::string stackTrace;
106     DumpStackTrace(stackTrace);
107     Caution caution(Rule::RULE_CHECK_SLOW_EVENT,
108         "trigger:RULE_CHECK_SLOW_EVENT," + tag, stackTrace);
109     HandleCaution(caution);
110 }
111 
NotifyAbilityConnectionLeak(const Caution & caution)112 void HiChecker::NotifyAbilityConnectionLeak(const Caution& caution)
113 {
114     if ((processRules_ & Rule::RULE_CHECK_ABILITY_CONNECTION_LEAK) == 0) {
115         return;
116     }
117     HandleCaution(caution);
118 }
119 
NotifyCaution(uint64_t rule,const std::string & tag,Caution & caution)120 void HiChecker::NotifyCaution(uint64_t rule, const std::string& tag, Caution& caution)
121 {
122     if ((threadLocalRules_ & rule) == 0 && (processRules_ & rule) == 0) {
123         return;
124     }
125     std::string msg;
126     switch (rule) {
127         case Rule::RULE_THREAD_CHECK_SLOW_PROCESS:
128             msg = "trigger:RULE_THREAD_CHECK_SLOW_PROCESS," + tag;
129             break;
130         case Rule::RULE_CHECK_SLOW_EVENT:
131             msg = "trigger:RULE_CHECK_SLOW_EVENT," + tag;
132             break;
133         case Rule::RULE_CHECK_ARKUI_PERFORMANCE:
134             msg = "trigger:RULE_CHECK_ARKUI_PERFORMANCE," + tag;
135             break;
136         default:
137             break;
138     }
139     if (Rule::RULE_CHECK_ABILITY_CONNECTION_LEAK != rule) {
140         std::string stackTrace;
141         DumpStackTrace(stackTrace);
142         caution.SetCautionMsg(msg);
143         caution.SetStackTrace(stackTrace);
144     }
145     HandleCaution(caution);
146 }
147 
HandleCaution(const Caution & caution)148 void HiChecker::HandleCaution(const Caution& caution)
149 {
150     uint64_t triggerRule = caution.GetTriggerRule();
151     if ((threadLocalRules_ & triggerRule)) {
152         CautionDetail cautionDetail(caution, threadLocalRules_);
153         OnThreadCautionFound(cautionDetail);
154         return;
155     }
156     if ((processRules_ & triggerRule)) {
157         CautionDetail cautionDetail(caution, processRules_);
158         OnProcessCautionFound(cautionDetail);
159         return;
160     }
161 }
162 
OnThreadCautionFound(CautionDetail & cautionDetail)163 void HiChecker::OnThreadCautionFound(CautionDetail& cautionDetail)
164 {
165     if ((cautionDetail.rules_ & Rule::ALL_CAUTION_RULES) == 0) {
166         cautionDetail.rules_ |= Rule::RULE_CAUTION_PRINT_LOG;
167     }
168     if (cautionDetail.CautionEnable(Rule::RULE_CAUTION_PRINT_LOG)
169         && !cautionDetail.CautionEnable(Rule::RULE_CAUTION_TRIGGER_CRASH)) {
170         PrintLog(cautionDetail);
171     }
172     if (cautionDetail.CautionEnable(Rule::RULE_CAUTION_TRIGGER_CRASH)) {
173         TriggerCrash(cautionDetail);
174     }
175 }
176 
OnProcessCautionFound(CautionDetail & cautionDetail)177 void HiChecker::OnProcessCautionFound(CautionDetail& cautionDetail)
178 {
179     OnThreadCautionFound(cautionDetail);
180 }
181 
PrintLog(const CautionDetail & cautionDetail)182 void HiChecker::PrintLog(const CautionDetail& cautionDetail)
183 {
184     HILOG_INFO(LOG_CORE,
185         "HiChecker caution with RULE_CAUTION_PRINT_LOG.\nCautionMsg:%{public}s\nStackTrace:\n%{public}s",
186         cautionDetail.caution_.GetCautionMsg().c_str(),
187         cautionDetail.caution_.GetStackTrace().c_str());
188 }
189 
TriggerCrash(const CautionDetail & cautionDetail)190 void HiChecker::TriggerCrash(const CautionDetail& cautionDetail)
191 {
192     HILOG_INFO(LOG_CORE,
193         "HiChecker caution with RULE_CAUTION_TRIGGER_CRASH; exit.\nCautionMsg:%{public}s\nStackTrace:\n%{public}s",
194         cautionDetail.caution_.GetCautionMsg().c_str(),
195         cautionDetail.caution_.GetStackTrace().c_str());
196     kill(getpid(), SIGABRT);
197 }
198 
NeedCheckSlowEvent()199 bool HiChecker::NeedCheckSlowEvent()
200 {
201     return checkMode_;
202 }
203 
HasCautionRule(uint64_t rules)204 bool HiChecker::HasCautionRule(uint64_t rules)
205 {
206     return (rules & Rule::ALL_CAUTION_RULES);
207 }
208 
DumpStackTrace(std::string & msg)209 void HiChecker::DumpStackTrace(std::string& msg)
210 {
211     DfxDumpCatcher dumplog;
212     if (!dumplog.DumpCatch(getpid(), gettid(), msg)) {
213         HILOG_INFO(LOG_CORE, "HiChecker DumpStackTrace fail.");
214     }
215 }
216 
CheckRule(uint64_t rule)217 bool HiChecker::CheckRule(uint64_t rule)
218 {
219     if (rule <= 0 || Rule::ALL_RULES != (Rule::ALL_RULES | rule)) {
220         HILOG_INFO(LOG_CORE, "input rule is not exist,please check.");
221         return false;
222     }
223     return true;
224 }
225 
InitHicheckerParam(const char * processName)226 void HiChecker::InitHicheckerParam(const char *processName)
227 {
228     HILOG_INFO(LOG_CORE, "hichecker processName is %{public}s", processName);
229     char checkerName[QUERYNAME_LEN] = "hiviewdfx.hichecker.";
230     errno_t err = 0;
231     err = strcat_s(checkerName, sizeof(checkerName), processName);
232     if (err != EOK) {
233         HILOG_INFO(LOG_CORE, "checker strcat_s query name failed.");
234         return;
235     }
236 
237     char paramOutBuf[PARAM_BUF_LEN] = { 0 };
238     char defStrValue[PARAM_BUF_LEN] = { 0 };
239     int retLen = GetParameter(checkerName, defStrValue, paramOutBuf, PARAM_BUF_LEN);
240     if (retLen == 0 || retLen > PARAM_BUF_LEN - 1) {
241         HILOG_INFO(LOG_CORE, "hichecker param is empty.");
242         return;
243     }
244     paramOutBuf[retLen] = '\0';
245     HILOG_INFO(LOG_CORE, "hichecker param value is %{public}s", paramOutBuf);
246     std::string paramStr(paramOutBuf);
247     uint64_t rule = std::stoull(paramStr);
248     AddRule(rule);
249     return;
250 }
251 } // HiviewDFX
252 } // OHOS
253