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