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