• 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 <malloc.h>
20 #include <fcntl.h>
21 #include <securec.h>
22 #include <string>
23 #include <thread>
24 #include <unistd.h>
25 #include <vector>
26 #include <sys/prctl.h>
27 #include <sys/syscall.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <thread>
32 
33 #include "dfx_define.h"
34 #include "dfx_signal_handler.h"
35 #include "dfx_signalhandler_exception.h"
36 #include "dfx_test_util.h"
37 #include "info/fatal_message.h"
38 
39 using namespace testing;
40 using namespace testing::ext;
41 using namespace std;
42 
43 namespace OHOS {
44 namespace HiviewDFX {
45 class SignalHandlerTest : public testing::Test {
46 public:
47     static void SetUpTestCase();
48     static void TearDownTestCase();
49     void SetUp();
50     void TearDown();
51 };
52 
SetUpTestCase()53 void SignalHandlerTest::SetUpTestCase()
54 {}
55 
TearDownTestCase()56 void SignalHandlerTest::TearDownTestCase()
57 {}
58 
SetUp()59 void SignalHandlerTest::SetUp()
60 {}
61 
TearDown()62 void SignalHandlerTest::TearDown()
63 {}
64 
65 extern "C" void SetThreadInfoCallback(ThreadInfoCallBack func) __attribute__((weak));
66 extern "C" void DFX_InstallSignalHandler(void) __attribute__((weak));
67 extern "C" void SetAsyncStackCallbackFunc(void* func) __attribute__((weak));
68 extern "C" int DFX_SetAppRunningUniqueId(const char* appRunningId, size_t len) __attribute__((weak));
CheckCallbackCrashKeyWords(const string & filePath,pid_t pid,int sig)69 static bool CheckCallbackCrashKeyWords(const string& filePath, pid_t pid, int sig)
70 {
71     if (filePath.empty() || pid <= 0) {
72         return false;
73     }
74     map<int, string> sigKey = {
75         { SIGILL, string("SIGILL") },
76         { SIGBUS, string("SIGBUS") },
77         { SIGSEGV, string("SIGSEGV") },
78     };
79     string sigKeyword = "";
80     map<int, string>::iterator iter = sigKey.find(sig);
81     if (iter != sigKey.end()) {
82         sigKeyword = iter->second;
83     }
84     string keywords[] = {
85         "Pid:" + to_string(pid), "Uid:", "name:./test_signalhandler", sigKeyword,
86         "Tid:", "#00", "Registers:", "FaultStack:", "Maps:", "test_signalhandler"
87     };
88     int length = sizeof(keywords) / sizeof(keywords[0]);
89     int minRegIdx = -1;
90     return CheckKeyWords(filePath, keywords, length, minRegIdx) == length;
91 }
CheckCrashKeyWords(const string & filePath,pid_t pid,int sig)92 static bool CheckCrashKeyWords(const string& filePath, pid_t pid, int sig)
93 {
94     if (filePath.empty() || pid <= 0) {
95         return false;
96     }
97     map<int, string> sigKey = {
98         { SIGILL, string("SIGILL") },
99         { SIGBUS, string("SIGBUS") },
100         { SIGSEGV, string("SIGSEGV") },
101         { SIGABRT, string("SIGABRT") },
102         { SIGFPE, string("SIGFPE") },
103         { SIGSTKFLT, string("SIGSTKFLT") },
104         { SIGSYS, string("SIGSYS") },
105         { SIGTRAP, string("SIGTRAP") },
106     };
107     string sigKeyword = "";
108     map<int, string>::iterator iter = sigKey.find(sig);
109     if (iter != sigKey.end()) {
110         sigKeyword = iter->second;
111     }
112     string keywords[] = {
113         "Pid:" + to_string(pid), "Uid:", "name:./test_signalhandler", sigKeyword,
114         "Tid:", "#00", "Registers:", "FaultStack:", "Maps:", "test_signalhandler"
115     };
116     int length = sizeof(keywords) / sizeof(keywords[0]);
117     int minRegIdx = -1;
118     return CheckKeyWords(filePath, keywords, length, minRegIdx) == length;
119 }
120 
CheckDebugSignalFaultlog(const string & filePath,pid_t pid,int siCode)121 static bool CheckDebugSignalFaultlog(const string& filePath, pid_t pid, int siCode)
122 {
123     if (filePath.empty() || pid <= 0) {
124         return false;
125     }
126     std::list<LineRule> rules;
127     rules.push_back(LineRule(R"(^Build info:.*$)"));
128     rules.push_back(LineRule(R"(^Process name:./test_signalhandler$)"));
129     rules.push_back(LineRule(R"(^Process life time:.*$)"));
130     rules.push_back(LineRule("^Pid:" + to_string(pid) + "$"));
131     rules.push_back(LineRule(R"(^Uid:\d+$)"));
132     rules.push_back(LineRule(R"(^Reason:Signal:DEBUG SIGNAL\((FDSAN|JEMALLOC|BADFD)\).*$)"));
133     rules.push_back(LineRule(R"(^#\d+ pc [0-9a-f]+ .*$)", 5)); // match 5 times
134     rules.push_back(LineRule(R"(^Registers:$)"));
135     rules.push_back(LineRule(R"(^FaultStack:$)"));
136     rules.push_back(LineRule(R"(^Maps:$)"));
137     if (siCode != SIGLEAK_STACK_BADFD) {
138         rules.push_back(LineRule(R"(^LastFatalMessage:.*$)"));
139     }
140     if (siCode != SIGLEAK_STACK_JEMALLOC) {
141         rules.push_back(LineRule(R"(^OpenFiles:$)"));
142         rules.push_back(LineRule(R"(^\d+->.*$)", 5)); // match 5 times
143     }
144     return CheckLineMatch(filePath, rules);
145 }
146 
ThreadInfo(char * buf,size_t len,void * context)147 void ThreadInfo(char* buf, size_t len, void* context __attribute__((unused)))
148 {
149     char mes[] = "this is extraCrashInfo of test thread";
150     if (memcpy_s(buf, len, mes, sizeof(mes)) != 0) {
151         GTEST_LOG_(INFO) << "Failed to set thread info";
152     }
153 }
154 
TestThread(int threadId,int sig)155 int TestThread(int threadId, int sig)
156 {
157     std::string subThreadName = "SubTestThread" + to_string(threadId);
158     prctl(PR_SET_NAME, subThreadName.c_str());
159     if (SetThreadInfoCallback != nullptr) {
160         SetThreadInfoCallback(ThreadInfo);
161     }
162     int cashThreadId = 2;
163     if (threadId == cashThreadId) {
164         GTEST_LOG_(INFO) << subThreadName << " is ready to raise signo(" << sig <<")";
165         raise(sig);
166     }
167     return 0;
168 }
169 
SaveDebugMessage(int siCode,int64_t diffMs,const char * msg)170 static void SaveDebugMessage(int siCode, int64_t diffMs, const char *msg)
171 {
172     const int signo = 42; // Custom stack capture signal and leak reuse
173     siginfo_t info;
174     info.si_signo = signo;
175     info.si_code = siCode;
176 
177     debug_msg_t debug_message = {0, NULL};
178     if (msg != nullptr) {
179         const int numberOneThousand = 1000; // 1000 : second to millisecond convert ratio
180         const int numberOneMillion = 1000000; // 1000000 : nanosecond to millisecond convert ratio
181         struct timespec ts;
182         (void)clock_gettime(CLOCK_REALTIME, &ts);
183 
184         uint64_t timestamp = static_cast<uint64_t>(ts.tv_sec) * numberOneThousand +
185             static_cast<uint64_t>(ts.tv_sec) / numberOneMillion;
186         if (diffMs < 0  && timestamp < -diffMs) {
187             timestamp = 0;
188         } else if (UINT64_MAX - timestamp < diffMs) {
189             timestamp = UINT64_MAX;
190         } else {
191             timestamp += diffMs;
192         }
193 
194         debug_message.timestamp = timestamp;
195         debug_message.msg = msg;
196 
197         info.si_value.sival_ptr = &debug_message;
198     }
199 
200     if (syscall(SYS_rt_tgsigqueueinfo, getpid(), syscall(SYS_gettid), signo, &info) == -1) {
201         GTEST_LOG_(ERROR) << "send failed errno=" << errno;
202     }
203 }
204 
SendSigTestDebugSignal(int siCode)205 static bool SendSigTestDebugSignal(int siCode)
206 {
207     pid_t pid = fork();
208     if (pid < 0) {
209         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
210         return false;
211     }
212 
213     if (pid == 0) {
214         if (DFX_InstallSignalHandler != nullptr) {
215             DFX_InstallSignalHandler();
216         }
217         SaveDebugMessage(siCode, 0, "test123");
218         sleep(5); // 5: wait for stacktrace generating
219         _exit(0);
220     }
221 
222     sleep(2); // 2 : wait for cppcrash generating
223     return CheckDebugSignalFaultlog(GetDumpLogFileName("stacktrace", pid, TEMP_DIR), pid, siCode);
224 }
225 
TestFdsan()226 static void TestFdsan()
227 {
228     fdsan_set_error_level(FDSAN_ERROR_LEVEL_WARN_ONCE);
229     FILE *fp = fopen("/dev/null", "w+");
230     if (fp == nullptr) {
231         GTEST_LOG_(ERROR) << "fp is nullptr";
232         return;
233     }
234     close(fileno(fp));
235     uint64_t tag = fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, reinterpret_cast<uint64_t>(fp));
236     fdsan_exchange_owner_tag(fileno(fp), tag, 0);
237     return;
238 }
239 
TestBadfdThread(int maxCnt)240 void TestBadfdThread(int maxCnt)
241 {
242     for (int i = 0; i < maxCnt; i++) {
243         sleep(2); // Delay 2s waiting for the next triggerable cycle
244         SaveDebugMessage(SIGLEAK_STACK_BADFD, 0, nullptr);
245     }
246 }
247 
248 /**
249  * @tc.name: SignalHandlerTest001
250  * @tc.desc: test thread cash SignalHandler signo(SIGILL)
251  * @tc.type: FUNC
252  */
253 HWTEST_F(SignalHandlerTest, SignalHandlerTest001, TestSize.Level2)
254 {
255     GTEST_LOG_(INFO) << "SignalHandlerTest001: start.";
256     pid_t pid = fork();
257     if (pid < 0) {
258         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
259     } else if (pid == 0) {
260         if (SetThreadInfoCallback != nullptr) {
261             SetThreadInfoCallback(ThreadInfo);
262         }
263         sleep(1);
264     } else {
265         usleep(10000); // 10000 : sleep 10ms
266         GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")";
267         kill(pid, SIGILL);
268         auto filename = WaitCreateCrashFile("cppcrash", pid);
269         bool ret = CheckCallbackCrashKeyWords(filename, pid, SIGILL);
270         ASSERT_TRUE(ret);
271     }
272     GTEST_LOG_(INFO) << "SignalHandlerTest001: end.";
273 }
274 
275 /**
276  * @tc.name: SignalHandlerTest002
277  * @tc.desc: test thread cash SignalHandler signo(SIGBUS)
278  * @tc.type: FUNC
279  */
280 HWTEST_F(SignalHandlerTest, SignalHandlerTest002, TestSize.Level2)
281 {
282     GTEST_LOG_(INFO) << "SignalHandlerTest002: start.";
283     pid_t pid = fork();
284     if (pid < 0) {
285         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
286     } else if (pid == 0) {
287         if (SetThreadInfoCallback != nullptr) {
288             SetThreadInfoCallback(ThreadInfo);
289         }
290         sleep(1);
291     } else {
292         usleep(10000); // 10000 : sleep 10ms
293         GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")";
294         kill(pid, SIGBUS);
295         auto filename = WaitCreateCrashFile("cppcrash", pid);
296         bool ret = CheckCallbackCrashKeyWords(filename, pid, SIGBUS);
297         ASSERT_TRUE(ret);
298     }
299     GTEST_LOG_(INFO) << "SignalHandlerTest002: end.";
300 }
301 
302 /**
303  * @tc.name: SignalHandlerTest003
304  * @tc.desc: test thread cash SignalHandler signo(SIGSEGV)
305  * @tc.type: FUNC
306  */
307 HWTEST_F(SignalHandlerTest, SignalHandlerTest003, TestSize.Level2)
308 {
309     GTEST_LOG_(INFO) << "SignalHandlerTest003: start.";
310     pid_t pid = fork();
311     if (pid < 0) {
312         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
313     } else if (pid == 0) {
314         if (SetThreadInfoCallback != nullptr) {
315             SetThreadInfoCallback(ThreadInfo);
316         }
317         sleep(1);
318     } else {
319         usleep(10000); // 10000 : sleep 10ms
320         GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")";
321         kill(pid, SIGSEGV);
322         auto filename = WaitCreateCrashFile("cppcrash", pid);
323         bool ret = CheckCallbackCrashKeyWords(filename, pid, SIGSEGV);
324         ASSERT_TRUE(ret);
325     }
326     GTEST_LOG_(INFO) << "SignalHandlerTest003: end.";
327 }
328 
329 /**
330  * @tc.name: SignalHandlerTest004
331  * @tc.desc: test thread crash SignalHandler in multi-thread situation signo(SIGILL)
332  * @tc.type: FUNC
333  */
334 HWTEST_F(SignalHandlerTest, SignalHandlerTest004, TestSize.Level2)
335 {
336     GTEST_LOG_(INFO) << "SignalHandlerTest004: start.";
337     pid_t pid = fork();
338     if (pid < 0) {
339         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
340     } else if (pid == 0) {
341         std::thread (TestThread, 1, SIGILL).join(); // 1 : first thread
342         std::thread (TestThread, 2, SIGILL).join(); // 2 : second thread
343         _exit(0);
344     } else {
345         auto filename = WaitCreateCrashFile("cppcrash", pid);
346         bool ret = CheckCallbackCrashKeyWords(filename, pid, SIGILL);
347         ASSERT_TRUE(ret);
348     }
349     GTEST_LOG_(INFO) << "SignalHandlerTest004: end.";
350 }
351 
352 /**
353  * @tc.name: SignalHandlerTest005
354  * @tc.desc: test thread crash SignalHandler in multi-thread situation signo(SIGBUS)
355  * @tc.type: FUNC
356  */
357 HWTEST_F(SignalHandlerTest, SignalHandlerTest005, TestSize.Level2)
358 {
359     GTEST_LOG_(INFO) << "SignalHandlerTest005: start.";
360     pid_t pid = fork();
361     if (pid < 0) {
362         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
363     } else if (pid == 0) {
364         std::thread (TestThread, 1, SIGBUS).join(); // 1 : first thread
365         std::thread (TestThread, 2, SIGBUS).join(); // 2 : second thread
366         _exit(0);
367     } else {
368         auto filename = WaitCreateCrashFile("cppcrash", pid);
369         bool ret = CheckCallbackCrashKeyWords(filename, pid, SIGBUS);
370         ASSERT_TRUE(ret);
371     }
372     GTEST_LOG_(INFO) << "SignalHandlerTest005: end.";
373 }
374 
375 /**
376  * @tc.name: SignalHandlerTest006
377  * @tc.desc: test thread crash SignalHandler in multi-thread situation signo(SIGSEGV)
378  * @tc.type: FUNC
379  */
380 HWTEST_F(SignalHandlerTest, SignalHandlerTest006, TestSize.Level2)
381 {
382     GTEST_LOG_(INFO) << "SignalHandlerTest006: start.";
383     pid_t pid = fork();
384     if (pid < 0) {
385         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
386     } else if (pid == 0) {
387         std::thread (TestThread, 1, SIGSEGV).join(); // 1 : first thread
388         std::thread (TestThread, 2, SIGSEGV).join(); // 2 : second thread
389         _exit(0);
390     } else {
391         auto filename = WaitCreateCrashFile("cppcrash", pid);
392         bool ret = CheckCallbackCrashKeyWords(filename, pid, SIGSEGV);
393         ASSERT_TRUE(ret);
394     }
395     GTEST_LOG_(INFO) << "SignalHandlerTest006: end.";
396 }
397 
398 /**
399  * @tc.name: SignalHandlerTest007
400  * @tc.desc: test DFX_InstallSignalHandler interface
401  * @tc.type: FUNC
402  */
403 HWTEST_F(SignalHandlerTest, SignalHandlerTest007, TestSize.Level2)
404 {
405     GTEST_LOG_(INFO) << "SignalHandlerTest007: start.";
406     int interestedSignalList[] = {
407         SIGABRT, SIGBUS, SIGFPE,
408         SIGSEGV, SIGSTKFLT, SIGSYS, SIGTRAP
409     };
410     for (int sig : interestedSignalList) {
411         pid_t pid = fork();
412         if (pid < 0) {
413             GTEST_LOG_(ERROR) << "Failed to fork new test process.";
414         } else if (pid == 0) {
415             if (DFX_InstallSignalHandler != nullptr) {
416                 DFX_InstallSignalHandler();
417             }
418             sleep(1);
419         } else {
420             usleep(10000); // 10000 : sleep 10ms
421             GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill << process(" << pid << ")";
422             GTEST_LOG_(INFO) << "signal:" << sig;
423             kill(pid, sig);
424             auto filename = WaitCreateCrashFile("cppcrash", pid);
425             bool ret = CheckCrashKeyWords(filename, pid, sig);
426             ASSERT_TRUE(ret);
427         }
428     }
429     GTEST_LOG_(INFO) << "SignalHandlerTest007: end.";
430 }
431 
TestThread2(int threadId,int sig,int total,bool exitEarly)432 int TestThread2(int threadId, int sig, int total, bool exitEarly)
433 {
434     std::string subThreadName = "SubTestThread" + to_string(threadId);
435     prctl(PR_SET_NAME, subThreadName.c_str());
436     if (SetThreadInfoCallback != nullptr) {
437         SetThreadInfoCallback(ThreadInfo);
438     }
439     if (threadId == total - 1) {
440         GTEST_LOG_(INFO) << subThreadName << " is ready to raise signo(" << sig <<")";
441         raise(sig);
442     }
443 
444     if (!exitEarly) {
445         sleep(total - threadId);
446     }
447     if (SetThreadInfoCallback != nullptr) {
448         SetThreadInfoCallback(ThreadInfo);
449     }
450     return 0;
451 }
452 
453 /**
454  * @tc.name: SignalHandlerTest008
455  * @tc.desc: test add 36 thread info callback and crash thread has no callback
456  * @tc.type: FUNC
457  */
458 HWTEST_F(SignalHandlerTest, SignalHandlerTest008, TestSize.Level2)
459 {
460     GTEST_LOG_(INFO) << "SignalHandlerTest008: start.";
461     pid_t pid = fork();
462     if (pid < 0) {
463         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
464     } else if (pid == 0) {
465         std::vector<std::thread> threads;
466         const int testThreadCount = 36;
467         for (int i = 0; i < testThreadCount; i++) {
468             threads.push_back(std::thread(TestThread2, i, SIGSEGV, testThreadCount, false));
469         }
470 
471         for (auto& thread : threads) {
472             thread.join();
473         }
474         _exit(0);
475     } else {
476         auto file = WaitCreateCrashFile("cppcrash", pid);
477         ASSERT_FALSE(file.empty());
478     }
479     GTEST_LOG_(INFO) << "SignalHandlerTest008: end.";
480 }
481 
482 /**
483  * @tc.name: SignalHandlerTest009
484  * @tc.desc: test add 36 thread info callback and crash thread has the callback
485  * @tc.type: FUNC
486  */
487 HWTEST_F(SignalHandlerTest, SignalHandlerTest009, TestSize.Level2)
488 {
489     GTEST_LOG_(INFO) << "SignalHandlerTest009: start.";
490     pid_t pid = fork();
491     if (pid < 0) {
492         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
493     } else if (pid == 0) {
494         std::vector<std::thread> threads;
495         const int testThreadCount = 36;
496         for (int i = 0; i < testThreadCount; i++) {
497             bool exitEarly = false;
498             if (i % 2 == 0) {
499                 exitEarly =  true;
500             }
501             threads.push_back(std::thread (TestThread2, i, SIGSEGV, testThreadCount, exitEarly));
502         }
503 
504         for (auto& thread : threads) {
505             thread.join();
506         }
507         _exit(0);
508     } else {
509         auto file = WaitCreateCrashFile("cppcrash", pid);
510         ASSERT_FALSE(file.empty());
511     }
512     GTEST_LOG_(INFO) << "SignalHandlerTest009: end.";
513 }
514 
515 /**
516  * @tc.name: SignalHandlerTest010
517  * @tc.desc: test crash when free a invalid address
518  * @tc.type: FUNC
519  */
520 HWTEST_F(SignalHandlerTest, SignalHandlerTest010, TestSize.Level2)
521 {
522     GTEST_LOG_(INFO) << "SignalHandlerTest010: start.";
523     pid_t pid = fork();
524     if (pid < 0) {
525         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
526     } else if (pid == 0) {
527         if (SetThreadInfoCallback != nullptr) {
528             SetThreadInfoCallback(ThreadInfo);
529         }
530         int32_t freeAddr = 0x111;
531         // trigger crash
532         free(reinterpret_cast<void*>(freeAddr));
533         // force crash if not crash in free
534         abort();
535     } else {
536         auto file = WaitCreateCrashFile("cppcrash", pid);
537         ASSERT_FALSE(file.empty());
538     }
539     GTEST_LOG_(INFO) << "SignalHandlerTest010: end.";
540 }
541 
542 /**
543  * @tc.name: SignalHandlerTest011
544  * @tc.desc: test crash when realloc a invalid address
545  * @tc.type: FUNC
546  */
547 HWTEST_F(SignalHandlerTest, SignalHandlerTest011, TestSize.Level2)
548 {
549     GTEST_LOG_(INFO) << "SignalHandlerTest011: start.";
550     pid_t pid = fork();
551     if (pid < 0) {
552         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
553     } else if (pid == 0) {
554         int32_t initAllocSz = 10;
555         int32_t reallocSz = 20;
556         if (SetThreadInfoCallback != nullptr) {
557             SetThreadInfoCallback(ThreadInfo);
558         }
559         // alloc a buffer
560         int8_t* addr = reinterpret_cast<int8_t*>(malloc(initAllocSz));
561         // overwrite the control block
562         int8_t* newAddr = addr - initAllocSz;
563         (void)memset_s(newAddr, initAllocSz, 0, initAllocSz);
564         addr = reinterpret_cast<int8_t*>(realloc(reinterpret_cast<void*>(addr), reallocSz));
565         free(addr);
566         // force crash if not crash in realloc
567         abort();
568     } else {
569         auto file = WaitCreateCrashFile("cppcrash", pid);
570         ASSERT_FALSE(file.empty());
571     }
572     GTEST_LOG_(INFO) << "SignalHandlerTest011: end.";
573 }
574 
575 /**
576  * @tc.name: SignalHandlerTest012
577  * @tc.desc: test crash when realloc a invalid address without threadInfo callback
578  * @tc.type: FUNC
579  */
580 HWTEST_F(SignalHandlerTest, SignalHandlerTest012, TestSize.Level2)
581 {
582     GTEST_LOG_(INFO) << "SignalHandlerTest012: start.";
583     pid_t pid = fork();
584     if (pid < 0) {
585         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
586     } else if (pid == 0) {
587         int32_t initAllocSz = 10;
588         int32_t reallocSz = 20;
589         // alloc a buffer
590         int8_t* addr = reinterpret_cast<int8_t*>(malloc(initAllocSz));
591         // overwrite the control block
592         int8_t* newAddr = addr - initAllocSz;
593         (void)memset_s(newAddr, initAllocSz, 0, initAllocSz);
594         addr = reinterpret_cast<int8_t*>(realloc(reinterpret_cast<void*>(addr), reallocSz));
595         free(addr);
596         // force crash if not crash in realloc
597         abort();
598     } else {
599         auto file = WaitCreateCrashFile("cppcrash", pid);
600         ASSERT_FALSE(file.empty());
601     }
602     GTEST_LOG_(INFO) << "SignalHandlerTest012: end.";
603 }
604 
605 /**
606  * @tc.name: SignalHandlerTest013
607  * @tc.desc: test add 100 thread info callback and do nothing
608  * @tc.type: FUNC
609  */
610 HWTEST_F(SignalHandlerTest, SignalHandlerTest013, TestSize.Level2)
611 {
612     GTEST_LOG_(INFO) << "SignalHandlerTest013: start.";
613     std::vector<std::thread> threads;
614     const int testThreadCount = 100;
615     for (int i = 0; i < testThreadCount - 1; i++) {
616         threads.push_back(std::thread (TestThread2, i, SIGSEGV, testThreadCount, true));
617     }
618 
619     for (auto& thread : threads) {
620         if (thread.joinable()) {
621             thread.join();
622         }
623     }
624     auto file = GetCppCrashFileName(getpid());
625     ASSERT_TRUE(file.empty());
626     GTEST_LOG_(INFO) << "SignalHandlerTest013: end.";
627 }
628 
TestCallbackFunc()629 void TestCallbackFunc()
630 {}
631 
632 /**
633  * @tc.name: SignalHandlerTest015
634  * @tc.desc: test DFX_SetAppRunningUniqueId
635  * @tc.type: FUNC
636  */
637 HWTEST_F(SignalHandlerTest, SignalHandlerTest015, TestSize.Level2)
638 {
639     bool isSuccess = DFX_SetAppRunningUniqueId != nullptr;
640     if (!isSuccess) {
641         ASSERT_FALSE(isSuccess);
642         return;
643     }
644     /**
645      * @tc.steps: step1.
646      *            case: appRunningId == nullptr, len= 0
647      * @tc.expected: ret == -1
648      * */
649     int ret = DFX_SetAppRunningUniqueId(nullptr, 0);
650     ASSERT_EQ(ret, -1);
651 
652     /**
653      * @tc.steps: step2.
654      *            case: appRunningId == nullptr, len= MAX_APP_RUNNING_UNIQUE_ID_LEN
655      * @tc.expected: ret == -1
656      * */
657     ret = DFX_SetAppRunningUniqueId(nullptr, MAX_APP_RUNNING_UNIQUE_ID_LEN);
658     ASSERT_EQ(ret, -1);
659 
660     /**
661      * @tc.steps: step3.
662      *            case: appRunningId != nullptr, len= 0
663      * @tc.expected: ret == 0
664      * */
665     constexpr char testId1[] = "App running unique test id";
666     ret = DFX_SetAppRunningUniqueId(testId1, 0);
667     ASSERT_EQ(ret, 0);
668 
669     /**
670      * @tc.steps: step4.
671      *            case: appRunningId != nullptr, len= strleng(appRunningId)
672      * @tc.expected: ret == 0
673      * */
674     ret = DFX_SetAppRunningUniqueId(testId1, strlen(testId1));
675     ASSERT_EQ(ret, 0);
676 
677     /**
678      * @tc.steps: step5.
679      *            case: appRunningId != nullptr, len= MAX_APP_RUNNING_UNIQUE_ID_LEN + 1
680      * @tc.expected: ret == -1
681      * */
682     constexpr size_t testLen = MAX_APP_RUNNING_UNIQUE_ID_LEN + 1;
683     ret = DFX_SetAppRunningUniqueId(testId1, testLen);
684     ASSERT_EQ(ret, -1);
685 
686     /**
687      * @tc.steps: step6.
688      *            case: appRunningId != nullptr, len= MAX_APP_RUNNING_UNIQUE_ID_LEN
689      * @tc.expected: ret == 0
690      * */
691     constexpr char testId2[MAX_APP_RUNNING_UNIQUE_ID_LEN] = "App running unique test id";
692     ret = DFX_SetAppRunningUniqueId(testId2, MAX_APP_RUNNING_UNIQUE_ID_LEN);
693     ASSERT_EQ(ret, -1);
694 }
695 
696 /**
697  * @tc.name: SignalHandlerTest016
698  * @tc.desc: test ReportException
699  * @tc.type: FUNC
700  */
701 HWTEST_F(SignalHandlerTest, SignalHandlerTest016, TestSize.Level2)
702 {
703     GTEST_LOG_(INFO) << "SignalHandlerTest016: start.";
704     if (SetAsyncStackCallbackFunc != nullptr) {
705         SetAsyncStackCallbackFunc(reinterpret_cast<void*>(TestCallbackFunc));
706     }
707 
708     struct CrashDumpException exception;
709     exception.pid = 1;
710     exception.uid = 1;
711     exception.error = CRASH_SIGNAL_EMASKED;
712     int ret = ReportException(&exception);
713     ASSERT_NE(ret, -1);
714     GTEST_LOG_(INFO) << "SignalHandlerTest016: end.";
715 }
716 
717 /**
718  * @tc.name: SignalHandlerTest017
719  * @tc.desc: send sig SIGLEAK_STACK_FDSAN
720  * @tc.type: FUNC
721  */
722 HWTEST_F(SignalHandlerTest, SignalHandlerTest017, TestSize.Level2)
723 {
724     std::string res = ExecuteCommands("uname");
725     bool linuxKernel = res.find("Linux") != std::string::npos;
726     if (linuxKernel) {
727         ASSERT_TRUE(linuxKernel);
728         return;
729     }
730 
731     bool ret = SendSigTestDebugSignal(SIGLEAK_STACK_FDSAN);
732     ASSERT_TRUE(ret);
733 }
734 
735 /**
736  * @tc.name: SignalHandlerTest018
737  * @tc.desc: send sig SIGLEAK_STACK_JEMALLOC
738  * @tc.type: FUNC
739  */
740 HWTEST_F(SignalHandlerTest, SignalHandlerTest018, TestSize.Level2)
741 {
742     std::string res = ExecuteCommands("uname");
743     bool linuxKernel = res.find("Linux") != std::string::npos;
744     if (linuxKernel) {
745         ASSERT_TRUE(linuxKernel);
746         return;
747     }
748 
749     bool ret = SendSigTestDebugSignal(SIGLEAK_STACK_JEMALLOC);
750     ASSERT_TRUE(ret);
751 }
752 
753 /**
754  * @tc.name: SignalHandlerTest019
755  * @tc.desc: send sig SIGLEAK_STACK_BADFD
756  * @tc.type: FUNC
757  */
758 HWTEST_F(SignalHandlerTest, SignalHandlerTest019, TestSize.Level2)
759 {
760     std::string res = ExecuteCommands("uname");
761     bool linuxKernel = res.find("Linux") != std::string::npos;
762     if (linuxKernel) {
763         ASSERT_TRUE(linuxKernel);
764         return;
765     }
766 
767     bool ret = SendSigTestDebugSignal(SIGLEAK_STACK_BADFD);
768     ASSERT_TRUE(ret);
769 }
770 
771 /**
772  * @tc.name: SignalHandlerTest020
773  * @tc.desc: test DEBUG SIGNAL time out, BADFD no timeout
774  * @tc.type: FUNC
775  */
776 HWTEST_F(SignalHandlerTest, SignalHandlerTest020, TestSize.Level2)
777 {
778     std::string res = ExecuteCommands("uname");
779     bool linuxKernel = res.find("Linux") != std::string::npos;
780     if (linuxKernel) {
781         ASSERT_TRUE(linuxKernel);
782         return;
783     }
784     int interestedSiCodeList[] = {
785         SIGLEAK_STACK_FDSAN, SIGLEAK_STACK_JEMALLOC
786     };
787     for (int siCode : interestedSiCodeList) {
788         pid_t pid = fork();
789         if (pid < 0) {
790             GTEST_LOG_(ERROR) << "Failed to fork new test process.";
791         } else if (pid == 0) {
792             if (DFX_InstallSignalHandler != nullptr) {
793                 DFX_InstallSignalHandler();
794             }
795             constexpr int diffMs = -10000; // 10s
796             SaveDebugMessage(siCode, diffMs, "test123");
797             sleep(5); // 5: wait for stacktrace generating
798             _exit(0);
799         } else {
800             auto fileName = WaitCreateCrashFile("stacktrace", pid);
801             ASSERT_TRUE(fileName.empty());
802         }
803     }
804 }
805 
806 /**
807  * @tc.name: SignalHandlerTest021
808  * @tc.desc: test FDSAN
809  * @tc.type: FUNC
810  */
811 HWTEST_F(SignalHandlerTest, SignalHandlerTest021, TestSize.Level2)
812 {
813     std::string res = ExecuteCommands("uname");
814     bool linuxKernel = res.find("Linux") != std::string::npos;
815     if (linuxKernel) {
816         ASSERT_TRUE(linuxKernel);
817         return;
818     }
819     pid_t pid = fork();
820     if (pid < 0) {
821         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
822     } else if (pid == 0) {
823         if (DFX_InstallSignalHandler != nullptr) {
824             DFX_InstallSignalHandler();
825         }
826         TestFdsan();
827         sleep(5); // 5: wait for stacktrace generating
828         _exit(0);
829     } else {
830         constexpr int siCode = SIGLEAK_STACK_FDSAN;
831         auto fileName = WaitCreateCrashFile("stacktrace", pid);
832         bool ret = CheckDebugSignalFaultlog(fileName, pid, siCode);
833         ASSERT_TRUE(ret);
834     }
835 }
836 
837 /**
838  * @tc.name: SignalHandlerTest022
839  * @tc.desc: test BADFD
840  * @tc.type: FUNC
841  */
842 HWTEST_F(SignalHandlerTest, SignalHandlerTest022, TestSize.Level2)
843 {
844     std::string res = ExecuteCommands("uname");
845     bool linuxKernel = res.find("Linux") != std::string::npos;
846     if (linuxKernel) {
847         ASSERT_TRUE(linuxKernel);
848         return;
849     }
850     pid_t pid = fork();
851     if (pid < 0) {
852         GTEST_LOG_(ERROR) << "Failed to fork new test process.";
853     } else if (pid == 0) {
854         if (DFX_InstallSignalHandler != nullptr) {
855             DFX_InstallSignalHandler();
856         }
857         SaveDebugMessage(SIGLEAK_STACK_BADFD, 0, nullptr);
858         sleep(5); // 5: wait for stacktrace generating
859         _exit(0);
860     } else {
861         constexpr int siCode = SIGLEAK_STACK_BADFD;
862         auto fileName = WaitCreateCrashFile("stacktrace", pid);
863         bool ret = CheckDebugSignalFaultlog(fileName, pid, siCode);
864         ASSERT_TRUE(ret);
865     }
866 }
867 
868 /**
869  * @tc.name: SignalHandlerTest023
870  * @tc.desc: test BADFD
871  * @tc.type: FUNC
872  */
873 HWTEST_F(SignalHandlerTest, SignalHandlerTest023, TestSize.Level2)
874 {
875     std::string res = ExecuteCommands("uname");
876     bool linuxKernel = res.find("Linux") != std::string::npos;
877     if (linuxKernel) {
878         ASSERT_TRUE(linuxKernel);
879         return;
880     }
881 
882     if (DFX_InstallSignalHandler != nullptr) {
883         DFX_InstallSignalHandler();
884     }
885 
886     constexpr int maxCnt = 3; // Run the test 3 times
887     std::thread testBadfdThread(TestBadfdThread, maxCnt);
888     for (int i = 0; i < maxCnt; i++) {
889         auto fileName = WaitCreateCrashFile("stacktrace", getpid());
890         ASSERT_TRUE(!fileName.empty());
891     }
892     testBadfdThread.join();
893 }
894 
895 /**
896  * @tc.name: FdTableTest001
897  * @tc.desc: Verify the fdtable structure
898  * @tc.type: FUNC
899  */
900 HWTEST_F(SignalHandlerTest, FdTableTest001, TestSize.Level2)
901 {
902     std::string res = ExecuteCommands("uname");
903     bool linuxKernel = res.find("Linux") != std::string::npos;
904     if (linuxKernel) {
905         ASSERT_TRUE(linuxKernel);
906         return;
907     }
908     /**
909      * @tc.steps: step1. open 128 fd files
910      *            case: open success
911      * @tc.expected: fp != nullptr
912      * */
913     constexpr int maxOpenNum = 128; // open fd table
914     FILE* fdList[maxOpenNum] = {nullptr};
915     for (int i = 0; i < maxOpenNum; i++) {
916         fdList[i] = fopen("/dev/null", "r");
917         ASSERT_NE(fdList[i], nullptr);
918     }
919 
920     /**
921      * @tc.steps: step2. open test fd
922      *            case: open success
923      * @tc.expected: fp != nullptr
924      * */
925     FILE *fp = fopen("/dev/null", "r");
926     ASSERT_NE(fp, nullptr);
927 
928     /**
929      * @tc.steps: step3. Clean up resources
930      * */
931     for (int i = 0; i < maxOpenNum; i++) {
932         if (fdList[i] != nullptr) {
933             fclose(fdList[i]);
934             fdList[i] = nullptr;
935         }
936     }
937 
938     /**
939      * @tc.steps: step4. Get fd tag
940      * */
941     uint64_t ownerTag = fdsan_get_owner_tag(fileno(fp));
942     uint64_t tag = fdsan_get_tag_value(ownerTag);
943 
944     pid_t pid = fork();
945     if (pid < 0) {
946         GTEST_LOG_(ERROR) << "Failed to fork new process.";
947     } else if (pid == 0) {
948         // The child process has disabled fdsan detection by default
949         fdsan_set_error_level(FDSAN_ERROR_LEVEL_WARN_ONCE);
950         /**
951          * @tc.steps: step5. Trigger fdsan
952          * */
953         close(fileno(fp));
954     } else {
955         /**
956          * @tc.steps: step6. Waiting for the completion of stack grabbing
957          * */
958         sleep(3);
959 
960         string keywords[] = {
961             to_string(fileno(fp)) + "->/dev/null", to_string(tag)
962         };
963         fclose(fp);
964 
965         /**
966          * @tc.steps: step7. Check key words
967          * @tc.expected: check success
968          * */
969         auto filePath = GetDumpLogFileName("stacktrace", pid, TEMP_DIR);
970         ASSERT_FALSE(filePath.empty());
971 
972         int length = sizeof(keywords) / sizeof(keywords[0]);
973         int minRegIdx = -1;
974         ASSERT_EQ(CheckKeyWords(filePath, keywords, length, minRegIdx), length);
975     }
976 
977     return;
978 }
979 } // namespace HiviewDFX
980 } // namepsace OHOS
981