• 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 "watchdog.h"
17 
18 #include <parameter.h>
19 #include <unistd.h>
20 
21 #include "app_recovery.h"
22 #include "hisysevent.h"
23 #include "hilog_wrapper.h"
24 #include "xcollie/watchdog.h"
25 
26 namespace OHOS {
27 namespace AppExecFwk {
28 namespace {
29 constexpr char EVENT_KEY_UID[] = "UID";
30 constexpr char EVENT_KEY_PID[] = "PID";
31 constexpr char EVENT_KEY_MESSAGE[] = "MSG";
32 constexpr char EVENT_KEY_PACKAGE_NAME[] = "PACKAGE_NAME";
33 constexpr char EVENT_KEY_PROCESS_NAME[] = "PROCESS_NAME";
34 constexpr uint32_t CHECK_MAIN_THREAD_IS_ALIVE = 1;
35 
36 #ifdef SUPPORT_ASAN
37 constexpr uint32_t CHECK_INTERVAL_TIME = 45000;
38 #else
39 constexpr uint32_t CHECK_INTERVAL_TIME = 3000;
40 #endif
41 }
42 std::shared_ptr<EventHandler> Watchdog::appMainHandler_ = nullptr;
43 
Watchdog()44 Watchdog::Watchdog()
45 {}
46 
~Watchdog()47 Watchdog::~Watchdog()
48 {
49     if (!stopWatchdog_) {
50         HILOG_DEBUG("Stop watchdog when deconstruct.");
51         OHOS::HiviewDFX::Watchdog::GetInstance().StopWatchdog();
52     }
53 }
54 
Init(const std::shared_ptr<EventHandler> mainHandler)55 void Watchdog::Init(const std::shared_ptr<EventHandler> mainHandler)
56 {
57     Watchdog::appMainHandler_ = mainHandler;
58     if (appMainHandler_ != nullptr) {
59         HILOG_DEBUG("Watchdog init send event");
60         appMainHandler_->SendEvent(CHECK_MAIN_THREAD_IS_ALIVE);
61     }
62     lastWatchTime_ = 0;
63     auto watchdogTask = std::bind(&Watchdog::Timer, this);
64     OHOS::HiviewDFX::Watchdog::GetInstance().RunPeriodicalTask("AppkitWatchdog", watchdogTask,
65         CHECK_INTERVAL_TIME, INI_TIMER_FIRST_SECOND);
66 }
67 
Stop()68 void Watchdog::Stop()
69 {
70     HILOG_DEBUG("Watchdog is stop!");
71     std::unique_lock<std::mutex> lock(cvMutex_);
72     if (stopWatchdog_) {
73         HILOG_DEBUG("Watchdog has stoped.");
74         return;
75     }
76     stopWatchdog_.store(true);
77     cvWatchdog_.notify_all();
78     OHOS::HiviewDFX::Watchdog::GetInstance().StopWatchdog();
79 
80     if (appMainHandler_) {
81         appMainHandler_.reset();
82         appMainHandler_ = nullptr;
83     }
84 }
85 
SetApplicationInfo(const std::shared_ptr<ApplicationInfo> & applicationInfo)86 void Watchdog::SetApplicationInfo(const std::shared_ptr<ApplicationInfo> &applicationInfo)
87 {
88     applicationInfo_ = applicationInfo;
89 }
90 
SetAppMainThreadState(const bool appMainThreadState)91 void Watchdog::SetAppMainThreadState(const bool appMainThreadState)
92 {
93     appMainThreadIsAlive_.store(appMainThreadState);
94 }
95 
SetBackgroundStatus(const bool isInBackground)96 void Watchdog::SetBackgroundStatus(const bool isInBackground)
97 {
98     isInBackground_.store(isInBackground);
99 }
100 
AllowReportEvent()101 void Watchdog::AllowReportEvent()
102 {
103     needReport_.store(true);
104     isSixSecondEvent_.store(false);
105 }
106 
IsReportEvent()107 bool Watchdog::IsReportEvent()
108 {
109     if (appMainThreadIsAlive_) {
110         appMainThreadIsAlive_.store(false);
111         return false;
112     }
113     HILOG_DEBUG("AppMainThread is not alive");
114     return true;
115 }
116 
IsStopWatchdog()117 bool Watchdog::IsStopWatchdog()
118 {
119     return stopWatchdog_;
120 }
121 
Timer()122 void Watchdog::Timer()
123 {
124     std::unique_lock<std::mutex> lock(cvMutex_);
125     if (stopWatchdog_) {
126         HILOG_DEBUG("Watchdog has stoped.");
127         return;
128     }
129     if (!needReport_) {
130         HILOG_ERROR("Watchdog timeout, wait for the handler to recover, and do not send event.");
131         return;
132     }
133 
134     if (isInBackground_) {
135         appMainThreadIsAlive_.store(true);
136         return;
137     }
138 
139     if (IsReportEvent()) {
140         const int bufferLen = 128;
141         char paramOutBuf[bufferLen] = {0};
142         const char *hook_mode = "startup:";
143         int ret = GetParameter("libc.hook_mode", "", paramOutBuf, bufferLen);
144         if (ret <= 0 || strncmp(paramOutBuf, hook_mode, strlen(hook_mode)) != 0) {
145             reportEvent();
146         }
147     }
148     if (appMainHandler_ != nullptr) {
149         appMainHandler_->SendEvent(CHECK_MAIN_THREAD_IS_ALIVE);
150     }
151     lastWatchTime_ = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::
152         system_clock::now().time_since_epoch()).count();
153 }
154 
reportEvent()155 void Watchdog::reportEvent()
156 {
157     int64_t now = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::
158         system_clock::now().time_since_epoch()).count();
159     constexpr int RESET_RATIO = 2;
160     if ((now - lastWatchTime_) > (RESET_RATIO * CHECK_INTERVAL_TIME)) {
161         HILOG_INFO("Thread may be blocked, do not report this time. currTime: %{public}llu, lastTime: %{public}llu",
162             static_cast<unsigned long long>(now), static_cast<unsigned long long>(lastWatchTime_));
163         lastWatchTime_ = now;
164         return;
165     }
166 
167     if (applicationInfo_ == nullptr) {
168         HILOG_ERROR("reportEvent fail, applicationInfo_ is nullptr.");
169         return;
170     }
171 
172     if (!needReport_) {
173         return;
174     }
175 
176     std::string eventType;
177     if (isSixSecondEvent_) {
178         eventType = "THREAD_BLOCK_6S";
179         needReport_.store(false);
180     } else {
181         eventType = "THREAD_BLOCK_3S";
182         isSixSecondEvent_.store(true);
183     }
184 
185     HILOG_DEBUG("Start dump message.");
186     std::string msgContent = "App main thread is not response!";
187     MainHandlerDumper handlerDumper;
188     appMainHandler_->Dump(handlerDumper);
189     msgContent += handlerDumper.GetDumpInfo();
190     HILOG_DEBUG("msgContent is %{public}s", msgContent.c_str());
191 
192     OHOS::HiviewDFX::HiSysEvent::Write(OHOS::HiviewDFX::HiSysEvent::Domain::AAFWK, eventType,
193         OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, EVENT_KEY_UID, applicationInfo_->uid,
194         EVENT_KEY_PID, static_cast<int32_t>(getpid()), EVENT_KEY_PACKAGE_NAME, applicationInfo_->bundleName,
195         EVENT_KEY_PROCESS_NAME, applicationInfo_->process, EVENT_KEY_MESSAGE, msgContent);
196     HILOG_INFO("reportEvent success, %{public}zu %{public}s", msgContent.size(), msgContent.c_str());
197 
198     // should call error manager-> appRecovery
199     if (isSixSecondEvent_) {
200         AppRecovery::GetInstance().ScheduleSaveAppState(StateReason::APP_FREEZE);
201         AppRecovery::GetInstance().ScheduleRecoverApp(StateReason::APP_FREEZE);
202     }
203 }
204 
Dump(const std::string & message)205 void MainHandlerDumper::Dump(const std::string &message)
206 {
207     dumpInfo += message;
208 }
209 
GetTag()210 std::string MainHandlerDumper::GetTag()
211 {
212     return "";
213 }
214 
GetDumpInfo()215 std::string MainHandlerDumper::GetDumpInfo()
216 {
217     return dumpInfo;
218 }
219 }  // namespace AppExecFwk
220 }  // namespace OHOS
221