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