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