1/* 2 * Copyright (c) 2024 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_task.h" 17 18#include <fstream> 19#include <unistd.h> 20 21#include "backtrace_local.h" 22#include "hisysevent.h" 23#include "mmi_log.h" 24#include "parameter.h" 25 26#undef MMI_LOG_DOMAIN 27#define MMI_LOG_DOMAIN MMI_LOG_SERVER 28#undef MMI_LOG_TAG 29#define MMI_LOG_TAG "WatchdogTask" 30 31namespace OHOS { 32namespace MMI { 33namespace { 34const std::string THREAD_NAME { "mmi_service" }; 35} // namespace 36 37WatchdogTask::WatchdogTask() {} 38 39WatchdogTask::~WatchdogTask() {} 40 41std::string WatchdogTask::GetFirstLine(const std::string& path) 42{ 43 char checkPath[PATH_MAX] = { 0 }; 44 if (realpath(path.c_str(), checkPath) == nullptr) { 45 MMI_HILOGE("Canonicalize failed. path:%{private}s", path.c_str()); 46 return ""; 47 } 48 std::ifstream inFile(checkPath); 49 if (!inFile.is_open()) { 50 MMI_HILOGE("inFile.is_open() false"); 51 return ""; 52 } 53 std::string firstLine; 54 getline(inFile, firstLine); 55 inFile.close(); 56 return firstLine; 57} 58 59std::string WatchdogTask::GetProcessNameFromProcCmdline(int32_t pid) 60{ 61 std::string procCmdlinePath = "/proc/" + std::to_string(pid) + "/cmdline"; 62 std::string procCmdlineContent = GetFirstLine(procCmdlinePath); 63 if (procCmdlineContent.empty()) { 64 return ""; 65 } 66 auto pos = procCmdlineContent.find('\0'); 67 if (pos != std::string::npos) { 68 procCmdlineContent = procCmdlineContent.substr(0, pos); 69 } 70 pos = procCmdlineContent.rfind('/'); 71 if (pos != std::string::npos) { 72 return procCmdlineContent.substr(pos + 1); 73 } 74 return procCmdlineContent; 75} 76 77bool WatchdogTask::IsNumberic(const std::string &str) 78{ 79 return !str.empty() && std::all_of(str.begin(), str.end(), ::isdigit); 80} 81 82bool WatchdogTask::IsProcessDebug(int32_t pid) 83{ 84 const int32_t buffSize = 128; 85 char param[buffSize] = { 0 }; 86 std::string filter = "hiviewdfx.freeze.filter." + GetProcessNameFromProcCmdline(pid); 87 GetParameter(filter.c_str(), "", param, buffSize - 1); 88 if (!IsNumberic(param)) { 89 MMI_HILOGE("Parameter:%{public}s is error", param); 90 return false; 91 } 92 int32_t debugPid = atoi(param); 93 if (debugPid == pid) { 94 return true; 95 } 96 return false; 97} 98 99std::string WatchdogTask::GetBlockDescription(uint64_t interval) 100{ 101 std::string desc = "Watchdog: thread("; 102 desc += THREAD_NAME; 103 desc += ") blocked " + std::to_string(interval) + "s"; 104 return desc; 105} 106 107std::string WatchdogTask::GetSelfProcName() 108{ 109 constexpr uint16_t READ_SIZE = 128; 110 std::ifstream fin; 111 fin.open("/proc/self/comm", std::ifstream::in); 112 if (!fin.is_open()) { 113 MMI_HILOGE("fin.is_open() false"); 114 return ""; 115 } 116 char readStr[READ_SIZE] = {'\0'}; 117 fin.getline(readStr, READ_SIZE - 1); 118 fin.close(); 119 120 std::string ret = std::string(readStr); 121 auto comparisonFun = [](unsigned char c) { 122 if (c >= '0' && c <= '9') { 123 return false; 124 } 125 if (c >= 'a' && c <= 'z') { 126 return false; 127 } 128 if (c >= 'A' && c <= 'Z') { 129 return false; 130 } 131 if (c == '.' || c == '-' || c == '_') { 132 return false; 133 } 134 return true; 135 }; 136 ret.erase(std::remove_if(ret.begin(), ret.end(), comparisonFun), ret.end()); 137 return ret; 138} 139 140void WatchdogTask::SendEvent(const std::string &msg, const std::string &eventName) 141{ 142 int32_t pid = getpid(); 143 if (IsProcessDebug(pid)) { 144 MMI_HILOGI("Heap dump for %{public}d, don't report", pid); 145 return; 146 } 147 uint32_t gid = getgid(); 148 uint32_t uid = getuid(); 149 time_t curTime = time(nullptr); 150 std::string sendMsg = std::string((ctime(&curTime) == nullptr) ? "" : ctime(&curTime)) + 151 "\n" + msg + "\n"; 152 HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::FRAMEWORK, eventName, 153 OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, 154 "PID", pid, 155 "TGID", gid, 156 "UID", uid, 157 "MODULE_NAME", THREAD_NAME, 158 "PROCESS_NAME", GetSelfProcName(), 159 "MSG", sendMsg, 160 "STACK", OHOS::HiviewDFX::GetProcessStacktrace()); 161 MMI_HILOGI("Send event, eventName:%{public}s, msg:%{public}s", eventName.c_str(), msg.c_str()); 162} 163} // namespace MMI 164} // namespace OHOS 165