• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 <gtest/gtest.h>
17 #include <csignal>
18 #include <map>
19 #include <securec.h>
20 #include <string>
21 #include <thread>
22 #include <unistd.h>
23 #include <vector>
24 #include <sys/prctl.h>
25 
26 #include "dfx_define.h"
27 #include "dfx_signal_local_handler.h"
28 #include "dfx_signal_handler.h"
29 #include "dfx_test_util.h"
30 
31 using namespace testing;
32 using namespace testing::ext;
33 using namespace std;
34 
35 namespace OHOS {
36 namespace HiviewDFX {
37 class SignalHandlerTest : public testing::Test {
38 public:
39     static void SetUpTestCase();
40     static void TearDownTestCase();
41     void SetUp();
42     void TearDown();
43 };
44 
SetUpTestCase()45 void SignalHandlerTest::SetUpTestCase()
46 {}
47 
TearDownTestCase()48 void SignalHandlerTest::TearDownTestCase()
49 {}
50 
SetUp()51 void SignalHandlerTest::SetUp()
52 {}
53 
TearDown()54 void SignalHandlerTest::TearDown()
55 {}
56 
CheckLocalCrashKeyWords(const string & filePath,pid_t pid,int sig)57 static bool CheckLocalCrashKeyWords(const string& filePath, pid_t pid, int sig)
58 {
59     if (filePath.empty() || pid <= 0) {
60         return false;
61     }
62     map<int, string> sigKey = {
63         { SIGILL, string("Signal(4)") },
64         { SIGABRT, string("Signal(6)") },
65         { SIGBUS, string("Signal(7)") },
66         { SIGSEGV, string("Signal(11)") },
67     };
68     string sigKeyword = "";
69     map<int, string>::iterator iter = sigKey.find(sig);
70     if (iter != sigKey.end()) {
71         sigKeyword = iter->second;
72     }
73 #ifdef __aarch64__
74     string keywords[] = {
75         "Pid:" + to_string(pid), "Uid:", "name:./test_signalhandler",
76         sigKeyword, "Tid:", "fp", "x0:", "test_signalhandler"
77     };
78 #else
79     string keywords[] = {
80         "Pid:" + to_string(pid), "Uid:", "name:./test_signalhandler",
81         sigKeyword, "Tid:", "#00", "test_signalhandler"
82     };
83 #endif
84 
85     int length = sizeof(keywords) / sizeof(keywords[0]);
86     int minRegIdx = -1;
87     return CheckKeyWords(filePath, keywords, length, minRegIdx) == length;
88 }
89 
CheckThreadCrashKeyWords(const string & filePath,pid_t pid,int sig)90 static bool CheckThreadCrashKeyWords(const string& filePath, pid_t pid, int sig)
91 {
92     if (filePath.empty() || pid <= 0) {
93         return false;
94     }
95     map<int, string> sigKey = {
96         { SIGILL, string("SIGILL") },
97         { SIGBUS, string("SIGBUS") },
98         { SIGSEGV, string("SIGSEGV") },
99     };
100     string sigKeyword = "";
101     map<int, string>::iterator iter = sigKey.find(sig);
102     if (iter != sigKey.end()) {
103         sigKeyword = iter->second;
104     }
105     string keywords[] = {
106         "Pid:" + to_string(pid), "Uid:", "name:./test_signalhandler", sigKeyword, "LastFatalMessage:",
107         "Tid:", "#00", "Registers:", "FaultStack:", "Maps:", "test_signalhandler"
108     };
109     int length = sizeof(keywords) / sizeof(keywords[0]);
110     int minRegIdx = -1;
111     return CheckKeyWords(filePath, keywords, length, minRegIdx) == length;
112 }
CheckCrashKeyWords(const string & filePath,pid_t pid,int sig)113 static bool CheckCrashKeyWords(const string& filePath, pid_t pid, int sig)
114 {
115     if (filePath.empty() || pid <= 0) {
116         return false;
117     }
118     map<int, string> sigKey = {
119         { SIGILL, string("SIGILL") },
120         { SIGBUS, string("SIGBUS") },
121         { SIGSEGV, string("SIGSEGV") },
122         { SIGABRT, string("SIGABRT") },
123         { SIGFPE, string("SIGFPE") },
124         { SIGSTKFLT, string("SIGSTKFLT") },
125         { SIGSYS, string("SIGSYS") },
126         { SIGTRAP, string("SIGTRAP") },
127     };
128     string sigKeyword = "";
129     map<int, string>::iterator iter = sigKey.find(sig);
130     if (iter != sigKey.end()) {
131         sigKeyword = iter->second;
132     }
133     string keywords[] = {
134         "Pid:" + to_string(pid), "Uid:", "name:./test_signalhandler", sigKeyword,
135         "Tid:", "#00", "Registers:", "FaultStack:", "Maps:", "test_signalhandler"
136     };
137     int length = sizeof(keywords) / sizeof(keywords[0]);
138     int minRegIdx = -1;
139     return CheckKeyWords(filePath, keywords, length, minRegIdx) == length;
140 }
141 
ThreadInfo(char * buf,size_t len,void * context)142 void ThreadInfo(char* buf, size_t len, void* context __attribute__((unused)))
143 {
144     char mes[] = "this is cash information of test thread";
145     (void)memcpy_s(buf, len, mes, sizeof(mes));
146 }
147 
TestThread(int threadId,int sig)148 int TestThread(int threadId, int sig)
149 {
150     std::string subThreadName = "SubTestThread" + to_string(threadId);
151     prctl(PR_SET_NAME, subThreadName.c_str());
152     SetThreadInfoCallback(ThreadInfo);
153     int cashThreadId = 2;
154     if (threadId == cashThreadId) {
155         GTEST_LOG_(INFO) << subThreadName << " is ready to raise signo(" << sig <<")";
156         raise(sig);
157     }
158     return 0;
159 }
160 
161 /**
162  * @tc.name: LocalHandlerTest001
163  * @tc.desc: test crashlocalhandler signo(SIGILL)
164  * @tc.type: FUNC
165  */
166 HWTEST_F(SignalHandlerTest, LocalHandlerTest001, TestSize.Level2)
167 {
168     GTEST_LOG_(INFO) << "LocalHandlerTest001: start.";
169     pid_t pid = fork();
170     if (pid < 0) {
171         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
172     } else if (pid == 0) {
173         DFX_InstallLocalSignalHandler();
174         sleep(1);
175     } else {
176         usleep(10000); // 10000 : sleep 10ms
177         GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")";
178         kill(pid, SIGILL);
179         sleep(2); // 2 : wait for cppcrash generating
180         bool ret = CheckLocalCrashKeyWords(GetCppCrashFileName(pid), pid, SIGILL);
181         ASSERT_TRUE(ret);
182     }
183     GTEST_LOG_(INFO) << "LocalHandlerTest001: end.";
184 }
185 
186 /**
187  * @tc.name: LocalHandlerTest002
188  * @tc.desc: test crashlocalhandler signo(SIGABRT)
189  * @tc.type: FUNC
190  */
191 HWTEST_F(SignalHandlerTest, LocalHandlerTest002, TestSize.Level2)
192 {
193     GTEST_LOG_(INFO) << "LocalHandlerTest002: start.";
194     pid_t pid = fork();
195     if (pid < 0) {
196         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
197     } else if (pid == 0) {
198         DFX_InstallLocalSignalHandler();
199         sleep(1);
200     } else {
201         usleep(10000); // 10000 : sleep 10ms
202         GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")";
203         kill(pid, SIGABRT);
204         sleep(2); // 2 : wait for cppcrash generating
205         bool ret = CheckLocalCrashKeyWords(GetCppCrashFileName(pid), pid, SIGABRT);
206         ASSERT_TRUE(ret);
207     }
208     GTEST_LOG_(INFO) << "LocalHandlerTest002: end.";
209 }
210 
211 /**
212  * @tc.name: LocalHandlerTest003
213  * @tc.desc: test crashlocalhandler signo(SIGBUS)
214  * @tc.type: FUNC
215  */
216 HWTEST_F(SignalHandlerTest, LocalHandlerTest003, TestSize.Level2)
217 {
218     GTEST_LOG_(INFO) << "LocalHandlerTest003: start.";
219     pid_t pid = fork();
220     if (pid < 0) {
221         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
222     } else if (pid == 0) {
223         DFX_InstallLocalSignalHandler();
224         sleep(1);
225     } else {
226         usleep(10000); // 10000 : sleep 10ms
227         GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")";
228         kill(pid, SIGBUS);
229         sleep(2); // 2 : wait for cppcrash generating
230         bool ret = CheckLocalCrashKeyWords(GetCppCrashFileName(pid), pid, SIGBUS);
231         ASSERT_TRUE(ret);
232     }
233     GTEST_LOG_(INFO) << "LocalHandlerTest003: end.";
234 }
235 
236 /**
237  * @tc.name: LocalHandlerTest004
238  * @tc.desc: test crashlocalhandler signo(SIGSEGV)
239  * @tc.type: FUNC
240  */
241 HWTEST_F(SignalHandlerTest, LocalHandlerTest004, TestSize.Level2)
242 {
243     GTEST_LOG_(INFO) << "LocalHandlerTest004: start.";
244     pid_t pid = fork();
245     if (pid < 0) {
246         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
247     } else if (pid == 0) {
248         DFX_InstallLocalSignalHandler();
249         sleep(1);
250     } else {
251         usleep(10000); // 10000 : sleep 10ms
252         GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")";
253         kill(pid, SIGSEGV);
254         sleep(2); // 2 : wait for cppcrash generating
255         bool ret = CheckLocalCrashKeyWords(GetCppCrashFileName(pid), pid, SIGSEGV);
256         ASSERT_TRUE(ret);
257     }
258     GTEST_LOG_(INFO) << "LocalHandlerTest004: end.";
259 }
260 
261 /**
262  * @tc.name: LocalHandlerTest005
263  * @tc.desc: test crashlocalhandler signo(SIGSEGV) by execl
264  * @tc.type: FUNC
265  */
266 HWTEST_F(SignalHandlerTest, LocalHandlerTest005, TestSize.Level2)
267 {
268     GTEST_LOG_(INFO) << "LocalHandlerTest005: start.";
269     pid_t pid = fork();
270     if (pid < 0) {
271         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
272     } else if (pid == 0) {
273         DFX_InstallLocalSignalHandler();
274         sleep(1);
275         raise(SIGSEGV);
276     } else {
277         usleep(10000); // 10000 : sleep 10ms
278         GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to wait process(" << pid << ")";
279         sleep(2); // 2 : wait for cppcrash generating
280         bool ret = CheckLocalCrashKeyWords(GetCppCrashFileName(pid), pid, SIGSEGV);
281         ASSERT_TRUE(ret);
282     }
283     GTEST_LOG_(INFO) << "LocalHandlerTest005: end.";
284 }
285 
286 /**
287  * @tc.name: SignalHandlerTest001
288  * @tc.desc: test thread cash SignalHandler signo(SIGILL)
289  * @tc.type: FUNC
290  */
291 HWTEST_F(SignalHandlerTest, SignalHandlerTest001, TestSize.Level2)
292 {
293     GTEST_LOG_(INFO) << "SignalHandlerTest001: start.";
294     pid_t pid = fork();
295     if (pid < 0) {
296         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
297     } else if (pid == 0) {
298         SetThreadInfoCallback(ThreadInfo);
299         sleep(1);
300     } else {
301         usleep(10000); // 10000 : sleep 10ms
302         GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")";
303         kill(pid, SIGILL);
304         sleep(2); // 2 : wait for cppcrash generating
305         bool ret = CheckThreadCrashKeyWords(GetCppCrashFileName(pid), pid, SIGILL);
306         ASSERT_TRUE(ret);
307     }
308     GTEST_LOG_(INFO) << "SignalHandlerTest001: end.";
309 }
310 
311 /**
312  * @tc.name: SignalHandlerTest002
313  * @tc.desc: test thread cash SignalHandler signo(SIGBUS)
314  * @tc.type: FUNC
315  */
316 HWTEST_F(SignalHandlerTest, SignalHandlerTest002, TestSize.Level2)
317 {
318     GTEST_LOG_(INFO) << "SignalHandlerTest002: start.";
319     pid_t pid = fork();
320     if (pid < 0) {
321         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
322     } else if (pid == 0) {
323         SetThreadInfoCallback(ThreadInfo);
324         sleep(1);
325     } else {
326         usleep(10000); // 10000 : sleep 10ms
327         GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")";
328         kill(pid, SIGBUS);
329         sleep(2); // 2 : wait for cppcrash generating
330         bool ret = CheckThreadCrashKeyWords(GetCppCrashFileName(pid), pid, SIGBUS);
331         ASSERT_TRUE(ret);
332     }
333     GTEST_LOG_(INFO) << "SignalHandlerTest002: end.";
334 }
335 
336 /**
337  * @tc.name: SignalHandlerTest003
338  * @tc.desc: test thread cash SignalHandler signo(SIGSEGV)
339  * @tc.type: FUNC
340  */
341 HWTEST_F(SignalHandlerTest, SignalHandlerTest003, TestSize.Level2)
342 {
343     GTEST_LOG_(INFO) << "SignalHandlerTest003: start.";
344     pid_t pid = fork();
345     if (pid < 0) {
346         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
347     } else if (pid == 0) {
348         SetThreadInfoCallback(ThreadInfo);
349         sleep(1);
350     } else {
351         usleep(10000); // 10000 : sleep 10ms
352         GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")";
353         kill(pid, SIGSEGV);
354         sleep(2); // 2 : wait for cppcrash generating
355         bool ret = CheckThreadCrashKeyWords(GetCppCrashFileName(pid), pid, SIGSEGV);
356         ASSERT_TRUE(ret);
357     }
358     GTEST_LOG_(INFO) << "SignalHandlerTest003: end.";
359 }
360 
361 /**
362  * @tc.name: SignalHandlerTest004
363  * @tc.desc: test thread crash SignalHandler in multi-thread situation signo(SIGILL)
364  * @tc.type: FUNC
365  */
366 HWTEST_F(SignalHandlerTest, SignalHandlerTest004, TestSize.Level2)
367 {
368     GTEST_LOG_(INFO) << "SignalHandlerTest004: start.";
369     pid_t pid = fork();
370     if (pid < 0) {
371         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
372     } else if (pid == 0) {
373         std::thread (TestThread, 1, SIGILL).join(); // 1 : first thread
374         std::thread (TestThread, 2, SIGILL).join(); // 2 : second thread
375     } else {
376         sleep(2); // 2 : wait for cppcrash generating
377         bool ret = CheckThreadCrashKeyWords(GetCppCrashFileName(pid), pid, SIGILL);
378         ASSERT_TRUE(ret);
379     }
380     GTEST_LOG_(INFO) << "SignalHandlerTest004: end.";
381 }
382 
383 /**
384  * @tc.name: SignalHandlerTest005
385  * @tc.desc: test thread crash SignalHandler in multi-thread situation signo(SIGBUS)
386  * @tc.type: FUNC
387  */
388 HWTEST_F(SignalHandlerTest, SignalHandlerTest005, TestSize.Level2)
389 {
390     GTEST_LOG_(INFO) << "SignalHandlerTest005: start.";
391     pid_t pid = fork();
392     if (pid < 0) {
393         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
394     } else if (pid == 0) {
395         std::thread (TestThread, 1, SIGBUS).join(); // 1 : first thread
396         std::thread (TestThread, 2, SIGBUS).join(); // 2 : second thread
397     } else {
398         sleep(2); // 2 : wait for cppcrash generating
399         bool ret = CheckThreadCrashKeyWords(GetCppCrashFileName(pid), pid, SIGBUS);
400         ASSERT_TRUE(ret);
401     }
402     GTEST_LOG_(INFO) << "SignalHandlerTest005: end.";
403 }
404 
405 /**
406  * @tc.name: SignalHandlerTest006
407  * @tc.desc: test thread crash SignalHandler in multi-thread situation signo(SIGSEGV)
408  * @tc.type: FUNC
409  */
410 HWTEST_F(SignalHandlerTest, SignalHandlerTest006, TestSize.Level2)
411 {
412     GTEST_LOG_(INFO) << "SignalHandlerTest006: start.";
413     pid_t pid = fork();
414     if (pid < 0) {
415         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
416     } else if (pid == 0) {
417         std::thread (TestThread, 1, SIGSEGV).join(); // 1 : first thread
418         std::thread (TestThread, 2, SIGSEGV).join(); // 2 : second thread
419     } else {
420         sleep(2); // 2 : wait for cppcrash generating
421         bool ret = CheckThreadCrashKeyWords(GetCppCrashFileName(pid), pid, SIGSEGV);
422         ASSERT_TRUE(ret);
423     }
424     GTEST_LOG_(INFO) << "SignalHandlerTest006: end.";
425 }
426 
427 /**
428  * @tc.name: SignalHandlerTest007
429  * @tc.desc: test DFX_InstallSignalHandler interface
430  * @tc.type: FUNC
431  */
432 HWTEST_F(SignalHandlerTest, SignalHandlerTest007, TestSize.Level2)
433 {
434     GTEST_LOG_(INFO) << "SignalHandlerTest007: start.";
435     int interestedSignalList[] = {
436         SIGABRT, SIGBUS, SIGFPE,
437         SIGSEGV, SIGSTKFLT, SIGSYS, SIGTRAP
438     };
439     for (int sig : interestedSignalList) {
440         pid_t pid = fork();
441         if (pid < 0) {
442             GTEST_LOG_(ERROR) << "Failed to fork new test process.";
443         } else if (pid == 0) {
444             DFX_InstallSignalHandler();
445             sleep(1);
446         } else {
447             usleep(10000); // 10000 : sleep 10ms
448             GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill << process(" << pid << ")";
449             GTEST_LOG_(INFO) << "signal:" << sig;
450             kill(pid, sig);
451             sleep(2); // 2 : wait for cppcrash generating
452             bool ret = CheckCrashKeyWords(GetCppCrashFileName(pid), pid, sig);
453             ASSERT_TRUE(ret);
454         }
455     }
456     GTEST_LOG_(INFO) << "SignalHandlerTest007: end.";
457 }
458 } // namespace HiviewDFX
459 } // namepsace OHOS
460