1020a203aSopenharmony_ci/* 2020a203aSopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd. 3020a203aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4020a203aSopenharmony_ci * you may not use this file except in compliance with the License. 5020a203aSopenharmony_ci * You may obtain a copy of the License at 6020a203aSopenharmony_ci * 7020a203aSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8020a203aSopenharmony_ci * 9020a203aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10020a203aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11020a203aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12020a203aSopenharmony_ci * See the License for the specific language governing permissions and 13020a203aSopenharmony_ci * limitations under the License. 14020a203aSopenharmony_ci */ 15020a203aSopenharmony_ci#include "peer_binder_catcher.h" 16020a203aSopenharmony_ci 17020a203aSopenharmony_ci#include <ctime> 18020a203aSopenharmony_ci#include <cstdio> 19020a203aSopenharmony_ci#include <cstdlib> 20020a203aSopenharmony_ci#include <list> 21020a203aSopenharmony_ci#include <securec.h> 22020a203aSopenharmony_ci#include <sys/wait.h> 23020a203aSopenharmony_ci 24020a203aSopenharmony_ci#include "common_utils.h" 25020a203aSopenharmony_ci#include "file_util.h" 26020a203aSopenharmony_ci#include "freeze_json_util.h" 27020a203aSopenharmony_ci#include "hiview_logger.h" 28020a203aSopenharmony_ci#include "log_catcher_utils.h" 29020a203aSopenharmony_ci#include "open_stacktrace_catcher.h" 30020a203aSopenharmony_ci#include "parameter_ex.h" 31020a203aSopenharmony_ci#include "perf_collector.h" 32020a203aSopenharmony_ci#include "string_util.h" 33020a203aSopenharmony_ci 34020a203aSopenharmony_cinamespace OHOS { 35020a203aSopenharmony_cinamespace HiviewDFX { 36020a203aSopenharmony_cinamespace { 37020a203aSopenharmony_ci static constexpr const char* const LOGGER_EVENT_PEERBINDER = "PeerBinder"; 38020a203aSopenharmony_ci enum { 39020a203aSopenharmony_ci LOGGER_BINDER_STACK_ONE = 0, 40020a203aSopenharmony_ci LOGGER_BINDER_STACK_ALL = 1, 41020a203aSopenharmony_ci }; 42020a203aSopenharmony_ci} 43020a203aSopenharmony_ciDEFINE_LOG_LABEL(0xD002D01, "EventLogger-PeerBinderCatcher"); 44020a203aSopenharmony_ci#ifdef HAS_HIPERF 45020a203aSopenharmony_ciusing namespace OHOS::HiviewDFX::UCollectUtil; 46020a203aSopenharmony_ciconstexpr char EVENT_LOG_PATH[] = "/data/log/eventlog"; 47020a203aSopenharmony_ci#endif 48020a203aSopenharmony_ciPeerBinderCatcher::PeerBinderCatcher() : EventLogCatcher() 49020a203aSopenharmony_ci{ 50020a203aSopenharmony_ci name_ = "PeerBinderCatcher"; 51020a203aSopenharmony_ci} 52020a203aSopenharmony_ci 53020a203aSopenharmony_cibool PeerBinderCatcher::Initialize(const std::string& perfCmd, int layer, int pid) 54020a203aSopenharmony_ci{ 55020a203aSopenharmony_ci pid_ = pid; 56020a203aSopenharmony_ci layer_ = layer; 57020a203aSopenharmony_ci perfCmd_ = perfCmd; 58020a203aSopenharmony_ci char buf[BUF_SIZE_512] = {0}; 59020a203aSopenharmony_ci int ret = snprintf_s(buf, BUF_SIZE_512, BUF_SIZE_512 - 1, 60020a203aSopenharmony_ci "PeerBinderCatcher -- pid==%d layer_ == %d\n", pid_, layer_); 61020a203aSopenharmony_ci if (ret > 0) { 62020a203aSopenharmony_ci description_ = buf; 63020a203aSopenharmony_ci } 64020a203aSopenharmony_ci return true; 65020a203aSopenharmony_ci} 66020a203aSopenharmony_ci 67020a203aSopenharmony_civoid PeerBinderCatcher::Init(std::shared_ptr<SysEvent> event, const std::string& filePath, std::set<int>& catchedPids) 68020a203aSopenharmony_ci{ 69020a203aSopenharmony_ci event_ = event; 70020a203aSopenharmony_ci catchedPids_ = catchedPids; 71020a203aSopenharmony_ci if ((filePath != "") && FileUtil::FileExists(filePath)) { 72020a203aSopenharmony_ci binderPath_ = filePath; 73020a203aSopenharmony_ci } 74020a203aSopenharmony_ci} 75020a203aSopenharmony_ci 76020a203aSopenharmony_ciint PeerBinderCatcher::Catch(int fd, int jsonFd) 77020a203aSopenharmony_ci{ 78020a203aSopenharmony_ci if (pid_ <= 0) { 79020a203aSopenharmony_ci return -1; 80020a203aSopenharmony_ci } 81020a203aSopenharmony_ci 82020a203aSopenharmony_ci auto originSize = GetFdSize(fd); 83020a203aSopenharmony_ci 84020a203aSopenharmony_ci if (!FileUtil::FileExists(binderPath_)) { 85020a203aSopenharmony_ci std::string content = binderPath_ + " : file isn't exists\r\n"; 86020a203aSopenharmony_ci FileUtil::SaveStringToFd(fd, content); 87020a203aSopenharmony_ci return -1; 88020a203aSopenharmony_ci } 89020a203aSopenharmony_ci 90020a203aSopenharmony_ci std::set<int> pids = GetBinderPeerPids(fd, jsonFd); 91020a203aSopenharmony_ci if (pids.empty()) { 92020a203aSopenharmony_ci std::string content = "PeerBinder pids is empty\r\n"; 93020a203aSopenharmony_ci FileUtil::SaveStringToFd(fd, content); 94020a203aSopenharmony_ci } 95020a203aSopenharmony_ci#ifdef HAS_HIPERF 96020a203aSopenharmony_ci ForkToDumpHiperf(pids); 97020a203aSopenharmony_ci#endif 98020a203aSopenharmony_ci std::string pidStr = ""; 99020a203aSopenharmony_ci for (auto pidTemp : pids) { 100020a203aSopenharmony_ci if (pidTemp == pid_ || IsAncoProc(pidTemp)) { 101020a203aSopenharmony_ci HIVIEW_LOGI("Stack of pid %{public}d is catched.", pidTemp); 102020a203aSopenharmony_ci continue; 103020a203aSopenharmony_ci } 104020a203aSopenharmony_ci 105020a203aSopenharmony_ci if (catchedPids_.count(pidTemp) == 0) { 106020a203aSopenharmony_ci CatcherStacktrace(fd, pidTemp); 107020a203aSopenharmony_ci pidStr += "," + std::to_string(pidTemp); 108020a203aSopenharmony_ci } 109020a203aSopenharmony_ci CatcherFfrtStack(fd, pidTemp); 110020a203aSopenharmony_ci } 111020a203aSopenharmony_ci 112020a203aSopenharmony_ci if (event_ != nullptr) { 113020a203aSopenharmony_ci event_->SetValue(LOGGER_EVENT_PEERBINDER, StringUtil::TrimStr(pidStr, ',')); 114020a203aSopenharmony_ci } 115020a203aSopenharmony_ci 116020a203aSopenharmony_ci logSize_ = GetFdSize(fd) - originSize; 117020a203aSopenharmony_ci return logSize_; 118020a203aSopenharmony_ci} 119020a203aSopenharmony_ci 120020a203aSopenharmony_civoid PeerBinderCatcher::AddBinderJsonInfo(std::list<OutputBinderInfo> outputBinderInfoList, int jsonFd) const 121020a203aSopenharmony_ci{ 122020a203aSopenharmony_ci if (jsonFd < 0) { 123020a203aSopenharmony_ci return; 124020a203aSopenharmony_ci } 125020a203aSopenharmony_ci std::map<int, std::string> processNameMap; 126020a203aSopenharmony_ci for (OutputBinderInfo outputBinderInfo : outputBinderInfoList) { 127020a203aSopenharmony_ci int pid = outputBinderInfo.pid; 128020a203aSopenharmony_ci if (processNameMap[pid] != "") { 129020a203aSopenharmony_ci continue; 130020a203aSopenharmony_ci } 131020a203aSopenharmony_ci std::string filePath = "/proc/" + std::to_string(pid) + "/cmdline"; 132020a203aSopenharmony_ci std::string realPath; 133020a203aSopenharmony_ci if (!FileUtil::PathToRealPath(filePath, realPath)) { 134020a203aSopenharmony_ci continue; 135020a203aSopenharmony_ci } 136020a203aSopenharmony_ci std::ifstream cmdLineFile(realPath); 137020a203aSopenharmony_ci std::string processName; 138020a203aSopenharmony_ci if (cmdLineFile) { 139020a203aSopenharmony_ci std::getline(cmdLineFile, processName); 140020a203aSopenharmony_ci cmdLineFile.close(); 141020a203aSopenharmony_ci processName = StringUtil::FormatCmdLine(processName); 142020a203aSopenharmony_ci processNameMap[pid] = processName; 143020a203aSopenharmony_ci } else { 144020a203aSopenharmony_ci HIVIEW_LOGE("Fail to open /proc/%{public}d/cmdline", pid); 145020a203aSopenharmony_ci } 146020a203aSopenharmony_ci } 147020a203aSopenharmony_ci std::list<std::string> infoList; 148020a203aSopenharmony_ci for (auto it = outputBinderInfoList.begin(); it != outputBinderInfoList.end(); it++) { 149020a203aSopenharmony_ci int pid = (*it).pid; 150020a203aSopenharmony_ci std::string info = (*it).info; 151020a203aSopenharmony_ci std::string lineStr = info + " " + std::to_string(pid) 152020a203aSopenharmony_ci + FreezeJsonUtil::WrapByParenthesis(processNameMap[pid]); 153020a203aSopenharmony_ci infoList.push_back(lineStr); 154020a203aSopenharmony_ci } 155020a203aSopenharmony_ci std::string binderInfoJsonStr = FreezeJsonUtil::GetStrByList(infoList); 156020a203aSopenharmony_ci HIVIEW_LOGI("Get FreezeJson PeerBinder jsonStr: %{public}s.", binderInfoJsonStr.c_str()); 157020a203aSopenharmony_ci FreezeJsonUtil::WriteKeyValue(jsonFd, "peer_binder", binderInfoJsonStr); 158020a203aSopenharmony_ci} 159020a203aSopenharmony_ci 160020a203aSopenharmony_cistd::map<int, std::list<PeerBinderCatcher::BinderInfo>> PeerBinderCatcher::BinderInfoParser( 161020a203aSopenharmony_ci std::ifstream& fin, int fd, int jsonFd) const 162020a203aSopenharmony_ci{ 163020a203aSopenharmony_ci std::map<int, std::list<BinderInfo>> manager; 164020a203aSopenharmony_ci FileUtil::SaveStringToFd(fd, "\nBinderCatcher --\n\n"); 165020a203aSopenharmony_ci std::list<OutputBinderInfo> outputBinderInfoList; 166020a203aSopenharmony_ci 167020a203aSopenharmony_ci BinderInfoParser(fin, fd, manager, outputBinderInfoList); 168020a203aSopenharmony_ci AddBinderJsonInfo(outputBinderInfoList, jsonFd); 169020a203aSopenharmony_ci 170020a203aSopenharmony_ci FileUtil::SaveStringToFd(fd, "\n\nPeerBinder Stacktrace --\n\n"); 171020a203aSopenharmony_ci HIVIEW_LOGI("manager size: %{public}zu", manager.size()); 172020a203aSopenharmony_ci return manager; 173020a203aSopenharmony_ci} 174020a203aSopenharmony_ci 175020a203aSopenharmony_civoid PeerBinderCatcher::GetFileToList(std::string line, 176020a203aSopenharmony_ci std::vector<std::string>& strList) const 177020a203aSopenharmony_ci{ 178020a203aSopenharmony_ci std::istringstream lineStream(line); 179020a203aSopenharmony_ci std::string tmpstr; 180020a203aSopenharmony_ci while (lineStream >> tmpstr) { 181020a203aSopenharmony_ci strList.push_back(tmpstr); 182020a203aSopenharmony_ci } 183020a203aSopenharmony_ci HIVIEW_LOGD("strList size: %{public}zu", strList.size()); 184020a203aSopenharmony_ci} 185020a203aSopenharmony_ci 186020a203aSopenharmony_civoid PeerBinderCatcher::BinderInfoParser(std::ifstream& fin, int fd, 187020a203aSopenharmony_ci std::map<int, std::list<PeerBinderCatcher::BinderInfo>>& manager, 188020a203aSopenharmony_ci std::list<PeerBinderCatcher::OutputBinderInfo>& outputBinderInfoList) const 189020a203aSopenharmony_ci{ 190020a203aSopenharmony_ci const int DECIMAL = 10; 191020a203aSopenharmony_ci std::string line; 192020a203aSopenharmony_ci bool findBinderHeader = false; 193020a203aSopenharmony_ci while (getline(fin, line)) { 194020a203aSopenharmony_ci FileUtil::SaveStringToFd(fd, line + "\n"); 195020a203aSopenharmony_ci if (findBinderHeader) { 196020a203aSopenharmony_ci continue; 197020a203aSopenharmony_ci } 198020a203aSopenharmony_ci 199020a203aSopenharmony_ci if (line.find("async\t") != std::string::npos) { 200020a203aSopenharmony_ci continue; 201020a203aSopenharmony_ci } 202020a203aSopenharmony_ci 203020a203aSopenharmony_ci std::vector<std::string> strList; 204020a203aSopenharmony_ci GetFileToList(line, strList); 205020a203aSopenharmony_ci auto stringSplit = [](const std::string& str, uint16_t index) -> std::string { 206020a203aSopenharmony_ci std::vector<std::string> strings; 207020a203aSopenharmony_ci StringUtil::SplitStr(str, ":", strings); 208020a203aSopenharmony_ci if (index < strings.size()) { 209020a203aSopenharmony_ci return strings[index]; 210020a203aSopenharmony_ci } 211020a203aSopenharmony_ci return ""; 212020a203aSopenharmony_ci }; 213020a203aSopenharmony_ci 214020a203aSopenharmony_ci if (strList.size() >= 7) { // 7: valid array size 215020a203aSopenharmony_ci BinderInfo info = {0}; 216020a203aSopenharmony_ci OutputBinderInfo outputInfo; 217020a203aSopenharmony_ci // 2: binder peer id, 218020a203aSopenharmony_ci std::string server = stringSplit(strList[2], 0); 219020a203aSopenharmony_ci // 0: binder local id, 220020a203aSopenharmony_ci std::string client = stringSplit(strList[0], 0); 221020a203aSopenharmony_ci // 5: binder wait time, s 222020a203aSopenharmony_ci std::string wait = stringSplit(strList[5], 1); 223020a203aSopenharmony_ci if (server == "" || client == "" || wait == "") { 224020a203aSopenharmony_ci HIVIEW_LOGI("server:%{public}s, client:%{public}s, wait:%{public}s", 225020a203aSopenharmony_ci server.c_str(), client.c_str(), wait.c_str()); 226020a203aSopenharmony_ci continue; 227020a203aSopenharmony_ci } 228020a203aSopenharmony_ci info.server = std::strtol(server.c_str(), nullptr, DECIMAL); 229020a203aSopenharmony_ci info.client = std::strtol(client.c_str(), nullptr, DECIMAL); 230020a203aSopenharmony_ci info.wait = std::strtol(wait.c_str(), nullptr, DECIMAL); 231020a203aSopenharmony_ci HIVIEW_LOGD("server:%{public}d, client:%{public}d, wait:%{public}d", info.server, info.client, info.wait); 232020a203aSopenharmony_ci manager[info.client].push_back(info); 233020a203aSopenharmony_ci outputInfo.info = StringUtil::TrimStr(line); 234020a203aSopenharmony_ci outputInfo.pid = info.server; 235020a203aSopenharmony_ci outputBinderInfoList.push_back(outputInfo); 236020a203aSopenharmony_ci } else { 237020a203aSopenharmony_ci HIVIEW_LOGI("strList size: %{public}zu, line: %{public}s", strList.size(), line.c_str()); 238020a203aSopenharmony_ci } 239020a203aSopenharmony_ci if (line.find("context") != line.npos) { 240020a203aSopenharmony_ci findBinderHeader = true; 241020a203aSopenharmony_ci } 242020a203aSopenharmony_ci } 243020a203aSopenharmony_ci} 244020a203aSopenharmony_ci 245020a203aSopenharmony_cistd::set<int> PeerBinderCatcher::GetBinderPeerPids(int fd, int jsonFd) const 246020a203aSopenharmony_ci{ 247020a203aSopenharmony_ci std::set<int> pids; 248020a203aSopenharmony_ci std::ifstream fin; 249020a203aSopenharmony_ci std::string path = binderPath_; 250020a203aSopenharmony_ci fin.open(path.c_str()); 251020a203aSopenharmony_ci if (!fin.is_open()) { 252020a203aSopenharmony_ci HIVIEW_LOGE("open binder file failed, %{public}s.", path.c_str()); 253020a203aSopenharmony_ci std::string content = "open binder file failed :" + path + "\r\n"; 254020a203aSopenharmony_ci FileUtil::SaveStringToFd(fd, content); 255020a203aSopenharmony_ci return pids; 256020a203aSopenharmony_ci } 257020a203aSopenharmony_ci 258020a203aSopenharmony_ci std::map<int, std::list<PeerBinderCatcher::BinderInfo>> manager = BinderInfoParser(fin, fd, jsonFd); 259020a203aSopenharmony_ci fin.close(); 260020a203aSopenharmony_ci 261020a203aSopenharmony_ci if (manager.size() == 0 || manager.find(pid_) == manager.end()) { 262020a203aSopenharmony_ci return pids; 263020a203aSopenharmony_ci } 264020a203aSopenharmony_ci 265020a203aSopenharmony_ci if (layer_ == LOGGER_BINDER_STACK_ONE) { 266020a203aSopenharmony_ci for (auto each : manager[pid_]) { 267020a203aSopenharmony_ci pids.insert(each.server); 268020a203aSopenharmony_ci } 269020a203aSopenharmony_ci } else if (layer_ == LOGGER_BINDER_STACK_ALL) { 270020a203aSopenharmony_ci ParseBinderCallChain(manager, pids, pid_); 271020a203aSopenharmony_ci } 272020a203aSopenharmony_ci return pids; 273020a203aSopenharmony_ci} 274020a203aSopenharmony_ci 275020a203aSopenharmony_civoid PeerBinderCatcher::ParseBinderCallChain(std::map<int, std::list<PeerBinderCatcher::BinderInfo>>& manager, 276020a203aSopenharmony_ci std::set<int>& pids, int pid) const 277020a203aSopenharmony_ci{ 278020a203aSopenharmony_ci for (auto& each : manager[pid]) { 279020a203aSopenharmony_ci if (pids.find(each.server) != pids.end()) { 280020a203aSopenharmony_ci continue; 281020a203aSopenharmony_ci } 282020a203aSopenharmony_ci pids.insert(each.server); 283020a203aSopenharmony_ci ParseBinderCallChain(manager, pids, each.server); 284020a203aSopenharmony_ci } 285020a203aSopenharmony_ci} 286020a203aSopenharmony_ci 287020a203aSopenharmony_cibool PeerBinderCatcher::IsAncoProc(int pid) const 288020a203aSopenharmony_ci{ 289020a203aSopenharmony_ci std::string cgroupPath = "/proc/" + std::to_string(pid) + "/cgroup"; 290020a203aSopenharmony_ci std::string firstLine = FileUtil::GetFirstLine(cgroupPath); 291020a203aSopenharmony_ci return firstLine.find("isulad") != std::string::npos; 292020a203aSopenharmony_ci} 293020a203aSopenharmony_ci 294020a203aSopenharmony_civoid PeerBinderCatcher::CatcherFfrtStack(int fd, int pid) const 295020a203aSopenharmony_ci{ 296020a203aSopenharmony_ci std::string content = "PeerBinderCatcher start catcher ffrt stack for pid : " + std::to_string(pid) + "\r\n"; 297020a203aSopenharmony_ci FileUtil::SaveStringToFd(fd, content); 298020a203aSopenharmony_ci 299020a203aSopenharmony_ci LogCatcherUtils::DumpStackFfrt(fd, std::to_string(pid)); 300020a203aSopenharmony_ci} 301020a203aSopenharmony_ci 302020a203aSopenharmony_civoid PeerBinderCatcher::CatcherStacktrace(int fd, int pid) const 303020a203aSopenharmony_ci{ 304020a203aSopenharmony_ci std::string content = "PeerBinderCatcher start catcher stacktrace for pid : " + std::to_string(pid) + "\r\n"; 305020a203aSopenharmony_ci FileUtil::SaveStringToFd(fd, content); 306020a203aSopenharmony_ci 307020a203aSopenharmony_ci LogCatcherUtils::DumpStacktrace(fd, pid); 308020a203aSopenharmony_ci} 309020a203aSopenharmony_ci 310020a203aSopenharmony_ci#ifdef HAS_HIPERF 311020a203aSopenharmony_civoid PeerBinderCatcher::DoExecHiperf(const std::string& fileName, const std::set<int>& pids) 312020a203aSopenharmony_ci{ 313020a203aSopenharmony_ci std::shared_ptr<PerfCollector> perfCollector = PerfCollector::Create(); 314020a203aSopenharmony_ci perfCollector->SetOutputFilename(fileName); 315020a203aSopenharmony_ci constexpr int collectTime = 1; 316020a203aSopenharmony_ci perfCollector->SetTimeStopSec(collectTime); 317020a203aSopenharmony_ci if (perfCmd_.find("a") == std::string::npos) { 318020a203aSopenharmony_ci std::vector<pid_t> selectPids; 319020a203aSopenharmony_ci selectPids.push_back(pid_); 320020a203aSopenharmony_ci for (const auto& pid : pids) { 321020a203aSopenharmony_ci if (pid > 0) { 322020a203aSopenharmony_ci selectPids.push_back(pid); 323020a203aSopenharmony_ci } 324020a203aSopenharmony_ci } 325020a203aSopenharmony_ci perfCollector->SetSelectPids(selectPids); 326020a203aSopenharmony_ci perfCollector->SetReport(true); 327020a203aSopenharmony_ci } else { 328020a203aSopenharmony_ci perfCollector->SetTargetSystemWide(true); 329020a203aSopenharmony_ci } 330020a203aSopenharmony_ci perfCollector->SetFrequency(1000); // 1000 : 1kHz 331020a203aSopenharmony_ci CollectResult<bool> ret = perfCollector->StartPerf(EVENT_LOG_PATH); 332020a203aSopenharmony_ci if (ret.retCode == UCollect::UcError::SUCCESS) { 333020a203aSopenharmony_ci HIVIEW_LOGI("Success to call perf result : %{public}d", ret.data); 334020a203aSopenharmony_ci } else { 335020a203aSopenharmony_ci HIVIEW_LOGI("Failed to call perf result : %{public}d", ret.data); 336020a203aSopenharmony_ci } 337020a203aSopenharmony_ci} 338020a203aSopenharmony_ci 339020a203aSopenharmony_civoid PeerBinderCatcher::ForkToDumpHiperf(const std::set<int>& pids) 340020a203aSopenharmony_ci{ 341020a203aSopenharmony_ci#if defined(__aarch64__) 342020a203aSopenharmony_ci if (perfCmd_.empty()) { 343020a203aSopenharmony_ci HIVIEW_LOGI("BinderPeer perf is not configured."); 344020a203aSopenharmony_ci return; 345020a203aSopenharmony_ci } 346020a203aSopenharmony_ci 347020a203aSopenharmony_ci if (!Parameter::IsBetaVersion()) { 348020a203aSopenharmony_ci HIVIEW_LOGI("BinderPeer perf is only enabled in beta version."); 349020a203aSopenharmony_ci return; 350020a203aSopenharmony_ci } 351020a203aSopenharmony_ci 352020a203aSopenharmony_ci static std::mutex lock; 353020a203aSopenharmony_ci std::unique_lock<std::mutex> mlock(lock); 354020a203aSopenharmony_ci std::string fileName = "hiperf-" + std::to_string(pid_) + ".data"; 355020a203aSopenharmony_ci std::string fullPath = std::string(EVENT_LOG_PATH) + "/" + fileName; 356020a203aSopenharmony_ci constexpr int perfLogExPireTime = 60; 357020a203aSopenharmony_ci if (access(fullPath.c_str(), F_OK) == 0) { 358020a203aSopenharmony_ci struct stat statBuf; 359020a203aSopenharmony_ci auto now = time(nullptr); 360020a203aSopenharmony_ci if (stat(fullPath.c_str(), &statBuf) == -1) { 361020a203aSopenharmony_ci HIVIEW_LOGI("Failed to stat file, error:%{public}d.", errno); 362020a203aSopenharmony_ci FileUtil::RemoveFile(fullPath); 363020a203aSopenharmony_ci } else if (now - statBuf.st_mtime < perfLogExPireTime) { 364020a203aSopenharmony_ci HIVIEW_LOGI("Target log has exist, reuse it."); 365020a203aSopenharmony_ci return; 366020a203aSopenharmony_ci } else { 367020a203aSopenharmony_ci FileUtil::RemoveFile(fullPath); 368020a203aSopenharmony_ci } 369020a203aSopenharmony_ci } 370020a203aSopenharmony_ci 371020a203aSopenharmony_ci pid_t child = fork(); 372020a203aSopenharmony_ci if (child < 0) { 373020a203aSopenharmony_ci // failed to fork child 374020a203aSopenharmony_ci return; 375020a203aSopenharmony_ci } else if (child == 0) { 376020a203aSopenharmony_ci pid_t grandChild = fork(); 377020a203aSopenharmony_ci if (grandChild == 0) { 378020a203aSopenharmony_ci DoExecHiperf(fileName, pids); 379020a203aSopenharmony_ci } 380020a203aSopenharmony_ci _exit(0); 381020a203aSopenharmony_ci } else { 382020a203aSopenharmony_ci // do not left a zombie 383020a203aSopenharmony_ci waitpid(child, nullptr, 0); 384020a203aSopenharmony_ci } 385020a203aSopenharmony_ci#endif 386020a203aSopenharmony_ci} 387020a203aSopenharmony_ci#endif 388020a203aSopenharmony_ci} // namespace HiviewDFX 389020a203aSopenharmony_ci} // namespace OHOS