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