1209bc2fbSopenharmony_ci/*
2209bc2fbSopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3209bc2fbSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4209bc2fbSopenharmony_ci * you may not use this file except in compliance with the License.
5209bc2fbSopenharmony_ci * You may obtain a copy of the License at
6209bc2fbSopenharmony_ci *
7209bc2fbSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8209bc2fbSopenharmony_ci *
9209bc2fbSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10209bc2fbSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11209bc2fbSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12209bc2fbSopenharmony_ci * See the License for the specific language governing permissions and
13209bc2fbSopenharmony_ci * limitations under the License.
14209bc2fbSopenharmony_ci */
15209bc2fbSopenharmony_ci
16209bc2fbSopenharmony_ci#include "watchdog_task.h"
17209bc2fbSopenharmony_ci
18209bc2fbSopenharmony_ci#include <cinttypes>
19209bc2fbSopenharmony_ci#include <ctime>
20209bc2fbSopenharmony_ci#include <cstdio>
21209bc2fbSopenharmony_ci#include <securec.h>
22209bc2fbSopenharmony_ci#include <thread>
23209bc2fbSopenharmony_ci
24209bc2fbSopenharmony_ci#include <fcntl.h>
25209bc2fbSopenharmony_ci#include <dlfcn.h>
26209bc2fbSopenharmony_ci#include <unistd.h>
27209bc2fbSopenharmony_ci
28209bc2fbSopenharmony_ci#include "backtrace_local.h"
29209bc2fbSopenharmony_ci#include "musl_preinit_common.h"
30209bc2fbSopenharmony_ci#include "watchdog_inner.h"
31209bc2fbSopenharmony_ci#include "xcollie_define.h"
32209bc2fbSopenharmony_ci#include "xcollie_utils.h"
33209bc2fbSopenharmony_ci
34209bc2fbSopenharmony_ci#ifdef HISYSEVENT_ENABLE
35209bc2fbSopenharmony_ci#include "hisysevent.h"
36209bc2fbSopenharmony_ci#endif
37209bc2fbSopenharmony_ci
38209bc2fbSopenharmony_cinamespace OHOS {
39209bc2fbSopenharmony_cinamespace HiviewDFX {
40209bc2fbSopenharmony_cinamespace {
41209bc2fbSopenharmony_cistatic const int COUNT_LIMIT_NUM_MAX_RATIO = 2;
42209bc2fbSopenharmony_cistatic const int TIME_LIMIT_NUM_MAX_RATIO = 2;
43209bc2fbSopenharmony_cistatic const int UID_TYPE_THRESHOLD = 20000;
44209bc2fbSopenharmony_ciconstexpr int32_t SAMGR_INIT_UID = 5555;
45209bc2fbSopenharmony_ciconstexpr const char* CORE_PROCS[] = {
46209bc2fbSopenharmony_ci    "anco_service_br", "aptouch_daemon", "foundation", "init", "multimodalinput", "ohos.sceneboard", "render_service"
47209bc2fbSopenharmony_ci};
48209bc2fbSopenharmony_ci}
49209bc2fbSopenharmony_ciint64_t WatchdogTask::curId = 0;
50209bc2fbSopenharmony_ciWatchdogTask::WatchdogTask(std::string name, std::shared_ptr<AppExecFwk::EventHandler> handler,
51209bc2fbSopenharmony_ci    TimeOutCallback timeOutCallback, uint64_t interval)
52209bc2fbSopenharmony_ci    : name(name), task(nullptr), timeOutCallback(timeOutCallback), timeout(0), func(nullptr),
53209bc2fbSopenharmony_ci      arg(nullptr), flag(0), timeLimit(0), countLimit(0)
54209bc2fbSopenharmony_ci{
55209bc2fbSopenharmony_ci    id = ++curId;
56209bc2fbSopenharmony_ci    checker = std::make_shared<HandlerChecker>(name, handler);
57209bc2fbSopenharmony_ci    checkInterval = interval;
58209bc2fbSopenharmony_ci    nextTickTime = GetCurrentTickMillseconds();
59209bc2fbSopenharmony_ci    isTaskScheduled = false;
60209bc2fbSopenharmony_ci    isOneshotTask = false;
61209bc2fbSopenharmony_ci}
62209bc2fbSopenharmony_ci
63209bc2fbSopenharmony_ciWatchdogTask::WatchdogTask(std::string name, Task&& task, uint64_t delay, uint64_t interval,  bool isOneshot)
64209bc2fbSopenharmony_ci    : name(name), task(std::move(task)), timeOutCallback(nullptr), checker(nullptr), timeout(0), func(nullptr),
65209bc2fbSopenharmony_ci      arg(nullptr), flag(0), watchdogTid(0), timeLimit(0), countLimit(0)
66209bc2fbSopenharmony_ci{
67209bc2fbSopenharmony_ci    id = ++curId;
68209bc2fbSopenharmony_ci    checkInterval = interval;
69209bc2fbSopenharmony_ci    nextTickTime = GetCurrentTickMillseconds() + delay;
70209bc2fbSopenharmony_ci    isTaskScheduled = false;
71209bc2fbSopenharmony_ci    isOneshotTask = isOneshot;
72209bc2fbSopenharmony_ci}
73209bc2fbSopenharmony_ci
74209bc2fbSopenharmony_ciWatchdogTask::WatchdogTask(std::string name, unsigned int timeout, XCollieCallback func, void *arg, unsigned int flag)
75209bc2fbSopenharmony_ci    : name(name), task(nullptr), timeOutCallback(nullptr), checker(nullptr), timeout(timeout), func(std::move(func)),
76209bc2fbSopenharmony_ci      arg(arg), flag(flag), timeLimit(0), countLimit(0)
77209bc2fbSopenharmony_ci{
78209bc2fbSopenharmony_ci    id = ++curId;
79209bc2fbSopenharmony_ci    checkInterval = 0;
80209bc2fbSopenharmony_ci    nextTickTime = GetCurrentTickMillseconds() + timeout;
81209bc2fbSopenharmony_ci    isTaskScheduled = false;
82209bc2fbSopenharmony_ci    isOneshotTask = true;
83209bc2fbSopenharmony_ci    watchdogTid = getproctid();
84209bc2fbSopenharmony_ci}
85209bc2fbSopenharmony_ci
86209bc2fbSopenharmony_ciWatchdogTask::WatchdogTask(std::string name, unsigned int timeLimit, int countLimit)
87209bc2fbSopenharmony_ci    : name(name), task(nullptr), timeOutCallback(nullptr), timeout(0), func(nullptr), arg(nullptr), flag(0),
88209bc2fbSopenharmony_ci      isTaskScheduled(false), isOneshotTask(false), watchdogTid(0), timeLimit(timeLimit), countLimit(countLimit)
89209bc2fbSopenharmony_ci{
90209bc2fbSopenharmony_ci    id = ++curId;
91209bc2fbSopenharmony_ci    checkInterval = timeLimit / TIME_LIMIT_NUM_MAX_RATIO;
92209bc2fbSopenharmony_ci    nextTickTime = GetCurrentTickMillseconds();
93209bc2fbSopenharmony_ci}
94209bc2fbSopenharmony_ci
95209bc2fbSopenharmony_civoid WatchdogTask::DoCallback()
96209bc2fbSopenharmony_ci{
97209bc2fbSopenharmony_ci    if (func) {
98209bc2fbSopenharmony_ci        XCOLLIE_LOGE("XCollieInner::DoTimerCallback %{public}s callback", name.c_str());
99209bc2fbSopenharmony_ci        func(arg);
100209bc2fbSopenharmony_ci    }
101209bc2fbSopenharmony_ci    if (WatchdogInner::GetInstance().IsCallbackLimit(flag)) {
102209bc2fbSopenharmony_ci        XCOLLIE_LOGE("Too many callback triggered in a short time, %{public}s skip", name.c_str());
103209bc2fbSopenharmony_ci        return;
104209bc2fbSopenharmony_ci    }
105209bc2fbSopenharmony_ci    if (flag & XCOLLIE_FLAG_LOG) {
106209bc2fbSopenharmony_ci        /* send to freezedetetor */
107209bc2fbSopenharmony_ci        std::string msg = "timeout: " + name + " to check " + std::to_string(timeout) + "ms ago";
108209bc2fbSopenharmony_ci        SendXCollieEvent(name, msg);
109209bc2fbSopenharmony_ci    }
110209bc2fbSopenharmony_ci    if (getuid() > UID_TYPE_THRESHOLD) {
111209bc2fbSopenharmony_ci        XCOLLIE_LOGI("check uid is app, do not exit");
112209bc2fbSopenharmony_ci        return;
113209bc2fbSopenharmony_ci    }
114209bc2fbSopenharmony_ci    if (flag & XCOLLIE_FLAG_RECOVERY) {
115209bc2fbSopenharmony_ci        XCOLLIE_LOGE("%{public}s blocked, after timeout %{public}llu ,process will exit", name.c_str(),
116209bc2fbSopenharmony_ci            static_cast<long long>(timeout));
117209bc2fbSopenharmony_ci        std::thread exitFunc([]() {
118209bc2fbSopenharmony_ci            std::string description = "timeout, exit...";
119209bc2fbSopenharmony_ci            WatchdogInner::LeftTimeExitProcess(description);
120209bc2fbSopenharmony_ci        });
121209bc2fbSopenharmony_ci        if (exitFunc.joinable()) {
122209bc2fbSopenharmony_ci            exitFunc.detach();
123209bc2fbSopenharmony_ci        }
124209bc2fbSopenharmony_ci    }
125209bc2fbSopenharmony_ci}
126209bc2fbSopenharmony_ci
127209bc2fbSopenharmony_civoid WatchdogTask::Run(uint64_t now)
128209bc2fbSopenharmony_ci{
129209bc2fbSopenharmony_ci    if (countLimit > 0) {
130209bc2fbSopenharmony_ci        TimerCountTask();
131209bc2fbSopenharmony_ci        return;
132209bc2fbSopenharmony_ci    }
133209bc2fbSopenharmony_ci
134209bc2fbSopenharmony_ci    constexpr int resetRatio = 2;
135209bc2fbSopenharmony_ci    if ((checkInterval != 0) && (now - nextTickTime > (resetRatio * checkInterval))) {
136209bc2fbSopenharmony_ci        XCOLLIE_LOGI("checker thread may be blocked, reset next tick time."
137209bc2fbSopenharmony_ci            "now:%{public}" PRIu64 " expect:%{public}" PRIu64 " interval:%{public}" PRIu64 "",
138209bc2fbSopenharmony_ci            now, nextTickTime, checkInterval);
139209bc2fbSopenharmony_ci        nextTickTime = now;
140209bc2fbSopenharmony_ci        isTaskScheduled = false;
141209bc2fbSopenharmony_ci        return;
142209bc2fbSopenharmony_ci    }
143209bc2fbSopenharmony_ci
144209bc2fbSopenharmony_ci    if (timeout != 0) {
145209bc2fbSopenharmony_ci        if (IsMemHookOn()) {
146209bc2fbSopenharmony_ci            return;
147209bc2fbSopenharmony_ci        }
148209bc2fbSopenharmony_ci        DoCallback();
149209bc2fbSopenharmony_ci    } else if (task != nullptr) {
150209bc2fbSopenharmony_ci        task();
151209bc2fbSopenharmony_ci    } else {
152209bc2fbSopenharmony_ci        RunHandlerCheckerTask();
153209bc2fbSopenharmony_ci    }
154209bc2fbSopenharmony_ci}
155209bc2fbSopenharmony_ci
156209bc2fbSopenharmony_civoid WatchdogTask::TimerCountTask()
157209bc2fbSopenharmony_ci{
158209bc2fbSopenharmony_ci    int size = static_cast<int>(triggerTimes.size());
159209bc2fbSopenharmony_ci    if (size < countLimit) {
160209bc2fbSopenharmony_ci        return;
161209bc2fbSopenharmony_ci    }
162209bc2fbSopenharmony_ci    XCOLLIE_LOGD("timeLimit : %{public}" PRIu64 ", countLimit : %{public}d, triggerTimes size : %{public}d",
163209bc2fbSopenharmony_ci        timeLimit, countLimit, size);
164209bc2fbSopenharmony_ci
165209bc2fbSopenharmony_ci    while (size >= countLimit) {
166209bc2fbSopenharmony_ci        uint64_t timeInterval = triggerTimes[size -1] - triggerTimes[size - countLimit];
167209bc2fbSopenharmony_ci        if (timeInterval < timeLimit) {
168209bc2fbSopenharmony_ci            std::string sendMsg = name + " occured " + std::to_string(countLimit) + " times in " +
169209bc2fbSopenharmony_ci                std::to_string(timeInterval) + " ms, " + message;
170209bc2fbSopenharmony_ci#ifdef HISYSEVENT_ENABLE
171209bc2fbSopenharmony_ci            HiSysEventWrite(HiSysEvent::Domain::FRAMEWORK, name, HiSysEvent::EventType::FAULT,
172209bc2fbSopenharmony_ci                "PID", getprocpid(), "PROCESS_NAME", GetSelfProcName(), "MSG", sendMsg);
173209bc2fbSopenharmony_ci#else
174209bc2fbSopenharmony_ci       XCOLLIE_LOGI("hisysevent not exists");
175209bc2fbSopenharmony_ci#endif
176209bc2fbSopenharmony_ci            triggerTimes.clear();
177209bc2fbSopenharmony_ci            return;
178209bc2fbSopenharmony_ci        }
179209bc2fbSopenharmony_ci        size--;
180209bc2fbSopenharmony_ci    }
181209bc2fbSopenharmony_ci
182209bc2fbSopenharmony_ci    if (triggerTimes.size() > static_cast<unsigned long>(countLimit * COUNT_LIMIT_NUM_MAX_RATIO)) {
183209bc2fbSopenharmony_ci        triggerTimes.erase(triggerTimes.begin(), triggerTimes.end() - countLimit);
184209bc2fbSopenharmony_ci    }
185209bc2fbSopenharmony_ci}
186209bc2fbSopenharmony_ci
187209bc2fbSopenharmony_civoid WatchdogTask::RunHandlerCheckerTask()
188209bc2fbSopenharmony_ci{
189209bc2fbSopenharmony_ci    if (checker == nullptr) {
190209bc2fbSopenharmony_ci        return;
191209bc2fbSopenharmony_ci    }
192209bc2fbSopenharmony_ci
193209bc2fbSopenharmony_ci    if (!isTaskScheduled) {
194209bc2fbSopenharmony_ci        checker->ScheduleCheck();
195209bc2fbSopenharmony_ci        isTaskScheduled = true;
196209bc2fbSopenharmony_ci    } else {
197209bc2fbSopenharmony_ci        if (EvaluateCheckerState() == CheckStatus::COMPLETED) {
198209bc2fbSopenharmony_ci            // allow next check
199209bc2fbSopenharmony_ci            isTaskScheduled = false;
200209bc2fbSopenharmony_ci        }
201209bc2fbSopenharmony_ci    }
202209bc2fbSopenharmony_ci}
203209bc2fbSopenharmony_ci
204209bc2fbSopenharmony_civoid WatchdogTask::SendEvent(const std::string &msg, const std::string &eventName)
205209bc2fbSopenharmony_ci{
206209bc2fbSopenharmony_ci    int32_t pid = getprocpid();
207209bc2fbSopenharmony_ci    if (IsProcessDebug(pid)) {
208209bc2fbSopenharmony_ci        XCOLLIE_LOGI("heap dump or debug for %{public}d, don't report.", pid);
209209bc2fbSopenharmony_ci        return;
210209bc2fbSopenharmony_ci    }
211209bc2fbSopenharmony_ci    uint32_t gid = getgid();
212209bc2fbSopenharmony_ci    uint32_t uid = getuid();
213209bc2fbSopenharmony_ci    time_t curTime = time(nullptr);
214209bc2fbSopenharmony_ci    std::string sendMsg = std::string((ctime(&curTime) == nullptr) ? "" : ctime(&curTime)) +
215209bc2fbSopenharmony_ci        "\n" + msg + "\n";
216209bc2fbSopenharmony_ci    sendMsg += checker->GetDumpInfo();
217209bc2fbSopenharmony_ci
218209bc2fbSopenharmony_ci    watchdogTid = pid;
219209bc2fbSopenharmony_ci    std::string tidFrontStr = "Thread ID = ";
220209bc2fbSopenharmony_ci    std::string tidRearStr = ") is running";
221209bc2fbSopenharmony_ci    std::size_t frontPos = sendMsg.find(tidFrontStr);
222209bc2fbSopenharmony_ci    std::size_t rearPos = sendMsg.find(tidRearStr);
223209bc2fbSopenharmony_ci    std::size_t startPos = frontPos + tidFrontStr.length();
224209bc2fbSopenharmony_ci    if (frontPos != std::string::npos && rearPos != std::string::npos && rearPos > startPos) {
225209bc2fbSopenharmony_ci        size_t tidLength = rearPos - startPos;
226209bc2fbSopenharmony_ci        if (tidLength < std::to_string(INT32_MAX).length()) {
227209bc2fbSopenharmony_ci            std::string tidStr = sendMsg.substr(startPos, tidLength);
228209bc2fbSopenharmony_ci            if (std::all_of(std::begin(tidStr), std::end(tidStr), [] (const char &c) {
229209bc2fbSopenharmony_ci                return isdigit(c);
230209bc2fbSopenharmony_ci            })) {
231209bc2fbSopenharmony_ci                watchdogTid = std::stoi(tidStr);
232209bc2fbSopenharmony_ci            }
233209bc2fbSopenharmony_ci        }
234209bc2fbSopenharmony_ci    }
235209bc2fbSopenharmony_ci
236209bc2fbSopenharmony_ci#ifdef HISYSEVENT_ENABLE
237209bc2fbSopenharmony_ci    int ret = HiSysEventWrite(HiSysEvent::Domain::FRAMEWORK, eventName, HiSysEvent::EventType::FAULT,
238209bc2fbSopenharmony_ci        "PID", pid, "TID", watchdogTid, "TGID", gid, "UID", uid, "MODULE_NAME", name,
239209bc2fbSopenharmony_ci        "PROCESS_NAME", GetSelfProcName(), "MSG", sendMsg, "STACK", GetProcessStacktrace());
240209bc2fbSopenharmony_ci    if (ret == ERR_OVER_SIZE) {
241209bc2fbSopenharmony_ci        std::string stack = "";
242209bc2fbSopenharmony_ci        GetBacktraceStringByTid(stack, watchdogTid, 0, true);
243209bc2fbSopenharmony_ci        ret = HiSysEventWrite(HiSysEvent::Domain::FRAMEWORK, eventName, HiSysEvent::EventType::FAULT,
244209bc2fbSopenharmony_ci            "PID", pid, "TID", watchdogTid, "TGID", gid, "UID", uid, "MODULE_NAME", name,
245209bc2fbSopenharmony_ci            "PROCESS_NAME", GetSelfProcName(), "MSG", sendMsg, "STACK", stack);
246209bc2fbSopenharmony_ci    }
247209bc2fbSopenharmony_ci
248209bc2fbSopenharmony_ci    XCOLLIE_LOGI("hisysevent write result=%{public}d, send event [FRAMEWORK,%{public}s], msg=%{public}s",
249209bc2fbSopenharmony_ci        ret, eventName.c_str(), msg.c_str());
250209bc2fbSopenharmony_ci#else
251209bc2fbSopenharmony_ci       XCOLLIE_LOGI("hisysevent not exists");
252209bc2fbSopenharmony_ci#endif
253209bc2fbSopenharmony_ci}
254209bc2fbSopenharmony_ci
255209bc2fbSopenharmony_civoid WatchdogTask::SendXCollieEvent(const std::string &timerName, const std::string &keyMsg) const
256209bc2fbSopenharmony_ci{
257209bc2fbSopenharmony_ci    XCOLLIE_LOGD("SendXCollieEvent start");
258209bc2fbSopenharmony_ci    int32_t pid = getprocpid();
259209bc2fbSopenharmony_ci    if (IsProcessDebug(pid)) {
260209bc2fbSopenharmony_ci        XCOLLIE_LOGI("heap dump or debug for %{public}d, don't report.", pid);
261209bc2fbSopenharmony_ci        return;
262209bc2fbSopenharmony_ci    }
263209bc2fbSopenharmony_ci    uint32_t gid = getgid();
264209bc2fbSopenharmony_ci    uint32_t uid = getuid();
265209bc2fbSopenharmony_ci    time_t curTime = time(nullptr);
266209bc2fbSopenharmony_ci    std::string sendMsg = std::string((ctime(&curTime) == nullptr) ? "" : ctime(&curTime)) + "\n"+
267209bc2fbSopenharmony_ci        "timeout timer: " + timerName + "\n" +keyMsg;
268209bc2fbSopenharmony_ci
269209bc2fbSopenharmony_ci    std::string userStack = "";
270209bc2fbSopenharmony_ci    if (uid == SAMGR_INIT_UID) {
271209bc2fbSopenharmony_ci        XCOLLIE_LOGD("DumpUserStack dump init stack start");
272209bc2fbSopenharmony_ci        if (!GetBacktraceStringByTid(userStack, 1, 0, true)) {
273209bc2fbSopenharmony_ci            XCOLLIE_LOGE("get tid:1 BacktraceString failed");
274209bc2fbSopenharmony_ci        }
275209bc2fbSopenharmony_ci        XCOLLIE_LOGD("DumpUserStack dump init stack end");
276209bc2fbSopenharmony_ci    }
277209bc2fbSopenharmony_ci
278209bc2fbSopenharmony_ci    std::string eventName = "APP_HICOLLIE";
279209bc2fbSopenharmony_ci    std::string processName = GetSelfProcName();
280209bc2fbSopenharmony_ci    std::string stack = "";
281209bc2fbSopenharmony_ci    if (uid <= UID_TYPE_THRESHOLD) {
282209bc2fbSopenharmony_ci        eventName = std::find(std::begin(CORE_PROCS), std::end(CORE_PROCS), processName) != std::end(CORE_PROCS) ?
283209bc2fbSopenharmony_ci            "SERVICE_TIMEOUT" : "SERVICE_TIMEOUT_WARNING";
284209bc2fbSopenharmony_ci        stack = GetProcessStacktrace();
285209bc2fbSopenharmony_ci    } else if (!GetBacktraceStringByTid(stack, watchdogTid, 0, true)) {
286209bc2fbSopenharmony_ci        XCOLLIE_LOGE("get tid:%{public}d BacktraceString failed", watchdogTid);
287209bc2fbSopenharmony_ci    }
288209bc2fbSopenharmony_ci#ifdef HISYSEVENT_ENABLE
289209bc2fbSopenharmony_ci    int result = HiSysEventWrite(HiSysEvent::Domain::FRAMEWORK, eventName, HiSysEvent::EventType::FAULT, "PID", pid,
290209bc2fbSopenharmony_ci        "TID", watchdogTid, "TGID", gid, "UID", uid, "MODULE_NAME", timerName, "PROCESS_NAME", processName,
291209bc2fbSopenharmony_ci        "MSG", sendMsg, "STACK", stack + "\n"+ userStack);
292209bc2fbSopenharmony_ci    XCOLLIE_LOGI("hisysevent write result=%{public}d, send event [FRAMEWORK,%{public}s], "
293209bc2fbSopenharmony_ci        "msg=%{public}s", result, eventName.c_str(), keyMsg.c_str());
294209bc2fbSopenharmony_ci#else
295209bc2fbSopenharmony_ci       XCOLLIE_LOGI("hisysevent not exists");
296209bc2fbSopenharmony_ci#endif
297209bc2fbSopenharmony_ci}
298209bc2fbSopenharmony_ci
299209bc2fbSopenharmony_ciint WatchdogTask::EvaluateCheckerState()
300209bc2fbSopenharmony_ci{
301209bc2fbSopenharmony_ci    int waitState = checker->GetCheckState();
302209bc2fbSopenharmony_ci    if (waitState == CheckStatus::COMPLETED) {
303209bc2fbSopenharmony_ci        return waitState;
304209bc2fbSopenharmony_ci    } else if (waitState == CheckStatus::WAITED_HALF) {
305209bc2fbSopenharmony_ci        XCOLLIE_LOGI("Watchdog half-block happened, send event");
306209bc2fbSopenharmony_ci        std::string description = GetBlockDescription(checkInterval / 1000); // 1s = 1000ms
307209bc2fbSopenharmony_ci        if (timeOutCallback != nullptr) {
308209bc2fbSopenharmony_ci            timeOutCallback(name, waitState);
309209bc2fbSopenharmony_ci        } else {
310209bc2fbSopenharmony_ci            if (IsMemHookOn()) {
311209bc2fbSopenharmony_ci                return waitState;
312209bc2fbSopenharmony_ci            }
313209bc2fbSopenharmony_ci            if (name.compare(IPC_FULL) != 0) {
314209bc2fbSopenharmony_ci                SendEvent(description, "SERVICE_WARNING");
315209bc2fbSopenharmony_ci            }
316209bc2fbSopenharmony_ci        }
317209bc2fbSopenharmony_ci    } else {
318209bc2fbSopenharmony_ci        XCOLLIE_LOGI("Watchdog happened, send event twice.");
319209bc2fbSopenharmony_ci        std::string description = GetBlockDescription(checkInterval / 1000) +
320209bc2fbSopenharmony_ci            ", report twice instead of exiting process."; // 1s = 1000ms
321209bc2fbSopenharmony_ci        if (timeOutCallback != nullptr) {
322209bc2fbSopenharmony_ci            timeOutCallback(name, waitState);
323209bc2fbSopenharmony_ci        } else {
324209bc2fbSopenharmony_ci            if (IsMemHookOn()) {
325209bc2fbSopenharmony_ci                return waitState;
326209bc2fbSopenharmony_ci            }
327209bc2fbSopenharmony_ci            if (name.compare(IPC_FULL) == 0) {
328209bc2fbSopenharmony_ci                SendEvent(description, IPC_FULL);
329209bc2fbSopenharmony_ci            } else {
330209bc2fbSopenharmony_ci                SendEvent(description, "SERVICE_BLOCK");
331209bc2fbSopenharmony_ci            }
332209bc2fbSopenharmony_ci            // peer binder log is collected in hiview asynchronously
333209bc2fbSopenharmony_ci            // if blocked process exit early, binder blocked state will change
334209bc2fbSopenharmony_ci            // thus delay exit and let hiview have time to collect log.
335209bc2fbSopenharmony_ci            WatchdogInner::KillPeerBinderProcess(description);
336209bc2fbSopenharmony_ci        }
337209bc2fbSopenharmony_ci    }
338209bc2fbSopenharmony_ci    return waitState;
339209bc2fbSopenharmony_ci}
340209bc2fbSopenharmony_ci
341209bc2fbSopenharmony_cistd::string WatchdogTask::GetBlockDescription(uint64_t interval)
342209bc2fbSopenharmony_ci{
343209bc2fbSopenharmony_ci    std::string desc = "Watchdog: thread(";
344209bc2fbSopenharmony_ci    desc += name;
345209bc2fbSopenharmony_ci    desc += ") blocked " + std::to_string(interval) + "s";
346209bc2fbSopenharmony_ci    return desc;
347209bc2fbSopenharmony_ci}
348209bc2fbSopenharmony_ci
349209bc2fbSopenharmony_cibool WatchdogTask::IsMemHookOn()
350209bc2fbSopenharmony_ci{
351209bc2fbSopenharmony_ci    bool hookFlag = __get_global_hook_flag();
352209bc2fbSopenharmony_ci    if (hookFlag) {
353209bc2fbSopenharmony_ci        XCOLLIE_LOGI("memory hook is on, timeout task will skip");
354209bc2fbSopenharmony_ci    }
355209bc2fbSopenharmony_ci    return hookFlag;
356209bc2fbSopenharmony_ci}
357209bc2fbSopenharmony_ci} // end of namespace HiviewDFX
358209bc2fbSopenharmony_ci} // end of namespace OHOS
359