106f6ba60Sopenharmony_ci/*
206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License.
506f6ba60Sopenharmony_ci * You may obtain a copy of the License at
606f6ba60Sopenharmony_ci *
706f6ba60Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
806f6ba60Sopenharmony_ci *
906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and
1306f6ba60Sopenharmony_ci * limitations under the License.
1406f6ba60Sopenharmony_ci */
1506f6ba60Sopenharmony_ci
1606f6ba60Sopenharmony_ci#include <arpa/inet.h>
1706f6ba60Sopenharmony_ci#include <cinttypes>
1806f6ba60Sopenharmony_ci#include <condition_variable>
1906f6ba60Sopenharmony_ci#include <csignal>
2006f6ba60Sopenharmony_ci#include <cstdio>
2106f6ba60Sopenharmony_ci#include <cstring>
2206f6ba60Sopenharmony_ci#include <fstream>
2306f6ba60Sopenharmony_ci#include <getopt.h>
2406f6ba60Sopenharmony_ci#include <grpcpp/grpcpp.h>
2506f6ba60Sopenharmony_ci#include <ifaddrs.h>
2606f6ba60Sopenharmony_ci#include <netinet/in.h>
2706f6ba60Sopenharmony_ci#include <ostream>
2806f6ba60Sopenharmony_ci#include <sys/types.h>
2906f6ba60Sopenharmony_ci#include <thread>
3006f6ba60Sopenharmony_ci#include <unistd.h>
3106f6ba60Sopenharmony_ci#include <vector>
3206f6ba60Sopenharmony_ci#include <future>
3306f6ba60Sopenharmony_ci
3406f6ba60Sopenharmony_ci#include "common.h"
3506f6ba60Sopenharmony_ci#include "command_line.h"
3606f6ba60Sopenharmony_ci#include "google/protobuf/text_format.h"
3706f6ba60Sopenharmony_ci#include "parameters.h"
3806f6ba60Sopenharmony_ci#include "parse_plugin_config.h"
3906f6ba60Sopenharmony_ci#include "profiler_service.grpc.pb.h"
4006f6ba60Sopenharmony_ci#include "trace_plugin_config.pb.h"
4106f6ba60Sopenharmony_ci
4206f6ba60Sopenharmony_ciusing google::protobuf::TextFormat;
4306f6ba60Sopenharmony_ci
4406f6ba60Sopenharmony_cinamespace {
4506f6ba60Sopenharmony_ciconstexpr int ADDR_BUFFER_SIZE = 128;
4606f6ba60Sopenharmony_ciconstexpr int MS_PER_S = 1000;
4706f6ba60Sopenharmony_ciconstexpr int KEEP_SESSION_TIMEOUT_MS = 5 * 1000;
4806f6ba60Sopenharmony_ciconstexpr int KEEP_SESSION_SLEEP_SECOND = 3;
4906f6ba60Sopenharmony_ciconstexpr int DEFAULT_SESSION_TIME_S = 10;
5006f6ba60Sopenharmony_ciconstexpr uint32_t INT_MAX_LEN = 10;
5106f6ba60Sopenharmony_ciconst std::string DEFAULT_OUTPUT_FILE = "/data/local/tmp/hiprofiler_data.htrace";
5206f6ba60Sopenharmony_ciconst std::string HIPROFILERD_NAME("hiprofilerd");
5306f6ba60Sopenharmony_ciconst std::string HIPROFILER_PLUGINS_NAME("hiprofiler_plugins");
5406f6ba60Sopenharmony_ciconst std::string NATIVE_DAEMON_NAME("native_daemon");
5506f6ba60Sopenharmony_ci
5606f6ba60Sopenharmony_ciuint32_t g_sampleDuration = 0;
5706f6ba60Sopenharmony_ciint g_hiprofilerdPid = -1;
5806f6ba60Sopenharmony_ciint g_hiprofilerPluginsPid = -1;
5906f6ba60Sopenharmony_ciint g_nativeDaemonPid = -1;
6006f6ba60Sopenharmony_cistd::condition_variable g_sessionCv;
6106f6ba60Sopenharmony_cistd::condition_variable g_keepSessionCv;
6206f6ba60Sopenharmony_cibool g_exitProcessFlag = false;
6306f6ba60Sopenharmony_ci
6406f6ba60Sopenharmony_cistd::mutex g_keepSessionMutex;
6506f6ba60Sopenharmony_cistd::mutex g_sessionMutex;
6606f6ba60Sopenharmony_ci
6706f6ba60Sopenharmony_cistd::string GetLoopbackAddress()
6806f6ba60Sopenharmony_ci{
6906f6ba60Sopenharmony_ci    char addressBuffer[ADDR_BUFFER_SIZE] = "";
7006f6ba60Sopenharmony_ci    struct ifaddrs* ifAddrStruct = nullptr;
7106f6ba60Sopenharmony_ci    void* tmpAddrPtr = nullptr;
7206f6ba60Sopenharmony_ci
7306f6ba60Sopenharmony_ci    getifaddrs(&ifAddrStruct);
7406f6ba60Sopenharmony_ci    while (ifAddrStruct != nullptr) {
7506f6ba60Sopenharmony_ci        if (ifAddrStruct->ifa_addr == nullptr) {
7606f6ba60Sopenharmony_ci            ifAddrStruct = ifAddrStruct->ifa_next;
7706f6ba60Sopenharmony_ci            continue;
7806f6ba60Sopenharmony_ci        }
7906f6ba60Sopenharmony_ci        if (ifAddrStruct->ifa_addr->sa_family == AF_INET) {
8006f6ba60Sopenharmony_ci            // is a valid IP4 Address
8106f6ba60Sopenharmony_ci            tmpAddrPtr = &((reinterpret_cast<struct sockaddr_in*>(ifAddrStruct->ifa_addr))->sin_addr);
8206f6ba60Sopenharmony_ci            inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
8306f6ba60Sopenharmony_ci            if (strcmp(addressBuffer, "127.0.0.1") == 0) {
8406f6ba60Sopenharmony_ci                break;
8506f6ba60Sopenharmony_ci            }
8606f6ba60Sopenharmony_ci        } else if (ifAddrStruct->ifa_addr->sa_family == AF_INET6) { // check it is IP6
8706f6ba60Sopenharmony_ci            // is a valid IP6 Address
8806f6ba60Sopenharmony_ci            tmpAddrPtr = &((reinterpret_cast<struct sockaddr_in*>(ifAddrStruct->ifa_addr))->sin_addr);
8906f6ba60Sopenharmony_ci            inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
9006f6ba60Sopenharmony_ci        }
9106f6ba60Sopenharmony_ci        ifAddrStruct = ifAddrStruct->ifa_next;
9206f6ba60Sopenharmony_ci    }
9306f6ba60Sopenharmony_ci
9406f6ba60Sopenharmony_ci    freeifaddrs(ifAddrStruct);
9506f6ba60Sopenharmony_ci    return addressBuffer;
9606f6ba60Sopenharmony_ci}
9706f6ba60Sopenharmony_ci
9806f6ba60Sopenharmony_ciuint16_t GetServicePort()
9906f6ba60Sopenharmony_ci{
10006f6ba60Sopenharmony_ci    return COMMON::GetServicePort();
10106f6ba60Sopenharmony_ci}
10206f6ba60Sopenharmony_ci
10306f6ba60Sopenharmony_cistd::unique_ptr<CreateSessionRequest> MakeCreateRequest(const std::string& config,
10406f6ba60Sopenharmony_ci                                                        const std::string& keepSecond,
10506f6ba60Sopenharmony_ci                                                        const std::string& outputFile)
10606f6ba60Sopenharmony_ci{
10706f6ba60Sopenharmony_ci    auto request = std::make_unique<CreateSessionRequest>();
10806f6ba60Sopenharmony_ci    std::string content = config;
10906f6ba60Sopenharmony_ci    if (content.empty()) {
11006f6ba60Sopenharmony_ci        printf("config file empty!");
11106f6ba60Sopenharmony_ci        return nullptr;
11206f6ba60Sopenharmony_ci    }
11306f6ba60Sopenharmony_ci
11406f6ba60Sopenharmony_ci    if (!ParsePluginConfig::GetInstance().GetParser().ParseFromString(content, request.get())) {
11506f6ba60Sopenharmony_ci        printf("config [%s] parse FAILED!\n", content.c_str());
11606f6ba60Sopenharmony_ci        return nullptr;
11706f6ba60Sopenharmony_ci    }
11806f6ba60Sopenharmony_ci
11906f6ba60Sopenharmony_ci    auto sessionConfig = request->mutable_session_config();
12006f6ba60Sopenharmony_ci    if (!sessionConfig) {
12106f6ba60Sopenharmony_ci        return nullptr;
12206f6ba60Sopenharmony_ci    }
12306f6ba60Sopenharmony_ci
12406f6ba60Sopenharmony_ci    request->set_request_id(1);
12506f6ba60Sopenharmony_ci    if (!keepSecond.empty() && keepSecond.size() < INT_MAX_LEN) {
12606f6ba60Sopenharmony_ci        int ks = COMMON::IsNumeric(keepSecond) ? std::stoi(keepSecond) : 0;
12706f6ba60Sopenharmony_ci        if (ks > 0) {
12806f6ba60Sopenharmony_ci            sessionConfig->set_sample_duration(ks * MS_PER_S);
12906f6ba60Sopenharmony_ci        }
13006f6ba60Sopenharmony_ci    } else if (sessionConfig->sample_duration() <= 0) {
13106f6ba60Sopenharmony_ci        sessionConfig->set_sample_duration(DEFAULT_SESSION_TIME_S * MS_PER_S);
13206f6ba60Sopenharmony_ci    }
13306f6ba60Sopenharmony_ci    if (!outputFile.empty()) {
13406f6ba60Sopenharmony_ci        sessionConfig->set_result_file(outputFile);
13506f6ba60Sopenharmony_ci    } else if (sessionConfig->result_file() == "") {
13606f6ba60Sopenharmony_ci        sessionConfig->set_result_file(DEFAULT_OUTPUT_FILE);
13706f6ba60Sopenharmony_ci    }
13806f6ba60Sopenharmony_ci    printf("keepSecond: %us, outputFileName: %s\n", sessionConfig->sample_duration() / MS_PER_S,
13906f6ba60Sopenharmony_ci        sessionConfig->result_file().c_str());
14006f6ba60Sopenharmony_ci
14106f6ba60Sopenharmony_ci    g_sampleDuration = sessionConfig->sample_duration();
14206f6ba60Sopenharmony_ci    for (int i = 0; i < request->plugin_configs().size(); i++) {
14306f6ba60Sopenharmony_ci        auto pluginConfig = request->mutable_plugin_configs(i);
14406f6ba60Sopenharmony_ci        if (!ParsePluginConfig::GetInstance().SetSerializePluginsConfig(pluginConfig->name(), *pluginConfig)) {
14506f6ba60Sopenharmony_ci            printf("set %s plugin config failed\n", pluginConfig->name().c_str());
14606f6ba60Sopenharmony_ci            return nullptr;
14706f6ba60Sopenharmony_ci        }
14806f6ba60Sopenharmony_ci    }
14906f6ba60Sopenharmony_ci
15006f6ba60Sopenharmony_ci    content.clear();
15106f6ba60Sopenharmony_ci    if (!TextFormat::PrintToString(*request.get(), &content)) {
15206f6ba60Sopenharmony_ci        printf("config message format FAILED!\n");
15306f6ba60Sopenharmony_ci        return nullptr;
15406f6ba60Sopenharmony_ci    }
15506f6ba60Sopenharmony_ci
15606f6ba60Sopenharmony_ci    return request;
15706f6ba60Sopenharmony_ci}
15806f6ba60Sopenharmony_ci
15906f6ba60Sopenharmony_cistd::unique_ptr<IProfilerService::Stub> GetProfilerServiceStub()
16006f6ba60Sopenharmony_ci{
16106f6ba60Sopenharmony_ci    std::string serviceUri = GetLoopbackAddress() + ":" + std::to_string(GetServicePort());
16206f6ba60Sopenharmony_ci    auto grpcChannel = grpc::CreateChannel(serviceUri, grpc::InsecureChannelCredentials());
16306f6ba60Sopenharmony_ci    if (grpcChannel == nullptr) {
16406f6ba60Sopenharmony_ci        printf("Create gRPC channel failed!\n");
16506f6ba60Sopenharmony_ci        return nullptr;
16606f6ba60Sopenharmony_ci    }
16706f6ba60Sopenharmony_ci    return IProfilerService::NewStub(grpcChannel);
16806f6ba60Sopenharmony_ci}
16906f6ba60Sopenharmony_ci
17006f6ba60Sopenharmony_cibool GetCapabilities(std::string& content, bool isCheck)
17106f6ba60Sopenharmony_ci{
17206f6ba60Sopenharmony_ci    auto profilerStub = GetProfilerServiceStub();
17306f6ba60Sopenharmony_ci    if (profilerStub == nullptr) {
17406f6ba60Sopenharmony_ci        printf("Get profiler service stub failed!\n");
17506f6ba60Sopenharmony_ci        return false;
17606f6ba60Sopenharmony_ci    }
17706f6ba60Sopenharmony_ci
17806f6ba60Sopenharmony_ci    GetCapabilitiesRequest capRequest;
17906f6ba60Sopenharmony_ci    GetCapabilitiesResponse capResponse;
18006f6ba60Sopenharmony_ci    capRequest.set_request_id(0);
18106f6ba60Sopenharmony_ci    grpc::ClientContext capContext;
18206f6ba60Sopenharmony_ci    grpc::Status status = profilerStub->GetCapabilities(&capContext, capRequest, &capResponse);
18306f6ba60Sopenharmony_ci    if (!status.ok()) {
18406f6ba60Sopenharmony_ci        printf("Service not started\n");
18506f6ba60Sopenharmony_ci        return false;
18606f6ba60Sopenharmony_ci    }
18706f6ba60Sopenharmony_ci
18806f6ba60Sopenharmony_ci    if (!TextFormat::PrintToString(capResponse, &content)) {
18906f6ba60Sopenharmony_ci        printf("capabilities message format FAILED!\n");
19006f6ba60Sopenharmony_ci        return false;
19106f6ba60Sopenharmony_ci    }
19206f6ba60Sopenharmony_ci
19306f6ba60Sopenharmony_ci    if (!isCheck) {
19406f6ba60Sopenharmony_ci        printf("support plugin list:\n%s\n", content.c_str());
19506f6ba60Sopenharmony_ci    }
19606f6ba60Sopenharmony_ci    return true;
19706f6ba60Sopenharmony_ci}
19806f6ba60Sopenharmony_ci
19906f6ba60Sopenharmony_ciuint32_t CreateSession(std::unique_ptr<IProfilerService::Stub>& profilerStub, const std::string& config,
20006f6ba60Sopenharmony_ci    const std::string& keepSecond, const std::string& outputFile)
20106f6ba60Sopenharmony_ci{
20206f6ba60Sopenharmony_ci    auto request = MakeCreateRequest(config, keepSecond, outputFile);
20306f6ba60Sopenharmony_ci    if (!request) {
20406f6ba60Sopenharmony_ci        printf("MakeCreateRequest failed!\n");
20506f6ba60Sopenharmony_ci        return 0;
20606f6ba60Sopenharmony_ci    }
20706f6ba60Sopenharmony_ci
20806f6ba60Sopenharmony_ci    CreateSessionResponse createResponse;
20906f6ba60Sopenharmony_ci    grpc::ClientContext createSessionContext;
21006f6ba60Sopenharmony_ci    grpc::Status status = profilerStub->CreateSession(&createSessionContext, *request, &createResponse);
21106f6ba60Sopenharmony_ci    if (!status.ok()) {
21206f6ba60Sopenharmony_ci        printf("CreateSession FAIL\n");
21306f6ba60Sopenharmony_ci        return 0;
21406f6ba60Sopenharmony_ci    }
21506f6ba60Sopenharmony_ci
21606f6ba60Sopenharmony_ci    return createResponse.session_id();
21706f6ba60Sopenharmony_ci}
21806f6ba60Sopenharmony_ci
21906f6ba60Sopenharmony_cibool CheckStartSession(std::unique_ptr<IProfilerService::Stub>& profilerStub, uint32_t& sessionId)
22006f6ba60Sopenharmony_ci{
22106f6ba60Sopenharmony_ci    StartSessionRequest startRequest;
22206f6ba60Sopenharmony_ci    StartSessionResponse startResponse;
22306f6ba60Sopenharmony_ci    startRequest.set_request_id(0);
22406f6ba60Sopenharmony_ci    startRequest.set_session_id(sessionId);
22506f6ba60Sopenharmony_ci    grpc::ClientContext startContext;
22606f6ba60Sopenharmony_ci    grpc::Status status = profilerStub->StartSession(&startContext, startRequest, &startResponse);
22706f6ba60Sopenharmony_ci    if (!status.ok()) {
22806f6ba60Sopenharmony_ci        printf("StartSession FAIL\n");
22906f6ba60Sopenharmony_ci        return false;
23006f6ba60Sopenharmony_ci    }
23106f6ba60Sopenharmony_ci
23206f6ba60Sopenharmony_ci    return true;
23306f6ba60Sopenharmony_ci}
23406f6ba60Sopenharmony_ci
23506f6ba60Sopenharmony_cibool CheckStopSession(std::unique_ptr<IProfilerService::Stub>& profilerStub, uint32_t& sessionId)
23606f6ba60Sopenharmony_ci{
23706f6ba60Sopenharmony_ci    StopSessionRequest stopRequest;
23806f6ba60Sopenharmony_ci    StopSessionResponse stopResponse;
23906f6ba60Sopenharmony_ci    grpc::ClientContext stopContext;
24006f6ba60Sopenharmony_ci    stopRequest.set_session_id(sessionId);
24106f6ba60Sopenharmony_ci    grpc::Status status = profilerStub->StopSession(&stopContext, stopRequest, &stopResponse);
24206f6ba60Sopenharmony_ci    if (!status.ok()) {
24306f6ba60Sopenharmony_ci        return false;
24406f6ba60Sopenharmony_ci    }
24506f6ba60Sopenharmony_ci
24606f6ba60Sopenharmony_ci    printf("StopSession done!\n");
24706f6ba60Sopenharmony_ci    return true;
24806f6ba60Sopenharmony_ci}
24906f6ba60Sopenharmony_ci
25006f6ba60Sopenharmony_cibool CheckDestroySession(std::unique_ptr<IProfilerService::Stub>& profilerStub, uint32_t& sessionId)
25106f6ba60Sopenharmony_ci{
25206f6ba60Sopenharmony_ci    DestroySessionRequest destroyRequest;
25306f6ba60Sopenharmony_ci    DestroySessionResponse destroyResponse;
25406f6ba60Sopenharmony_ci    grpc::ClientContext destroyContext;
25506f6ba60Sopenharmony_ci    destroyRequest.set_session_id(sessionId);
25606f6ba60Sopenharmony_ci    grpc::Status status = profilerStub->DestroySession(&destroyContext, destroyRequest, &destroyResponse);
25706f6ba60Sopenharmony_ci    if (!status.ok()) {
25806f6ba60Sopenharmony_ci        return false;
25906f6ba60Sopenharmony_ci    }
26006f6ba60Sopenharmony_ci
26106f6ba60Sopenharmony_ci    printf("DestroySession done!\n");
26206f6ba60Sopenharmony_ci    return true;
26306f6ba60Sopenharmony_ci}
26406f6ba60Sopenharmony_ci
26506f6ba60Sopenharmony_civoid StartThread(std::unique_ptr<IProfilerService::Stub>& profilerStub, uint32_t& id, std::atomic<bool>& sendHeart)
26606f6ba60Sopenharmony_ci{
26706f6ba60Sopenharmony_ci    while (sendHeart.load()) {
26806f6ba60Sopenharmony_ci        KeepSessionRequest keepRequest;
26906f6ba60Sopenharmony_ci        keepRequest.set_request_id(0);
27006f6ba60Sopenharmony_ci        keepRequest.set_session_id(id);
27106f6ba60Sopenharmony_ci        keepRequest.set_keep_alive_time(KEEP_SESSION_TIMEOUT_MS);
27206f6ba60Sopenharmony_ci        grpc::ClientContext keepContext;
27306f6ba60Sopenharmony_ci        KeepSessionResponse keepResponse;
27406f6ba60Sopenharmony_ci        profilerStub->KeepSession(&keepContext, keepRequest, &keepResponse);
27506f6ba60Sopenharmony_ci
27606f6ba60Sopenharmony_ci        std::unique_lock<std::mutex> lck(g_keepSessionMutex);
27706f6ba60Sopenharmony_ci        g_keepSessionCv.wait_for(lck, std::chrono::seconds(KEEP_SESSION_SLEEP_SECOND));
27806f6ba60Sopenharmony_ci    }
27906f6ba60Sopenharmony_ci}
28006f6ba60Sopenharmony_ci
28106f6ba60Sopenharmony_civoid StopThread(std::thread& keepSessionThread, std::atomic<bool>& sendHeart)
28206f6ba60Sopenharmony_ci{
28306f6ba60Sopenharmony_ci    sendHeart = false;
28406f6ba60Sopenharmony_ci    g_keepSessionCv.notify_one();
28506f6ba60Sopenharmony_ci    if (keepSessionThread.joinable()) {
28606f6ba60Sopenharmony_ci        keepSessionThread.join();
28706f6ba60Sopenharmony_ci    }
28806f6ba60Sopenharmony_ci}
28906f6ba60Sopenharmony_ci
29006f6ba60Sopenharmony_cibool DoCapture(const std::string& config, const std::string& keepSecond, const std::string& outputFile)
29106f6ba60Sopenharmony_ci{
29206f6ba60Sopenharmony_ci    auto profilerStub = GetProfilerServiceStub();
29306f6ba60Sopenharmony_ci    if (profilerStub == nullptr) {
29406f6ba60Sopenharmony_ci        printf("Get profiler service stub failed!\n");
29506f6ba60Sopenharmony_ci        return false;
29606f6ba60Sopenharmony_ci    }
29706f6ba60Sopenharmony_ci    if (g_exitProcessFlag) {
29806f6ba60Sopenharmony_ci        return false;
29906f6ba60Sopenharmony_ci    }
30006f6ba60Sopenharmony_ci
30106f6ba60Sopenharmony_ci    if (!COMMON::IsNumeric(keepSecond)) {
30206f6ba60Sopenharmony_ci        printf("please input a valid time value");
30306f6ba60Sopenharmony_ci        return false;
30406f6ba60Sopenharmony_ci    }
30506f6ba60Sopenharmony_ci    uint32_t sessionId = CreateSession(profilerStub, config, keepSecond, outputFile);
30606f6ba60Sopenharmony_ci    if (sessionId == 0) {
30706f6ba60Sopenharmony_ci        printf("Create session returns Id 0\n");
30806f6ba60Sopenharmony_ci        return false;
30906f6ba60Sopenharmony_ci    }
31006f6ba60Sopenharmony_ci    if (g_exitProcessFlag) {
31106f6ba60Sopenharmony_ci        // session has been created, need to destroy the session.
31206f6ba60Sopenharmony_ci        return CheckDestroySession(profilerStub, sessionId);
31306f6ba60Sopenharmony_ci    }
31406f6ba60Sopenharmony_ci
31506f6ba60Sopenharmony_ci    // start keepSessionThread, in order to ensure the sessionId is valid.
31606f6ba60Sopenharmony_ci    std::atomic<bool> sendHeart = true;
31706f6ba60Sopenharmony_ci    std::thread keepSessionThread(StartThread, std::ref(profilerStub), std::ref(sessionId), std::ref(sendHeart));
31806f6ba60Sopenharmony_ci    if (g_exitProcessFlag) {
31906f6ba60Sopenharmony_ci        // session has been created and keepSessionThread has been started.
32006f6ba60Sopenharmony_ci        // need to stop keepSessionThread and destroy the session.
32106f6ba60Sopenharmony_ci        StopThread(keepSessionThread, sendHeart);
32206f6ba60Sopenharmony_ci        return CheckDestroySession(profilerStub, sessionId);
32306f6ba60Sopenharmony_ci    }
32406f6ba60Sopenharmony_ci
32506f6ba60Sopenharmony_ci    if (!CheckStartSession(profilerStub, sessionId)) {
32606f6ba60Sopenharmony_ci        return false;
32706f6ba60Sopenharmony_ci    }
32806f6ba60Sopenharmony_ci
32906f6ba60Sopenharmony_ci    if (!g_exitProcessFlag) {
33006f6ba60Sopenharmony_ci        // waiting for the collection time to end or signal wakeup.
33106f6ba60Sopenharmony_ci        printf("tracing %u ms....\n", g_sampleDuration);
33206f6ba60Sopenharmony_ci        std::cout.flush();
33306f6ba60Sopenharmony_ci        std::unique_lock<std::mutex> lck(g_sessionMutex);
33406f6ba60Sopenharmony_ci        g_sessionCv.wait_for(lck, std::chrono::milliseconds(g_sampleDuration));
33506f6ba60Sopenharmony_ci    }
33606f6ba60Sopenharmony_ci
33706f6ba60Sopenharmony_ci    bool ret = false;
33806f6ba60Sopenharmony_ci    if (CheckStopSession(profilerStub, sessionId) && CheckDestroySession(profilerStub, sessionId)) {
33906f6ba60Sopenharmony_ci        ret = true;
34006f6ba60Sopenharmony_ci    }
34106f6ba60Sopenharmony_ci
34206f6ba60Sopenharmony_ci    StopThread(keepSessionThread, sendHeart);
34306f6ba60Sopenharmony_ci    return ret;
34406f6ba60Sopenharmony_ci}
34506f6ba60Sopenharmony_ci
34606f6ba60Sopenharmony_cistruct DataContext {
34706f6ba60Sopenharmony_ci    bool isGetGrpcAddr = false;
34806f6ba60Sopenharmony_ci    std::string traceKeepSecond;
34906f6ba60Sopenharmony_ci    std::string configFile;
35006f6ba60Sopenharmony_ci    std::string outputFile;
35106f6ba60Sopenharmony_ci    bool isHelp = false;
35206f6ba60Sopenharmony_ci    bool isShowPluginList = false;
35306f6ba60Sopenharmony_ci    bool isStartProcess = false;
35406f6ba60Sopenharmony_ci    bool isKillProcess = false;
35506f6ba60Sopenharmony_ci};
35606f6ba60Sopenharmony_ci
35706f6ba60Sopenharmony_civoid ParseCmdline(CommandLine& cmdLine, DataContext& data)
35806f6ba60Sopenharmony_ci{
35906f6ba60Sopenharmony_ci    cmdLine.AddParamSwitch("--getport", "-q", data.isGetGrpcAddr, "get grpc address");
36006f6ba60Sopenharmony_ci    cmdLine.AddParamText("--time", "-t", data.traceKeepSecond, "trace time");
36106f6ba60Sopenharmony_ci    cmdLine.AddParamText("--out", "-o", data.outputFile, "output file name");
36206f6ba60Sopenharmony_ci    cmdLine.AddParamSwitch("--help", "-h", data.isHelp, "make some help");
36306f6ba60Sopenharmony_ci    cmdLine.AddParamSwitch("--list", "-l", data.isShowPluginList, "plugin list");
36406f6ba60Sopenharmony_ci    cmdLine.AddParamSwitch("--start", "-s", data.isStartProcess, "start dependent process");
36506f6ba60Sopenharmony_ci    cmdLine.AddParamSwitch("--kill", "-k", data.isKillProcess, "kill dependent process");
36606f6ba60Sopenharmony_ci    cmdLine.AddParamText("--config", "-c", data.configFile, "start trace by config file");
36706f6ba60Sopenharmony_ci}
36806f6ba60Sopenharmony_ci
36906f6ba60Sopenharmony_ciint CheckGrpcMsgSend()
37006f6ba60Sopenharmony_ci{
37106f6ba60Sopenharmony_ci    auto profilerStub = GetProfilerServiceStub();
37206f6ba60Sopenharmony_ci    if (profilerStub == nullptr) {
37306f6ba60Sopenharmony_ci        printf("Get profiler service stub failed!\n");
37406f6ba60Sopenharmony_ci        return -1;
37506f6ba60Sopenharmony_ci    }
37606f6ba60Sopenharmony_ci
37706f6ba60Sopenharmony_ci    GetCapabilitiesRequest request;
37806f6ba60Sopenharmony_ci    GetCapabilitiesResponse response;
37906f6ba60Sopenharmony_ci    request.set_request_id(0);
38006f6ba60Sopenharmony_ci
38106f6ba60Sopenharmony_ci    grpc::ClientContext context;
38206f6ba60Sopenharmony_ci    grpc::Status status = profilerStub->GetCapabilities(&context, request, &response);
38306f6ba60Sopenharmony_ci    if (!status.ok()) {
38406f6ba60Sopenharmony_ci        printf("Service not started\n");
38506f6ba60Sopenharmony_ci        return -1;
38606f6ba60Sopenharmony_ci    }
38706f6ba60Sopenharmony_ci
38806f6ba60Sopenharmony_ci    printf("OK\n");
38906f6ba60Sopenharmony_ci    printf("ip:%s\n", GetLoopbackAddress().c_str());
39006f6ba60Sopenharmony_ci    printf("port:%u\n", GetServicePort());
39106f6ba60Sopenharmony_ci    return 0;
39206f6ba60Sopenharmony_ci}
39306f6ba60Sopenharmony_ci
39406f6ba60Sopenharmony_cibool StartDependentProcess()
39506f6ba60Sopenharmony_ci{
39606f6ba60Sopenharmony_ci    constexpr int waitProcMills = 300;
39706f6ba60Sopenharmony_ci    OHOS::system::SetParameter("hiviewdfx.hiprofiler.memprofiler.start", "0");
39806f6ba60Sopenharmony_ci    std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
39906f6ba60Sopenharmony_ci    if (getuid() == 0) {
40006f6ba60Sopenharmony_ci        if (!COMMON::IsProcessExist(HIPROFILERD_NAME, g_hiprofilerdPid)) {
40106f6ba60Sopenharmony_ci            // need start hiprofilerd
40206f6ba60Sopenharmony_ci            std::vector<char*> argvVec;
40306f6ba60Sopenharmony_ci            argvVec.push_back(const_cast<char*>(HIPROFILERD_NAME.c_str()));
40406f6ba60Sopenharmony_ci            g_hiprofilerdPid = COMMON::StartProcess("/system/bin/hiprofilerd", argvVec);
40506f6ba60Sopenharmony_ci            // Wait for the hiprofilerd to start
40606f6ba60Sopenharmony_ci            std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
40706f6ba60Sopenharmony_ci        }
40806f6ba60Sopenharmony_ci
40906f6ba60Sopenharmony_ci        if (!COMMON::IsProcessExist(HIPROFILER_PLUGINS_NAME, g_hiprofilerPluginsPid)) {
41006f6ba60Sopenharmony_ci            // need start hiprofiler_plugins
41106f6ba60Sopenharmony_ci            std::vector<char*> argvVec;
41206f6ba60Sopenharmony_ci            argvVec.push_back(const_cast<char*>(HIPROFILER_PLUGINS_NAME.c_str()));
41306f6ba60Sopenharmony_ci            g_hiprofilerPluginsPid = COMMON::StartProcess("/system/bin/hiprofiler_plugins", argvVec);
41406f6ba60Sopenharmony_ci            // Wait for the hiprofiler_plugins add preset plugin
41506f6ba60Sopenharmony_ci            std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
41606f6ba60Sopenharmony_ci        }
41706f6ba60Sopenharmony_ci
41806f6ba60Sopenharmony_ci        if (!COMMON::IsProcessExist(NATIVE_DAEMON_NAME, g_nativeDaemonPid)) {
41906f6ba60Sopenharmony_ci            // need start native_daemon
42006f6ba60Sopenharmony_ci            std::vector<char*> argvVec;
42106f6ba60Sopenharmony_ci            argvVec.push_back(const_cast<char*>(NATIVE_DAEMON_NAME.c_str()));
42206f6ba60Sopenharmony_ci            g_nativeDaemonPid = COMMON::StartProcess("/system/bin/native_daemon", argvVec);
42306f6ba60Sopenharmony_ci            // Wait for the native_daemon to start
42406f6ba60Sopenharmony_ci            std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
42506f6ba60Sopenharmony_ci        }
42606f6ba60Sopenharmony_ci    } else {
42706f6ba60Sopenharmony_ci        OHOS::system::SetParameter("hiviewdfx.hiprofiler.profilerd.start", "0");
42806f6ba60Sopenharmony_ci        OHOS::system::SetParameter("hiviewdfx.hiprofiler.plugins.start", "0");
42906f6ba60Sopenharmony_ci        OHOS::system::SetParameter("hiviewdfx.hiprofiler.native_memoryd.start", "0");
43006f6ba60Sopenharmony_ci
43106f6ba60Sopenharmony_ci        OHOS::system::SetParameter("hiviewdfx.hiprofiler.profilerd.start", "1");
43206f6ba60Sopenharmony_ci        std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
43306f6ba60Sopenharmony_ci        OHOS::system::SetParameter("hiviewdfx.hiprofiler.plugins.start", "1");
43406f6ba60Sopenharmony_ci        std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
43506f6ba60Sopenharmony_ci        OHOS::system::SetParameter("hiviewdfx.hiprofiler.native_memoryd.start", "1");
43606f6ba60Sopenharmony_ci        std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
43706f6ba60Sopenharmony_ci    }
43806f6ba60Sopenharmony_ci
43906f6ba60Sopenharmony_ci    std::string content = "";
44006f6ba60Sopenharmony_ci    GetCapabilities(content, true);
44106f6ba60Sopenharmony_ci    if (content == "") {
44206f6ba60Sopenharmony_ci        printf("Please confirm whether the plugin exists\n");
44306f6ba60Sopenharmony_ci        return false;
44406f6ba60Sopenharmony_ci    }
44506f6ba60Sopenharmony_ci
44606f6ba60Sopenharmony_ci    return true;
44706f6ba60Sopenharmony_ci}
44806f6ba60Sopenharmony_ci
44906f6ba60Sopenharmony_cibool CheckProcessExit(const std::string& processName, int& pid)
45006f6ba60Sopenharmony_ci{
45106f6ba60Sopenharmony_ci    int nCount = 5; // 5: try 5 times
45206f6ba60Sopenharmony_ci    constexpr int waitExitMills = 1000;
45306f6ba60Sopenharmony_ci    while (nCount > 0) {
45406f6ba60Sopenharmony_ci        if (COMMON::IsProcessExist(processName, pid)) {
45506f6ba60Sopenharmony_ci            nCount--;
45606f6ba60Sopenharmony_ci            std::this_thread::sleep_for(std::chrono::milliseconds(waitExitMills));
45706f6ba60Sopenharmony_ci        } else {
45806f6ba60Sopenharmony_ci            break;
45906f6ba60Sopenharmony_ci        }
46006f6ba60Sopenharmony_ci    }
46106f6ba60Sopenharmony_ci    return nCount > 0;
46206f6ba60Sopenharmony_ci}
46306f6ba60Sopenharmony_ci
46406f6ba60Sopenharmony_civoid KillDependentProcess()
46506f6ba60Sopenharmony_ci{
46606f6ba60Sopenharmony_ci    constexpr int waitProcMills = 300;
46706f6ba60Sopenharmony_ci    OHOS::system::SetParameter("hiviewdfx.hiprofiler.memprofiler.start", "0");
46806f6ba60Sopenharmony_ci    std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
46906f6ba60Sopenharmony_ci    if (getuid() == 0) {
47006f6ba60Sopenharmony_ci        // if pid is equal to -1, need to get pid first.
47106f6ba60Sopenharmony_ci        if (g_nativeDaemonPid == -1) {
47206f6ba60Sopenharmony_ci            COMMON::IsProcessExist(NATIVE_DAEMON_NAME, g_nativeDaemonPid);
47306f6ba60Sopenharmony_ci        }
47406f6ba60Sopenharmony_ci        if (g_hiprofilerPluginsPid == -1) {
47506f6ba60Sopenharmony_ci            COMMON::IsProcessExist(HIPROFILER_PLUGINS_NAME, g_hiprofilerPluginsPid);
47606f6ba60Sopenharmony_ci        }
47706f6ba60Sopenharmony_ci        if (g_hiprofilerdPid == -1) {
47806f6ba60Sopenharmony_ci            COMMON::IsProcessExist(HIPROFILERD_NAME, g_hiprofilerdPid);
47906f6ba60Sopenharmony_ci        }
48006f6ba60Sopenharmony_ci        COMMON::KillProcess(g_nativeDaemonPid);
48106f6ba60Sopenharmony_ci        if (CheckProcessExit(NATIVE_DAEMON_NAME, g_nativeDaemonPid)) {
48206f6ba60Sopenharmony_ci            printf("process native_daemon exits successfully\n");
48306f6ba60Sopenharmony_ci        } else {
48406f6ba60Sopenharmony_ci            printf("process native_daemon exits failed\n");
48506f6ba60Sopenharmony_ci        }
48606f6ba60Sopenharmony_ci        COMMON::KillProcess(g_hiprofilerPluginsPid);
48706f6ba60Sopenharmony_ci        if (CheckProcessExit(HIPROFILER_PLUGINS_NAME, g_hiprofilerPluginsPid)) {
48806f6ba60Sopenharmony_ci            printf("process hiprofiler_plugins exits successfully\n");
48906f6ba60Sopenharmony_ci        } else {
49006f6ba60Sopenharmony_ci            printf("process hiprofiler_plugins exits failed\n");
49106f6ba60Sopenharmony_ci        }
49206f6ba60Sopenharmony_ci        COMMON::KillProcess(g_hiprofilerdPid);
49306f6ba60Sopenharmony_ci        if (CheckProcessExit(HIPROFILERD_NAME, g_hiprofilerdPid)) {
49406f6ba60Sopenharmony_ci            printf("process hiprofilerd exits successfully\n");
49506f6ba60Sopenharmony_ci        } else {
49606f6ba60Sopenharmony_ci            printf("process hiprofilerd exits failed\n");
49706f6ba60Sopenharmony_ci        }
49806f6ba60Sopenharmony_ci    } else {
49906f6ba60Sopenharmony_ci        OHOS::system::SetParameter("hiviewdfx.hiprofiler.profilerd.start", "0");
50006f6ba60Sopenharmony_ci        OHOS::system::SetParameter("hiviewdfx.hiprofiler.plugins.start", "0");
50106f6ba60Sopenharmony_ci        OHOS::system::SetParameter("hiviewdfx.hiprofiler.native_memoryd.start", "0");
50206f6ba60Sopenharmony_ci    }
50306f6ba60Sopenharmony_ci}
50406f6ba60Sopenharmony_ci
50506f6ba60Sopenharmony_cibool ParseConfig(const std::string& configFile, std::string& config)
50606f6ba60Sopenharmony_ci{
50706f6ba60Sopenharmony_ci    std::string configFileWithPath = configFile;
50806f6ba60Sopenharmony_ci    if (configFile.find('/') == std::string::npos) {
50906f6ba60Sopenharmony_ci        std::string path("/data/local/tmp/");
51006f6ba60Sopenharmony_ci        configFileWithPath = path + configFile; // add default path
51106f6ba60Sopenharmony_ci    }
51206f6ba60Sopenharmony_ci
51306f6ba60Sopenharmony_ci    printf("Read config from %s\n", configFileWithPath.c_str());
51406f6ba60Sopenharmony_ci    std::vector<std::string> validPaths = { "/data/local/tmp/" };
51506f6ba60Sopenharmony_ci    if (!COMMON::ReadFile(configFileWithPath, validPaths, config)) {
51606f6ba60Sopenharmony_ci        printf("Read %s fail, please place it under \'/data/local/tmp/\'.\n", configFile.c_str());
51706f6ba60Sopenharmony_ci        return false;
51806f6ba60Sopenharmony_ci    }
51906f6ba60Sopenharmony_ci    config = ParsePluginConfig::GetInstance().GetPluginsConfig(config);
52006f6ba60Sopenharmony_ci    if (config.empty()) {
52106f6ba60Sopenharmony_ci        printf("Error config file: %s\n", configFileWithPath.c_str()); // no config in command or config file
52206f6ba60Sopenharmony_ci        return false;
52306f6ba60Sopenharmony_ci    }
52406f6ba60Sopenharmony_ci    return true;
52506f6ba60Sopenharmony_ci}
52606f6ba60Sopenharmony_ci
52706f6ba60Sopenharmony_civoid SignalHandler(int signal)
52806f6ba60Sopenharmony_ci{
52906f6ba60Sopenharmony_ci    if (signal == SIGINT) {
53006f6ba60Sopenharmony_ci        g_exitProcessFlag = true;
53106f6ba60Sopenharmony_ci        std::async(&std::condition_variable::notify_one, &g_sessionCv);
53206f6ba60Sopenharmony_ci    }
53306f6ba60Sopenharmony_ci}
53406f6ba60Sopenharmony_ci} // namespace
53506f6ba60Sopenharmony_ci
53606f6ba60Sopenharmony_ciint main(int argc, char* argv[])
53706f6ba60Sopenharmony_ci{
53806f6ba60Sopenharmony_ci    if (!COMMON::GetDeveloperMode()) {
53906f6ba60Sopenharmony_ci        return -1;
54006f6ba60Sopenharmony_ci    }
54106f6ba60Sopenharmony_ci    signal(SIGINT, SignalHandler);
54206f6ba60Sopenharmony_ci
54306f6ba60Sopenharmony_ci    std::string config = "";
54406f6ba60Sopenharmony_ci    while (true) {
54506f6ba60Sopenharmony_ci        struct option long_options[] = {
54606f6ba60Sopenharmony_ci            {"getport", no_argument, nullptr, 'q'},
54706f6ba60Sopenharmony_ci            {"time", required_argument, nullptr, 't'},
54806f6ba60Sopenharmony_ci            {"out", required_argument, nullptr, 'o'},
54906f6ba60Sopenharmony_ci            {"help", no_argument, nullptr, 'h'},
55006f6ba60Sopenharmony_ci            {"list", no_argument, nullptr, 'l'},
55106f6ba60Sopenharmony_ci            {"start", no_argument,  nullptr, 's'},
55206f6ba60Sopenharmony_ci            {"kill", no_argument,  nullptr, 'k'},
55306f6ba60Sopenharmony_ci            {"config", required_argument, nullptr, 'c'},
55406f6ba60Sopenharmony_ci            {nullptr, 0, nullptr, 0}
55506f6ba60Sopenharmony_ci        };
55606f6ba60Sopenharmony_ci        int option = getopt_long(argc, argv, "c:t:o:qhlsk", long_options, nullptr);
55706f6ba60Sopenharmony_ci        if (option == -1) {
55806f6ba60Sopenharmony_ci            break;  // CONFIG.
55906f6ba60Sopenharmony_ci        }
56006f6ba60Sopenharmony_ci
56106f6ba60Sopenharmony_ci        if (option == 'c' && strcmp(optarg, "-") == 0) {
56206f6ba60Sopenharmony_ci            std::string content;
56306f6ba60Sopenharmony_ci            std::istreambuf_iterator<char> begin(std::cin);
56406f6ba60Sopenharmony_ci            std::istreambuf_iterator<char> end = {};
56506f6ba60Sopenharmony_ci            content.assign(begin, end);
56606f6ba60Sopenharmony_ci            config = ParsePluginConfig::GetInstance().GetPluginsConfig(content);
56706f6ba60Sopenharmony_ci            if (config.empty()) {
56806f6ba60Sopenharmony_ci                printf("Please check the configuration!\n");
56906f6ba60Sopenharmony_ci                return -1;
57006f6ba60Sopenharmony_ci            }
57106f6ba60Sopenharmony_ci        }
57206f6ba60Sopenharmony_ci    }
57306f6ba60Sopenharmony_ci
57406f6ba60Sopenharmony_ci    DataContext data;
57506f6ba60Sopenharmony_ci    CommandLine& cmdLine = CommandLine::GetInstance();
57606f6ba60Sopenharmony_ci    ParseCmdline(cmdLine, data);
57706f6ba60Sopenharmony_ci
57806f6ba60Sopenharmony_ci    std::vector<std::string> argvVector;
57906f6ba60Sopenharmony_ci    for (int i = 0; i < argc; i++) {
58006f6ba60Sopenharmony_ci        if (((i + 1) < argc) && (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--config") == 0) &&
58106f6ba60Sopenharmony_ci            (strcmp(argv[i + 1], "-") == 0)) {
58206f6ba60Sopenharmony_ci            i++;
58306f6ba60Sopenharmony_ci        } else {
58406f6ba60Sopenharmony_ci            argvVector.push_back(argv[i]);
58506f6ba60Sopenharmony_ci        }
58606f6ba60Sopenharmony_ci    }
58706f6ba60Sopenharmony_ci    if (argc < 1 || cmdLine.AnalyzeParam(argvVector) < 0 || data.isHelp) {
58806f6ba60Sopenharmony_ci        cmdLine.PrintHelp();
58906f6ba60Sopenharmony_ci        exit(0);
59006f6ba60Sopenharmony_ci    }
59106f6ba60Sopenharmony_ci
59206f6ba60Sopenharmony_ci    // need to delete old file.
59306f6ba60Sopenharmony_ci    remove(data.outputFile.c_str());
59406f6ba60Sopenharmony_ci
59506f6ba60Sopenharmony_ci    if (config.empty() && !data.configFile.empty()) {
59606f6ba60Sopenharmony_ci        if (!ParseConfig(data.configFile, config)) {
59706f6ba60Sopenharmony_ci            return -1;
59806f6ba60Sopenharmony_ci        }
59906f6ba60Sopenharmony_ci    }
60006f6ba60Sopenharmony_ci
60106f6ba60Sopenharmony_ci    if (data.isStartProcess) {
60206f6ba60Sopenharmony_ci        if (!StartDependentProcess()) {
60306f6ba60Sopenharmony_ci            if (data.isKillProcess) {
60406f6ba60Sopenharmony_ci                KillDependentProcess();
60506f6ba60Sopenharmony_ci            }
60606f6ba60Sopenharmony_ci            return 0;
60706f6ba60Sopenharmony_ci        }
60806f6ba60Sopenharmony_ci    }
60906f6ba60Sopenharmony_ci
61006f6ba60Sopenharmony_ci    if (data.isGetGrpcAddr) { // handle get port
61106f6ba60Sopenharmony_ci        int ret = CheckGrpcMsgSend();
61206f6ba60Sopenharmony_ci        if (data.isKillProcess) {
61306f6ba60Sopenharmony_ci            KillDependentProcess();
61406f6ba60Sopenharmony_ci        }
61506f6ba60Sopenharmony_ci        return ret;
61606f6ba60Sopenharmony_ci    }
61706f6ba60Sopenharmony_ci
61806f6ba60Sopenharmony_ci    if (data.isShowPluginList) { // handle show plugin list
61906f6ba60Sopenharmony_ci        std::string content = "";
62006f6ba60Sopenharmony_ci        GetCapabilities(content, false);
62106f6ba60Sopenharmony_ci        if (data.isKillProcess) {
62206f6ba60Sopenharmony_ci            KillDependentProcess();
62306f6ba60Sopenharmony_ci        }
62406f6ba60Sopenharmony_ci        return 0;
62506f6ba60Sopenharmony_ci    }
62606f6ba60Sopenharmony_ci
62706f6ba60Sopenharmony_ci    if (config.empty()) { // normal case
62806f6ba60Sopenharmony_ci        if (data.isKillProcess) {
62906f6ba60Sopenharmony_ci            KillDependentProcess();
63006f6ba60Sopenharmony_ci            return 1;
63106f6ba60Sopenharmony_ci        }
63206f6ba60Sopenharmony_ci        if (!data.isStartProcess) {
63306f6ba60Sopenharmony_ci            printf("config file argument must sepcified!\n");
63406f6ba60Sopenharmony_ci        }
63506f6ba60Sopenharmony_ci        return 1;
63606f6ba60Sopenharmony_ci    }
63706f6ba60Sopenharmony_ci    // do capture work
63806f6ba60Sopenharmony_ci    if (DoCapture(config, data.traceKeepSecond, data.outputFile)) {
63906f6ba60Sopenharmony_ci        printf("DONE\n");
64006f6ba60Sopenharmony_ci    }
64106f6ba60Sopenharmony_ci
64206f6ba60Sopenharmony_ci    if (data.isKillProcess) {
64306f6ba60Sopenharmony_ci        KillDependentProcess();
64406f6ba60Sopenharmony_ci    }
64506f6ba60Sopenharmony_ci    return 0;
64606f6ba60Sopenharmony_ci}
647