1 /*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
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 <cstdio>
17 #include <cstdlib>
18 #include <securec.h>
19 #include <string>
20 #include <unistd.h>
21 #include <getopt.h>
22 #include "dfx_define.h"
23 #include "dfx_log.h"
24 #include "dump_catcher.h"
25 #include "faultloggerd_client.h"
26
27 #if defined(DEBUG_CRASH_LOCAL_HANDLER)
28 #include "dfx_signal_local_handler.h"
29 #endif
30
31 static const std::string DUMP_STACK_TAG_USAGE = "Usage:";
32 static const std::string DUMP_STACK_TAG_FAILED = "Failed:";
33 static constexpr int WAIT_GET_KERNEL_STACK_TIMEOUT = 1000; // 1000 : time out 1000 ms
34 static constexpr int SAVE_CORE_DUMP_TIMEOUT = 10000; // time out 10000 ms
35
PrintCommandHelp()36 static void PrintCommandHelp()
37 {
38 printf("%s\n", DUMP_STACK_TAG_USAGE.c_str());
39 printf("-p pid -t tid dump the stacktrace of the thread with given tid.\n");
40 printf("-p pid dump the stacktrace of all the threads with given pid.\n");
41 printf("-T timeout(ms) dump in the timeout.\n");
42 }
43
PrintCommandFailed()44 static void PrintCommandFailed()
45 {
46 printf("%s\npid and tid must > 0 and timeout must > 1000.\n", DUMP_STACK_TAG_FAILED.c_str());
47 }
48
49
GetIdFromArgs(char * optarg,int32_t & id)50 static int GetIdFromArgs(char *optarg, int32_t &id)
51 {
52 int ret = 0;
53
54 if (atoi(optarg) > 0) {
55 ret = 1;
56 id = atoi(optarg);
57 } else {
58 ret = -1;
59 PrintCommandFailed();
60 }
61
62 return ret;
63 }
64
ExecuteCoredumpCmd(std::string subCmd,char * pidChar)65 static int ExecuteCoredumpCmd(std::string subCmd, char* pidChar)
66 {
67 if (atoi(pidChar) <= 0) {
68 printf("pid error, input should like dumpcatcher -c save/cancel pid\n");
69 return -1;
70 }
71 pid_t pid = atoi(pidChar);
72 printf("cmd is -c %s %d \n", subCmd.c_str(), pid);
73 if (subCmd == "save") {
74 SaveCoredumpToFileTimeout(pid, SAVE_CORE_DUMP_TIMEOUT);
75 return 0;
76 } else if (subCmd == "cancel") {
77 CancelCoredump(pid);
78 return 0;
79 } else {
80 printf("input error coredump cmd!\n");
81 return -1;
82 }
83 }
84
ParseParamters(int argc,char * argv[],int32_t & pid,int32_t & tid,int & timeout)85 static int ParseParamters(int argc, char *argv[], int32_t &pid, int32_t &tid, int &timeout)
86 {
87 int ret = 0;
88 if (argc <= 1) {
89 return ret;
90 }
91 DFXLOGD("[%{public}d]: argc: %{public}d, argv1: %{public}s", __LINE__, argc, argv[1]);
92
93 int optRet;
94 const char *optString = "p:t:c:T:";
95 while ((optRet = getopt(argc, argv, optString)) != -1) {
96 if (optarg == nullptr) {
97 continue;
98 }
99 switch (optRet) {
100 case 'p':
101 ret = GetIdFromArgs(optarg, pid);
102 break;
103 case 't':
104 ret = GetIdFromArgs(optarg, tid);
105 break;
106 case 'c':
107 if (optind >= argc) {
108 printf("input error, input should like dumpcatcher -c save/cancel pid\n");
109 return 0;
110 }
111 ExecuteCoredumpCmd(optarg, argv[optind]);
112 return 0;
113 case 'T':
114 if (atoi(optarg) > WAIT_GET_KERNEL_STACK_TIMEOUT) {
115 timeout = atoi(optarg);
116 } else {
117 ret = -1;
118 PrintCommandFailed();
119 }
120 break;
121 default:
122 ret = 0;
123 break;
124 }
125 }
126
127 if (ret == 0) {
128 PrintCommandHelp();
129 }
130 return ret;
131 }
132
main(int argc,char * argv[])133 int main(int argc, char *argv[])
134 {
135 #if defined(DEBUG_CRASH_LOCAL_HANDLER)
136 DFX_InstallLocalSignalHandler();
137 #endif
138
139 int32_t pid = 0;
140 int32_t tid = 0;
141 int timeout = 3000;
142
143 alarm(DUMPCATCHER_TIMEOUT);
144 setsid();
145
146 if (ParseParamters(argc, argv, pid, tid, timeout) <= 0) {
147 return 0;
148 }
149
150 DFXLOGD("pid: %{public}d, tid: %{public}d, timeout: %{public}d", pid, tid, timeout);
151 OHOS::HiviewDFX::DumpCatcher::GetInstance().Dump(pid, tid, timeout);
152 return 0;
153 }
154