1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <arpa/inet.h>
17 #include <cinttypes>
18 #include <condition_variable>
19 #include <csignal>
20 #include <cstdio>
21 #include <cstring>
22 #include <fstream>
23 #include <getopt.h>
24 #include <grpcpp/grpcpp.h>
25 #include <ifaddrs.h>
26 #include <netinet/in.h>
27 #include <ostream>
28 #include <sys/types.h>
29 #include <thread>
30 #include <unistd.h>
31 #include <vector>
32 #include <future>
33
34 #include "common.h"
35 #include "command_line.h"
36 #include "google/protobuf/text_format.h"
37 #include "parameters.h"
38 #include "parse_plugin_config.h"
39 #include "profiler_service.grpc.pb.h"
40 #include "trace_plugin_config.pb.h"
41
42 using google::protobuf::TextFormat;
43
44 namespace {
45 constexpr int ADDR_BUFFER_SIZE = 128;
46 constexpr int MS_PER_S = 1000;
47 constexpr int KEEP_SESSION_TIMEOUT_MS = 5 * 1000;
48 constexpr int KEEP_SESSION_SLEEP_SECOND = 3;
49 constexpr int DEFAULT_SESSION_TIME_S = 10;
50 constexpr uint32_t INT_MAX_LEN = 10;
51 const std::string DEFAULT_OUTPUT_FILE = "/data/local/tmp/hiprofiler_data.htrace";
52 const std::string HIPROFILERD_NAME("hiprofilerd");
53 const std::string HIPROFILER_PLUGINS_NAME("hiprofiler_plugins");
54 const std::string NATIVE_DAEMON_NAME("native_daemon");
55
56 uint32_t g_sampleDuration = 0;
57 int g_hiprofilerdPid = -1;
58 int g_hiprofilerPluginsPid = -1;
59 int g_nativeDaemonPid = -1;
60 std::condition_variable g_sessionCv;
61 std::condition_variable g_keepSessionCv;
62 bool g_exitProcessFlag = false;
63
64 std::mutex g_keepSessionMutex;
65 std::mutex g_sessionMutex;
66
GetLoopbackAddress()67 std::string GetLoopbackAddress()
68 {
69 char addressBuffer[ADDR_BUFFER_SIZE] = "";
70 struct ifaddrs* ifAddrStruct = nullptr;
71 void* tmpAddrPtr = nullptr;
72
73 getifaddrs(&ifAddrStruct);
74 while (ifAddrStruct != nullptr) {
75 if (ifAddrStruct->ifa_addr == nullptr) {
76 ifAddrStruct = ifAddrStruct->ifa_next;
77 continue;
78 }
79 if (ifAddrStruct->ifa_addr->sa_family == AF_INET) {
80 // is a valid IP4 Address
81 tmpAddrPtr = &((reinterpret_cast<struct sockaddr_in*>(ifAddrStruct->ifa_addr))->sin_addr);
82 inet_ntop(AF_INET, tmpAddrPtr, addressBuffer, INET_ADDRSTRLEN);
83 if (strcmp(addressBuffer, "127.0.0.1") == 0) {
84 break;
85 }
86 } else if (ifAddrStruct->ifa_addr->sa_family == AF_INET6) { // check it is IP6
87 // is a valid IP6 Address
88 tmpAddrPtr = &((reinterpret_cast<struct sockaddr_in*>(ifAddrStruct->ifa_addr))->sin_addr);
89 inet_ntop(AF_INET6, tmpAddrPtr, addressBuffer, INET6_ADDRSTRLEN);
90 }
91 ifAddrStruct = ifAddrStruct->ifa_next;
92 }
93
94 freeifaddrs(ifAddrStruct);
95 return addressBuffer;
96 }
97
GetServicePort()98 uint16_t GetServicePort()
99 {
100 return COMMON::GetServicePort();
101 }
102
MakeCreateRequest(const std::string& config, const std::string& keepSecond, const std::string& outputFile)103 std::unique_ptr<CreateSessionRequest> MakeCreateRequest(const std::string& config,
104 const std::string& keepSecond,
105 const std::string& outputFile)
106 {
107 auto request = std::make_unique<CreateSessionRequest>();
108 std::string content = config;
109 if (content.empty()) {
110 printf("config file empty!");
111 return nullptr;
112 }
113
114 if (!ParsePluginConfig::GetInstance().GetParser().ParseFromString(content, request.get())) {
115 printf("config [%s] parse FAILED!\n", content.c_str());
116 return nullptr;
117 }
118
119 auto sessionConfig = request->mutable_session_config();
120 if (!sessionConfig) {
121 return nullptr;
122 }
123
124 request->set_request_id(1);
125 if (!keepSecond.empty() && keepSecond.size() < INT_MAX_LEN) {
126 int ks = COMMON::IsNumeric(keepSecond) ? std::stoi(keepSecond) : 0;
127 if (ks > 0) {
128 sessionConfig->set_sample_duration(ks * MS_PER_S);
129 }
130 } else if (sessionConfig->sample_duration() <= 0) {
131 sessionConfig->set_sample_duration(DEFAULT_SESSION_TIME_S * MS_PER_S);
132 }
133 if (!outputFile.empty()) {
134 sessionConfig->set_result_file(outputFile);
135 } else if (sessionConfig->result_file() == "") {
136 sessionConfig->set_result_file(DEFAULT_OUTPUT_FILE);
137 }
138 printf("keepSecond: %us, outputFileName: %s\n", sessionConfig->sample_duration() / MS_PER_S,
139 sessionConfig->result_file().c_str());
140
141 g_sampleDuration = sessionConfig->sample_duration();
142 for (int i = 0; i < request->plugin_configs().size(); i++) {
143 auto pluginConfig = request->mutable_plugin_configs(i);
144 if (!ParsePluginConfig::GetInstance().SetSerializePluginsConfig(pluginConfig->name(), *pluginConfig)) {
145 printf("set %s plugin config failed\n", pluginConfig->name().c_str());
146 return nullptr;
147 }
148 }
149
150 content.clear();
151 if (!TextFormat::PrintToString(*request.get(), &content)) {
152 printf("config message format FAILED!\n");
153 return nullptr;
154 }
155
156 return request;
157 }
158
GetProfilerServiceStub()159 std::unique_ptr<IProfilerService::Stub> GetProfilerServiceStub()
160 {
161 std::string serviceUri = GetLoopbackAddress() + ":" + std::to_string(GetServicePort());
162 auto grpcChannel = grpc::CreateChannel(serviceUri, grpc::InsecureChannelCredentials());
163 if (grpcChannel == nullptr) {
164 printf("Create gRPC channel failed!\n");
165 return nullptr;
166 }
167 return IProfilerService::NewStub(grpcChannel);
168 }
169
GetCapabilities(std::string& content, bool isCheck)170 bool GetCapabilities(std::string& content, bool isCheck)
171 {
172 auto profilerStub = GetProfilerServiceStub();
173 if (profilerStub == nullptr) {
174 printf("Get profiler service stub failed!\n");
175 return false;
176 }
177
178 GetCapabilitiesRequest capRequest;
179 GetCapabilitiesResponse capResponse;
180 capRequest.set_request_id(0);
181 grpc::ClientContext capContext;
182 grpc::Status status = profilerStub->GetCapabilities(&capContext, capRequest, &capResponse);
183 if (!status.ok()) {
184 printf("Service not started\n");
185 return false;
186 }
187
188 if (!TextFormat::PrintToString(capResponse, &content)) {
189 printf("capabilities message format FAILED!\n");
190 return false;
191 }
192
193 if (!isCheck) {
194 printf("support plugin list:\n%s\n", content.c_str());
195 }
196 return true;
197 }
198
CreateSession(std::unique_ptr<IProfilerService::Stub>& profilerStub, const std::string& config, const std::string& keepSecond, const std::string& outputFile)199 uint32_t CreateSession(std::unique_ptr<IProfilerService::Stub>& profilerStub, const std::string& config,
200 const std::string& keepSecond, const std::string& outputFile)
201 {
202 auto request = MakeCreateRequest(config, keepSecond, outputFile);
203 if (!request) {
204 printf("MakeCreateRequest failed!\n");
205 return 0;
206 }
207
208 CreateSessionResponse createResponse;
209 grpc::ClientContext createSessionContext;
210 grpc::Status status = profilerStub->CreateSession(&createSessionContext, *request, &createResponse);
211 if (!status.ok()) {
212 printf("CreateSession FAIL\n");
213 return 0;
214 }
215
216 return createResponse.session_id();
217 }
218
CheckStartSession(std::unique_ptr<IProfilerService::Stub>& profilerStub, uint32_t& sessionId)219 bool CheckStartSession(std::unique_ptr<IProfilerService::Stub>& profilerStub, uint32_t& sessionId)
220 {
221 StartSessionRequest startRequest;
222 StartSessionResponse startResponse;
223 startRequest.set_request_id(0);
224 startRequest.set_session_id(sessionId);
225 grpc::ClientContext startContext;
226 grpc::Status status = profilerStub->StartSession(&startContext, startRequest, &startResponse);
227 if (!status.ok()) {
228 printf("StartSession FAIL\n");
229 return false;
230 }
231
232 return true;
233 }
234
CheckStopSession(std::unique_ptr<IProfilerService::Stub>& profilerStub, uint32_t& sessionId)235 bool CheckStopSession(std::unique_ptr<IProfilerService::Stub>& profilerStub, uint32_t& sessionId)
236 {
237 StopSessionRequest stopRequest;
238 StopSessionResponse stopResponse;
239 grpc::ClientContext stopContext;
240 stopRequest.set_session_id(sessionId);
241 grpc::Status status = profilerStub->StopSession(&stopContext, stopRequest, &stopResponse);
242 if (!status.ok()) {
243 return false;
244 }
245
246 printf("StopSession done!\n");
247 return true;
248 }
249
CheckDestroySession(std::unique_ptr<IProfilerService::Stub>& profilerStub, uint32_t& sessionId)250 bool CheckDestroySession(std::unique_ptr<IProfilerService::Stub>& profilerStub, uint32_t& sessionId)
251 {
252 DestroySessionRequest destroyRequest;
253 DestroySessionResponse destroyResponse;
254 grpc::ClientContext destroyContext;
255 destroyRequest.set_session_id(sessionId);
256 grpc::Status status = profilerStub->DestroySession(&destroyContext, destroyRequest, &destroyResponse);
257 if (!status.ok()) {
258 return false;
259 }
260
261 printf("DestroySession done!\n");
262 return true;
263 }
264
StartThread(std::unique_ptr<IProfilerService::Stub>& profilerStub, uint32_t& id, std::atomic<bool>& sendHeart)265 void StartThread(std::unique_ptr<IProfilerService::Stub>& profilerStub, uint32_t& id, std::atomic<bool>& sendHeart)
266 {
267 while (sendHeart.load()) {
268 KeepSessionRequest keepRequest;
269 keepRequest.set_request_id(0);
270 keepRequest.set_session_id(id);
271 keepRequest.set_keep_alive_time(KEEP_SESSION_TIMEOUT_MS);
272 grpc::ClientContext keepContext;
273 KeepSessionResponse keepResponse;
274 profilerStub->KeepSession(&keepContext, keepRequest, &keepResponse);
275
276 std::unique_lock<std::mutex> lck(g_keepSessionMutex);
277 g_keepSessionCv.wait_for(lck, std::chrono::seconds(KEEP_SESSION_SLEEP_SECOND));
278 }
279 }
280
StopThread(std::thread& keepSessionThread, std::atomic<bool>& sendHeart)281 void StopThread(std::thread& keepSessionThread, std::atomic<bool>& sendHeart)
282 {
283 sendHeart = false;
284 g_keepSessionCv.notify_one();
285 if (keepSessionThread.joinable()) {
286 keepSessionThread.join();
287 }
288 }
289
DoCapture(const std::string& config, const std::string& keepSecond, const std::string& outputFile)290 bool DoCapture(const std::string& config, const std::string& keepSecond, const std::string& outputFile)
291 {
292 auto profilerStub = GetProfilerServiceStub();
293 if (profilerStub == nullptr) {
294 printf("Get profiler service stub failed!\n");
295 return false;
296 }
297 if (g_exitProcessFlag) {
298 return false;
299 }
300
301 if (!COMMON::IsNumeric(keepSecond)) {
302 printf("please input a valid time value");
303 return false;
304 }
305 uint32_t sessionId = CreateSession(profilerStub, config, keepSecond, outputFile);
306 if (sessionId == 0) {
307 printf("Create session returns Id 0\n");
308 return false;
309 }
310 if (g_exitProcessFlag) {
311 // session has been created, need to destroy the session.
312 return CheckDestroySession(profilerStub, sessionId);
313 }
314
315 // start keepSessionThread, in order to ensure the sessionId is valid.
316 std::atomic<bool> sendHeart = true;
317 std::thread keepSessionThread(StartThread, std::ref(profilerStub), std::ref(sessionId), std::ref(sendHeart));
318 if (g_exitProcessFlag) {
319 // session has been created and keepSessionThread has been started.
320 // need to stop keepSessionThread and destroy the session.
321 StopThread(keepSessionThread, sendHeart);
322 return CheckDestroySession(profilerStub, sessionId);
323 }
324
325 if (!CheckStartSession(profilerStub, sessionId)) {
326 return false;
327 }
328
329 if (!g_exitProcessFlag) {
330 // waiting for the collection time to end or signal wakeup.
331 printf("tracing %u ms....\n", g_sampleDuration);
332 std::cout.flush();
333 std::unique_lock<std::mutex> lck(g_sessionMutex);
334 g_sessionCv.wait_for(lck, std::chrono::milliseconds(g_sampleDuration));
335 }
336
337 bool ret = false;
338 if (CheckStopSession(profilerStub, sessionId) && CheckDestroySession(profilerStub, sessionId)) {
339 ret = true;
340 }
341
342 StopThread(keepSessionThread, sendHeart);
343 return ret;
344 }
345
346 struct DataContext {
347 bool isGetGrpcAddr = false;
348 std::string traceKeepSecond;
349 std::string configFile;
350 std::string outputFile;
351 bool isHelp = false;
352 bool isShowPluginList = false;
353 bool isStartProcess = false;
354 bool isKillProcess = false;
355 };
356
ParseCmdline(CommandLine& cmdLine, DataContext& data)357 void ParseCmdline(CommandLine& cmdLine, DataContext& data)
358 {
359 cmdLine.AddParamSwitch("--getport", "-q", data.isGetGrpcAddr, "get grpc address");
360 cmdLine.AddParamText("--time", "-t", data.traceKeepSecond, "trace time");
361 cmdLine.AddParamText("--out", "-o", data.outputFile, "output file name");
362 cmdLine.AddParamSwitch("--help", "-h", data.isHelp, "make some help");
363 cmdLine.AddParamSwitch("--list", "-l", data.isShowPluginList, "plugin list");
364 cmdLine.AddParamSwitch("--start", "-s", data.isStartProcess, "start dependent process");
365 cmdLine.AddParamSwitch("--kill", "-k", data.isKillProcess, "kill dependent process");
366 cmdLine.AddParamText("--config", "-c", data.configFile, "start trace by config file");
367 }
368
CheckGrpcMsgSend()369 int CheckGrpcMsgSend()
370 {
371 auto profilerStub = GetProfilerServiceStub();
372 if (profilerStub == nullptr) {
373 printf("Get profiler service stub failed!\n");
374 return -1;
375 }
376
377 GetCapabilitiesRequest request;
378 GetCapabilitiesResponse response;
379 request.set_request_id(0);
380
381 grpc::ClientContext context;
382 grpc::Status status = profilerStub->GetCapabilities(&context, request, &response);
383 if (!status.ok()) {
384 printf("Service not started\n");
385 return -1;
386 }
387
388 printf("OK\n");
389 printf("ip:%s\n", GetLoopbackAddress().c_str());
390 printf("port:%u\n", GetServicePort());
391 return 0;
392 }
393
StartDependentProcess()394 bool StartDependentProcess()
395 {
396 constexpr int waitProcMills = 300;
397 OHOS::system::SetParameter("hiviewdfx.hiprofiler.memprofiler.start", "0");
398 std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
399 if (getuid() == 0) {
400 if (!COMMON::IsProcessExist(HIPROFILERD_NAME, g_hiprofilerdPid)) {
401 // need start hiprofilerd
402 std::vector<char*> argvVec;
403 argvVec.push_back(const_cast<char*>(HIPROFILERD_NAME.c_str()));
404 g_hiprofilerdPid = COMMON::StartProcess("/system/bin/hiprofilerd", argvVec);
405 // Wait for the hiprofilerd to start
406 std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
407 }
408
409 if (!COMMON::IsProcessExist(HIPROFILER_PLUGINS_NAME, g_hiprofilerPluginsPid)) {
410 // need start hiprofiler_plugins
411 std::vector<char*> argvVec;
412 argvVec.push_back(const_cast<char*>(HIPROFILER_PLUGINS_NAME.c_str()));
413 g_hiprofilerPluginsPid = COMMON::StartProcess("/system/bin/hiprofiler_plugins", argvVec);
414 // Wait for the hiprofiler_plugins add preset plugin
415 std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
416 }
417
418 if (!COMMON::IsProcessExist(NATIVE_DAEMON_NAME, g_nativeDaemonPid)) {
419 // need start native_daemon
420 std::vector<char*> argvVec;
421 argvVec.push_back(const_cast<char*>(NATIVE_DAEMON_NAME.c_str()));
422 g_nativeDaemonPid = COMMON::StartProcess("/system/bin/native_daemon", argvVec);
423 // Wait for the native_daemon to start
424 std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
425 }
426 } else {
427 OHOS::system::SetParameter("hiviewdfx.hiprofiler.profilerd.start", "0");
428 OHOS::system::SetParameter("hiviewdfx.hiprofiler.plugins.start", "0");
429 OHOS::system::SetParameter("hiviewdfx.hiprofiler.native_memoryd.start", "0");
430
431 OHOS::system::SetParameter("hiviewdfx.hiprofiler.profilerd.start", "1");
432 std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
433 OHOS::system::SetParameter("hiviewdfx.hiprofiler.plugins.start", "1");
434 std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
435 OHOS::system::SetParameter("hiviewdfx.hiprofiler.native_memoryd.start", "1");
436 std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
437 }
438
439 std::string content = "";
440 GetCapabilities(content, true);
441 if (content == "") {
442 printf("Please confirm whether the plugin exists\n");
443 return false;
444 }
445
446 return true;
447 }
448
CheckProcessExit(const std::string& processName, int& pid)449 bool CheckProcessExit(const std::string& processName, int& pid)
450 {
451 int nCount = 5; // 5: try 5 times
452 constexpr int waitExitMills = 1000;
453 while (nCount > 0) {
454 if (COMMON::IsProcessExist(processName, pid)) {
455 nCount--;
456 std::this_thread::sleep_for(std::chrono::milliseconds(waitExitMills));
457 } else {
458 break;
459 }
460 }
461 return nCount > 0;
462 }
463
KillDependentProcess()464 void KillDependentProcess()
465 {
466 constexpr int waitProcMills = 300;
467 OHOS::system::SetParameter("hiviewdfx.hiprofiler.memprofiler.start", "0");
468 std::this_thread::sleep_for(std::chrono::milliseconds(waitProcMills));
469 if (getuid() == 0) {
470 // if pid is equal to -1, need to get pid first.
471 if (g_nativeDaemonPid == -1) {
472 COMMON::IsProcessExist(NATIVE_DAEMON_NAME, g_nativeDaemonPid);
473 }
474 if (g_hiprofilerPluginsPid == -1) {
475 COMMON::IsProcessExist(HIPROFILER_PLUGINS_NAME, g_hiprofilerPluginsPid);
476 }
477 if (g_hiprofilerdPid == -1) {
478 COMMON::IsProcessExist(HIPROFILERD_NAME, g_hiprofilerdPid);
479 }
480 COMMON::KillProcess(g_nativeDaemonPid);
481 if (CheckProcessExit(NATIVE_DAEMON_NAME, g_nativeDaemonPid)) {
482 printf("process native_daemon exits successfully\n");
483 } else {
484 printf("process native_daemon exits failed\n");
485 }
486 COMMON::KillProcess(g_hiprofilerPluginsPid);
487 if (CheckProcessExit(HIPROFILER_PLUGINS_NAME, g_hiprofilerPluginsPid)) {
488 printf("process hiprofiler_plugins exits successfully\n");
489 } else {
490 printf("process hiprofiler_plugins exits failed\n");
491 }
492 COMMON::KillProcess(g_hiprofilerdPid);
493 if (CheckProcessExit(HIPROFILERD_NAME, g_hiprofilerdPid)) {
494 printf("process hiprofilerd exits successfully\n");
495 } else {
496 printf("process hiprofilerd exits failed\n");
497 }
498 } else {
499 OHOS::system::SetParameter("hiviewdfx.hiprofiler.profilerd.start", "0");
500 OHOS::system::SetParameter("hiviewdfx.hiprofiler.plugins.start", "0");
501 OHOS::system::SetParameter("hiviewdfx.hiprofiler.native_memoryd.start", "0");
502 }
503 }
504
ParseConfig(const std::string& configFile, std::string& config)505 bool ParseConfig(const std::string& configFile, std::string& config)
506 {
507 std::string configFileWithPath = configFile;
508 if (configFile.find('/') == std::string::npos) {
509 std::string path("/data/local/tmp/");
510 configFileWithPath = path + configFile; // add default path
511 }
512
513 printf("Read config from %s\n", configFileWithPath.c_str());
514 std::vector<std::string> validPaths = { "/data/local/tmp/" };
515 if (!COMMON::ReadFile(configFileWithPath, validPaths, config)) {
516 printf("Read %s fail, please place it under \'/data/local/tmp/\'.\n", configFile.c_str());
517 return false;
518 }
519 config = ParsePluginConfig::GetInstance().GetPluginsConfig(config);
520 if (config.empty()) {
521 printf("Error config file: %s\n", configFileWithPath.c_str()); // no config in command or config file
522 return false;
523 }
524 return true;
525 }
526
SignalHandler(int signal)527 void SignalHandler(int signal)
528 {
529 if (signal == SIGINT) {
530 g_exitProcessFlag = true;
531 std::async(&std::condition_variable::notify_one, &g_sessionCv);
532 }
533 }
534 } // namespace
535
main(int argc, char* argv[])536 int main(int argc, char* argv[])
537 {
538 if (!COMMON::GetDeveloperMode()) {
539 return -1;
540 }
541 signal(SIGINT, SignalHandler);
542
543 std::string config = "";
544 while (true) {
545 struct option long_options[] = {
546 {"getport", no_argument, nullptr, 'q'},
547 {"time", required_argument, nullptr, 't'},
548 {"out", required_argument, nullptr, 'o'},
549 {"help", no_argument, nullptr, 'h'},
550 {"list", no_argument, nullptr, 'l'},
551 {"start", no_argument, nullptr, 's'},
552 {"kill", no_argument, nullptr, 'k'},
553 {"config", required_argument, nullptr, 'c'},
554 {nullptr, 0, nullptr, 0}
555 };
556 int option = getopt_long(argc, argv, "c:t:o:qhlsk", long_options, nullptr);
557 if (option == -1) {
558 break; // CONFIG.
559 }
560
561 if (option == 'c' && strcmp(optarg, "-") == 0) {
562 std::string content;
563 std::istreambuf_iterator<char> begin(std::cin);
564 std::istreambuf_iterator<char> end = {};
565 content.assign(begin, end);
566 config = ParsePluginConfig::GetInstance().GetPluginsConfig(content);
567 if (config.empty()) {
568 printf("Please check the configuration!\n");
569 return -1;
570 }
571 }
572 }
573
574 DataContext data;
575 CommandLine& cmdLine = CommandLine::GetInstance();
576 ParseCmdline(cmdLine, data);
577
578 std::vector<std::string> argvVector;
579 for (int i = 0; i < argc; i++) {
580 if (((i + 1) < argc) && (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--config") == 0) &&
581 (strcmp(argv[i + 1], "-") == 0)) {
582 i++;
583 } else {
584 argvVector.push_back(argv[i]);
585 }
586 }
587 if (argc < 1 || cmdLine.AnalyzeParam(argvVector) < 0 || data.isHelp) {
588 cmdLine.PrintHelp();
589 exit(0);
590 }
591
592 // need to delete old file.
593 remove(data.outputFile.c_str());
594
595 if (config.empty() && !data.configFile.empty()) {
596 if (!ParseConfig(data.configFile, config)) {
597 return -1;
598 }
599 }
600
601 if (data.isStartProcess) {
602 if (!StartDependentProcess()) {
603 if (data.isKillProcess) {
604 KillDependentProcess();
605 }
606 return 0;
607 }
608 }
609
610 if (data.isGetGrpcAddr) { // handle get port
611 int ret = CheckGrpcMsgSend();
612 if (data.isKillProcess) {
613 KillDependentProcess();
614 }
615 return ret;
616 }
617
618 if (data.isShowPluginList) { // handle show plugin list
619 std::string content = "";
620 GetCapabilities(content, false);
621 if (data.isKillProcess) {
622 KillDependentProcess();
623 }
624 return 0;
625 }
626
627 if (config.empty()) { // normal case
628 if (data.isKillProcess) {
629 KillDependentProcess();
630 return 1;
631 }
632 if (!data.isStartProcess) {
633 printf("config file argument must sepcified!\n");
634 }
635 return 1;
636 }
637 // do capture work
638 if (DoCapture(config, data.traceKeepSecond, data.outputFile)) {
639 printf("DONE\n");
640 }
641
642 if (data.isKillProcess) {
643 KillDependentProcess();
644 }
645 return 0;
646 }
647