• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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_mgr_client.h"
22 #include "app_recovery.h"
23 #include "appfreeze_inner.h"
24 #include "hisysevent.h"
25 #include "hilog_wrapper.h"
26 #include "mix_stack_dumper.h"
27 #include "xcollie/watchdog.h"
28 
29 namespace OHOS {
30 namespace AppExecFwk {
31 namespace {
32 constexpr uint32_t CHECK_MAIN_THREAD_IS_ALIVE = 1;
33 constexpr int RESET_RATIO = 2;
34 
35 #ifdef SUPPORT_ASAN
36 constexpr uint32_t CHECK_INTERVAL_TIME = 45000;
37 #else
38 constexpr uint32_t CHECK_INTERVAL_TIME = 3000;
39 #endif
40 }
41 std::shared_ptr<EventHandler> Watchdog::appMainHandler_ = nullptr;
42 
Watchdog()43 Watchdog::Watchdog()
44 {}
45 
~Watchdog()46 Watchdog::~Watchdog()
47 {
48     if (!stopWatchdog_) {
49         HILOG_DEBUG("Stop watchdog when deconstruct.");
50         OHOS::HiviewDFX::Watchdog::GetInstance().StopWatchdog();
51     }
52 }
53 
Init(const std::shared_ptr<EventHandler> mainHandler)54 void Watchdog::Init(const std::shared_ptr<EventHandler> mainHandler)
55 {
56     Watchdog::appMainHandler_ = mainHandler;
57     if (appMainHandler_ != nullptr) {
58         HILOG_DEBUG("Watchdog init send event");
59         appMainHandler_->SendEvent(CHECK_MAIN_THREAD_IS_ALIVE);
60     }
61     lastWatchTime_ = 0;
62     auto watchdogTask = std::bind(&Watchdog::Timer, this);
63     OHOS::HiviewDFX::Watchdog::GetInstance().RunPeriodicalTask("AppkitWatchdog", watchdogTask,
64         CHECK_INTERVAL_TIME, INI_TIMER_FIRST_SECOND);
65 }
66 
Stop()67 void Watchdog::Stop()
68 {
69     HILOG_DEBUG("Watchdog is stop!");
70     std::unique_lock<std::mutex> lock(cvMutex_);
71     if (stopWatchdog_) {
72         HILOG_DEBUG("Watchdog has stoped.");
73         return;
74     }
75     stopWatchdog_.store(true);
76     cvWatchdog_.notify_all();
77     OHOS::HiviewDFX::Watchdog::GetInstance().StopWatchdog();
78 
79     if (appMainHandler_) {
80         appMainHandler_.reset();
81         appMainHandler_ = nullptr;
82     }
83 }
84 
SetAppMainThreadState(const bool appMainThreadState)85 void Watchdog::SetAppMainThreadState(const bool appMainThreadState)
86 {
87     appMainThreadIsAlive_.store(appMainThreadState);
88 }
89 
SetBackgroundStatus(const bool isInBackground)90 void Watchdog::SetBackgroundStatus(const bool isInBackground)
91 {
92     isInBackground_.store(isInBackground);
93 }
94 
AllowReportEvent()95 void Watchdog::AllowReportEvent()
96 {
97     needReport_.store(true);
98     isSixSecondEvent_.store(false);
99 }
100 
IsReportEvent()101 bool Watchdog::IsReportEvent()
102 {
103     if (appMainThreadIsAlive_) {
104         appMainThreadIsAlive_.store(false);
105         return false;
106     }
107     HILOG_DEBUG("AppMainThread is not alive");
108     return true;
109 }
110 
IsStopWatchdog()111 bool Watchdog::IsStopWatchdog()
112 {
113     return stopWatchdog_;
114 }
115 
Timer()116 void Watchdog::Timer()
117 {
118     std::unique_lock<std::mutex> lock(cvMutex_);
119     if (stopWatchdog_) {
120         HILOG_DEBUG("Watchdog has stoped.");
121         return;
122     }
123     if (!needReport_) {
124         HILOG_ERROR("Watchdog timeout, wait for the handler to recover, and do not send event.");
125         return;
126     }
127 
128     if (isInBackground_) {
129         appMainThreadIsAlive_.store(true);
130         return;
131     }
132 
133     if (IsReportEvent()) {
134         const int bufferLen = 128;
135         char paramOutBuf[bufferLen] = {0};
136         const char *hook_mode = "startup:";
137         int ret = GetParameter("libc.hook_mode", "", paramOutBuf, bufferLen);
138         if (ret <= 0 || strncmp(paramOutBuf, hook_mode, strlen(hook_mode)) != 0) {
139             ReportEvent();
140         }
141     }
142     if (appMainHandler_ != nullptr) {
143         appMainHandler_->SendEvent(CHECK_MAIN_THREAD_IS_ALIVE);
144     }
145     int64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::
146         system_clock::now().time_since_epoch()).count();
147     if ((now - lastWatchTime_) >= (CHECK_INTERVAL_TIME / RESET_RATIO)) {
148         lastWatchTime_ = now;
149     }
150 }
151 
ReportEvent()152 void Watchdog::ReportEvent()
153 {
154     int64_t now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::
155         system_clock::now().time_since_epoch()).count();
156     if ((now - lastWatchTime_) > (RESET_RATIO * CHECK_INTERVAL_TIME) ||
157         (now - lastWatchTime_) < (CHECK_INTERVAL_TIME / RESET_RATIO)) {
158         HILOG_INFO("Thread may be blocked, do not report this time. currTime: %{public}llu, lastTime: %{public}llu",
159             static_cast<unsigned long long>(now), static_cast<unsigned long long>(lastWatchTime_));
160         return;
161     }
162 
163     if (!needReport_) {
164         return;
165     }
166 
167     if (isSixSecondEvent_) {
168         needReport_.store(false);
169     }
170     AppExecFwk::AppfreezeInner::GetInstance()->ThreadBlock(isSixSecondEvent_);
171 }
172 }  // namespace AppExecFwk
173 }  // namespace OHOS
174