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_handler.h" 28#include "dfx_signalhandler_exception.h" 29#include "dfx_test_util.h" 30 31using namespace testing; 32using namespace testing::ext; 33using namespace std; 34 35namespace OHOS { 36namespace HiviewDFX { 37class SignalHandlerTest : public testing::Test { 38public: 39 static void SetUpTestCase(); 40 static void TearDownTestCase(); 41 void SetUp(); 42 void TearDown(); 43}; 44 45void SignalHandlerTest::SetUpTestCase() 46{} 47 48void SignalHandlerTest::TearDownTestCase() 49{} 50 51void SignalHandlerTest::SetUp() 52{} 53 54void SignalHandlerTest::TearDown() 55{} 56 57extern "C" void SetThreadInfoCallback(ThreadInfoCallBack func) __attribute__((weak)); 58extern "C" void DFX_InstallSignalHandler(void) __attribute__((weak)); 59extern "C" void SetAsyncStackCallbackFunc(void* func) __attribute__((weak)); 60extern "C" int DFX_SetAppRunningUniqueId(const char* appRunningId, size_t len) __attribute__((weak)); 61static bool CheckThreadCrashKeyWords(const string& filePath, pid_t pid, int sig) 62{ 63 if (filePath.empty() || pid <= 0) { 64 return false; 65 } 66 map<int, string> sigKey = { 67 { SIGILL, string("SIGILL") }, 68 { SIGBUS, string("SIGBUS") }, 69 { SIGSEGV, string("SIGSEGV") }, 70 }; 71 string sigKeyword = ""; 72 map<int, string>::iterator iter = sigKey.find(sig); 73 if (iter != sigKey.end()) { 74 sigKeyword = iter->second; 75 } 76 string keywords[] = { 77 "Pid:" + to_string(pid), "Uid:", "name:./test_signalhandler", sigKeyword, 78 "Tid:", "#00", "Registers:", "FaultStack:", "Maps:", "test_signalhandler" 79 }; 80 int length = sizeof(keywords) / sizeof(keywords[0]); 81 int minRegIdx = -1; 82 return CheckKeyWords(filePath, keywords, length, minRegIdx) == length; 83} 84static bool CheckCrashKeyWords(const string& filePath, pid_t pid, int sig) 85{ 86 if (filePath.empty() || pid <= 0) { 87 return false; 88 } 89 map<int, string> sigKey = { 90 { SIGILL, string("SIGILL") }, 91 { SIGBUS, string("SIGBUS") }, 92 { SIGSEGV, string("SIGSEGV") }, 93 { SIGABRT, string("SIGABRT") }, 94 { SIGFPE, string("SIGFPE") }, 95 { SIGSTKFLT, string("SIGSTKFLT") }, 96 { SIGSYS, string("SIGSYS") }, 97 { SIGTRAP, string("SIGTRAP") }, 98 }; 99 string sigKeyword = ""; 100 map<int, string>::iterator iter = sigKey.find(sig); 101 if (iter != sigKey.end()) { 102 sigKeyword = iter->second; 103 } 104 string keywords[] = { 105 "Pid:" + to_string(pid), "Uid:", "name:./test_signalhandler", sigKeyword, 106 "Tid:", "#00", "Registers:", "FaultStack:", "Maps:", "test_signalhandler" 107 }; 108 int length = sizeof(keywords) / sizeof(keywords[0]); 109 int minRegIdx = -1; 110 return CheckKeyWords(filePath, keywords, length, minRegIdx) == length; 111} 112 113void ThreadInfo(char* buf, size_t len, void* context __attribute__((unused))) 114{ 115 char mes[] = "this is cash information of test thread"; 116 if (memcpy_s(buf, len, mes, sizeof(mes)) != 0) { 117 GTEST_LOG_(INFO) << "Failed to set thread info"; 118 } 119} 120 121int TestThread(int threadId, int sig) 122{ 123 std::string subThreadName = "SubTestThread" + to_string(threadId); 124 prctl(PR_SET_NAME, subThreadName.c_str()); 125 if (SetThreadInfoCallback != nullptr) { 126 SetThreadInfoCallback(ThreadInfo); 127 } 128 int cashThreadId = 2; 129 if (threadId == cashThreadId) { 130 GTEST_LOG_(INFO) << subThreadName << " is ready to raise signo(" << sig <<")"; 131 raise(sig); 132 } 133 return 0; 134} 135 136/** 137 * @tc.name: SignalHandlerTest001 138 * @tc.desc: test thread cash SignalHandler signo(SIGILL) 139 * @tc.type: FUNC 140 */ 141HWTEST_F(SignalHandlerTest, SignalHandlerTest001, TestSize.Level2) 142{ 143 GTEST_LOG_(INFO) << "SignalHandlerTest001: start."; 144 pid_t pid = fork(); 145 if (pid < 0) { 146 GTEST_LOG_(ERROR) << "Failed to fork new test process."; 147 } else if (pid == 0) { 148 if (SetThreadInfoCallback != nullptr) { 149 SetThreadInfoCallback(ThreadInfo); 150 } 151 sleep(1); 152 } else { 153 usleep(10000); // 10000 : sleep 10ms 154 GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")"; 155 kill(pid, SIGILL); 156 sleep(2); // 2 : wait for cppcrash generating 157 bool ret = CheckThreadCrashKeyWords(GetCppCrashFileName(pid), pid, SIGILL); 158 ASSERT_TRUE(ret); 159 } 160 GTEST_LOG_(INFO) << "SignalHandlerTest001: end."; 161} 162 163/** 164 * @tc.name: SignalHandlerTest002 165 * @tc.desc: test thread cash SignalHandler signo(SIGBUS) 166 * @tc.type: FUNC 167 */ 168HWTEST_F(SignalHandlerTest, SignalHandlerTest002, TestSize.Level2) 169{ 170 GTEST_LOG_(INFO) << "SignalHandlerTest002: start."; 171 pid_t pid = fork(); 172 if (pid < 0) { 173 GTEST_LOG_(ERROR) << "Failed to fork new test process."; 174 } else if (pid == 0) { 175 if (SetThreadInfoCallback != nullptr) { 176 SetThreadInfoCallback(ThreadInfo); 177 } 178 sleep(1); 179 } else { 180 usleep(10000); // 10000 : sleep 10ms 181 GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")"; 182 kill(pid, SIGBUS); 183 sleep(2); // 2 : wait for cppcrash generating 184 bool ret = CheckThreadCrashKeyWords(GetCppCrashFileName(pid), pid, SIGBUS); 185 ASSERT_TRUE(ret); 186 } 187 GTEST_LOG_(INFO) << "SignalHandlerTest002: end."; 188} 189 190/** 191 * @tc.name: SignalHandlerTest003 192 * @tc.desc: test thread cash SignalHandler signo(SIGSEGV) 193 * @tc.type: FUNC 194 */ 195HWTEST_F(SignalHandlerTest, SignalHandlerTest003, TestSize.Level2) 196{ 197 GTEST_LOG_(INFO) << "SignalHandlerTest003: start."; 198 pid_t pid = fork(); 199 if (pid < 0) { 200 GTEST_LOG_(ERROR) << "Failed to fork new test process."; 201 } else if (pid == 0) { 202 if (SetThreadInfoCallback != nullptr) { 203 SetThreadInfoCallback(ThreadInfo); 204 } 205 sleep(1); 206 } else { 207 usleep(10000); // 10000 : sleep 10ms 208 GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill process(" << pid << ")"; 209 kill(pid, SIGSEGV); 210 sleep(2); // 2 : wait for cppcrash generating 211 bool ret = CheckThreadCrashKeyWords(GetCppCrashFileName(pid), pid, SIGSEGV); 212 ASSERT_TRUE(ret); 213 } 214 GTEST_LOG_(INFO) << "SignalHandlerTest003: end."; 215} 216 217/** 218 * @tc.name: SignalHandlerTest004 219 * @tc.desc: test thread crash SignalHandler in multi-thread situation signo(SIGILL) 220 * @tc.type: FUNC 221 */ 222HWTEST_F(SignalHandlerTest, SignalHandlerTest004, TestSize.Level2) 223{ 224 GTEST_LOG_(INFO) << "SignalHandlerTest004: start."; 225 pid_t pid = fork(); 226 if (pid < 0) { 227 GTEST_LOG_(ERROR) << "Failed to fork new test process."; 228 } else if (pid == 0) { 229 std::thread (TestThread, 1, SIGILL).join(); // 1 : first thread 230 std::thread (TestThread, 2, SIGILL).join(); // 2 : second thread 231 _exit(0); 232 } else { 233 sleep(2); // 2 : wait for cppcrash generating 234 bool ret = CheckThreadCrashKeyWords(GetCppCrashFileName(pid), pid, SIGILL); 235 ASSERT_TRUE(ret); 236 } 237 GTEST_LOG_(INFO) << "SignalHandlerTest004: end."; 238} 239 240/** 241 * @tc.name: SignalHandlerTest005 242 * @tc.desc: test thread crash SignalHandler in multi-thread situation signo(SIGBUS) 243 * @tc.type: FUNC 244 */ 245HWTEST_F(SignalHandlerTest, SignalHandlerTest005, TestSize.Level2) 246{ 247 GTEST_LOG_(INFO) << "SignalHandlerTest005: start."; 248 pid_t pid = fork(); 249 if (pid < 0) { 250 GTEST_LOG_(ERROR) << "Failed to fork new test process."; 251 } else if (pid == 0) { 252 std::thread (TestThread, 1, SIGBUS).join(); // 1 : first thread 253 std::thread (TestThread, 2, SIGBUS).join(); // 2 : second thread 254 _exit(0); 255 } else { 256 sleep(2); // 2 : wait for cppcrash generating 257 bool ret = CheckThreadCrashKeyWords(GetCppCrashFileName(pid), pid, SIGBUS); 258 ASSERT_TRUE(ret); 259 } 260 GTEST_LOG_(INFO) << "SignalHandlerTest005: end."; 261} 262 263/** 264 * @tc.name: SignalHandlerTest006 265 * @tc.desc: test thread crash SignalHandler in multi-thread situation signo(SIGSEGV) 266 * @tc.type: FUNC 267 */ 268HWTEST_F(SignalHandlerTest, SignalHandlerTest006, TestSize.Level2) 269{ 270 GTEST_LOG_(INFO) << "SignalHandlerTest006: start."; 271 pid_t pid = fork(); 272 if (pid < 0) { 273 GTEST_LOG_(ERROR) << "Failed to fork new test process."; 274 } else if (pid == 0) { 275 std::thread (TestThread, 1, SIGSEGV).join(); // 1 : first thread 276 std::thread (TestThread, 2, SIGSEGV).join(); // 2 : second thread 277 _exit(0); 278 } else { 279 sleep(2); // 2 : wait for cppcrash generating 280 bool ret = CheckThreadCrashKeyWords(GetCppCrashFileName(pid), pid, SIGSEGV); 281 ASSERT_TRUE(ret); 282 } 283 GTEST_LOG_(INFO) << "SignalHandlerTest006: end."; 284} 285 286/** 287 * @tc.name: SignalHandlerTest007 288 * @tc.desc: test DFX_InstallSignalHandler interface 289 * @tc.type: FUNC 290 */ 291HWTEST_F(SignalHandlerTest, SignalHandlerTest007, TestSize.Level2) 292{ 293 GTEST_LOG_(INFO) << "SignalHandlerTest007: start."; 294 int interestedSignalList[] = { 295 SIGABRT, SIGBUS, SIGFPE, 296 SIGSEGV, SIGSTKFLT, SIGSYS, SIGTRAP 297 }; 298 for (int sig : interestedSignalList) { 299 pid_t pid = fork(); 300 if (pid < 0) { 301 GTEST_LOG_(ERROR) << "Failed to fork new test process."; 302 } else if (pid == 0) { 303 if (DFX_InstallSignalHandler != nullptr) { 304 DFX_InstallSignalHandler(); 305 } 306 sleep(1); 307 } else { 308 usleep(10000); // 10000 : sleep 10ms 309 GTEST_LOG_(INFO) << "process(" << getpid() << ") is ready to kill << process(" << pid << ")"; 310 GTEST_LOG_(INFO) << "signal:" << sig; 311 kill(pid, sig); 312 sleep(2); // 2 : wait for cppcrash generating 313 bool ret = CheckCrashKeyWords(GetCppCrashFileName(pid), pid, sig); 314 ASSERT_TRUE(ret); 315 } 316 } 317 GTEST_LOG_(INFO) << "SignalHandlerTest007: end."; 318} 319 320int TestThread2(int threadId, int sig, int total, bool exitEarly) 321{ 322 std::string subThreadName = "SubTestThread" + to_string(threadId); 323 prctl(PR_SET_NAME, subThreadName.c_str()); 324 if (SetThreadInfoCallback != nullptr) { 325 SetThreadInfoCallback(ThreadInfo); 326 } 327 if (threadId == total - 1) { 328 GTEST_LOG_(INFO) << subThreadName << " is ready to raise signo(" << sig <<")"; 329 raise(sig); 330 } 331 332 if (!exitEarly) { 333 sleep(total - threadId); 334 } 335 if (SetThreadInfoCallback != nullptr) { 336 SetThreadInfoCallback(ThreadInfo); 337 } 338 return 0; 339} 340 341/** 342 * @tc.name: SignalHandlerTest008 343 * @tc.desc: test add 36 thread info callback and crash thread has no callback 344 * @tc.type: FUNC 345 */ 346HWTEST_F(SignalHandlerTest, SignalHandlerTest008, TestSize.Level2) 347{ 348 GTEST_LOG_(INFO) << "SignalHandlerTest008: start."; 349 pid_t pid = fork(); 350 if (pid < 0) { 351 GTEST_LOG_(ERROR) << "Failed to fork new test process."; 352 } else if (pid == 0) { 353 std::vector<std::thread> threads; 354 const int testThreadCount = 36; 355 for (int i = 0; i < testThreadCount; i++) { 356 threads.push_back(std::thread(TestThread2, i, SIGSEGV, testThreadCount, false)); 357 } 358 359 for (auto& thread : threads) { 360 thread.join(); 361 } 362 _exit(0); 363 } else { 364 sleep(2); // 2 : wait for cppcrash generating 365 auto file = GetCppCrashFileName(pid); 366 ASSERT_FALSE(file.empty()); 367 } 368 GTEST_LOG_(INFO) << "SignalHandlerTest008: end."; 369} 370 371/** 372 * @tc.name: SignalHandlerTest009 373 * @tc.desc: test add 36 thread info callback and crash thread has the callback 374 * @tc.type: FUNC 375 */ 376HWTEST_F(SignalHandlerTest, SignalHandlerTest009, TestSize.Level2) 377{ 378 GTEST_LOG_(INFO) << "SignalHandlerTest009: start."; 379 pid_t pid = fork(); 380 if (pid < 0) { 381 GTEST_LOG_(ERROR) << "Failed to fork new test process."; 382 } else if (pid == 0) { 383 std::vector<std::thread> threads; 384 const int testThreadCount = 36; 385 for (int i = 0; i < testThreadCount; i++) { 386 bool exitEarly = false; 387 if (i % 2 == 0) { 388 exitEarly = true; 389 } 390 threads.push_back(std::thread (TestThread2, i, SIGSEGV, testThreadCount, exitEarly)); 391 } 392 393 for (auto& thread : threads) { 394 thread.join(); 395 } 396 _exit(0); 397 } else { 398 sleep(2); // 2 : wait for cppcrash generating 399 auto file = GetCppCrashFileName(pid); 400 ASSERT_FALSE(file.empty()); 401 } 402 GTEST_LOG_(INFO) << "SignalHandlerTest009: end."; 403} 404 405/** 406 * @tc.name: SignalHandlerTest010 407 * @tc.desc: test crash when free a invalid address 408 * @tc.type: FUNC 409 */ 410HWTEST_F(SignalHandlerTest, SignalHandlerTest010, TestSize.Level2) 411{ 412 GTEST_LOG_(INFO) << "SignalHandlerTest010: 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 if (SetThreadInfoCallback != nullptr) { 418 SetThreadInfoCallback(ThreadInfo); 419 } 420 int32_t freeAddr = 0x111; 421 // trigger crash 422 free(reinterpret_cast<void*>(freeAddr)); 423 // force crash if not crash in free 424 abort(); 425 } else { 426 sleep(2); // 2 : wait for cppcrash generating 427 auto file = GetCppCrashFileName(pid); 428 ASSERT_FALSE(file.empty()); 429 } 430 GTEST_LOG_(INFO) << "SignalHandlerTest010: end."; 431} 432 433/** 434 * @tc.name: SignalHandlerTest011 435 * @tc.desc: test crash when realloc a invalid address 436 * @tc.type: FUNC 437 */ 438HWTEST_F(SignalHandlerTest, SignalHandlerTest011, TestSize.Level2) 439{ 440 GTEST_LOG_(INFO) << "SignalHandlerTest011: start."; 441 pid_t pid = fork(); 442 if (pid < 0) { 443 GTEST_LOG_(ERROR) << "Failed to fork new test process."; 444 } else if (pid == 0) { 445 int32_t initAllocSz = 10; 446 int32_t reallocSz = 20; 447 if (SetThreadInfoCallback != nullptr) { 448 SetThreadInfoCallback(ThreadInfo); 449 } 450 // alloc a buffer 451 int8_t* addr = reinterpret_cast<int8_t*>(malloc(initAllocSz)); 452 // overwrite the control block 453 int8_t* newAddr = addr - initAllocSz; 454 (void)memset_s(newAddr, initAllocSz, 0, initAllocSz); 455 addr = reinterpret_cast<int8_t*>(realloc(reinterpret_cast<void*>(addr), reallocSz)); 456 free(addr); 457 // force crash if not crash in realloc 458 abort(); 459 } else { 460 sleep(2); // 2 : wait for cppcrash generating 461 auto file = GetCppCrashFileName(pid); 462 ASSERT_FALSE(file.empty()); 463 } 464 GTEST_LOG_(INFO) << "SignalHandlerTest011: end."; 465} 466 467/** 468 * @tc.name: SignalHandlerTest012 469 * @tc.desc: test crash when realloc a invalid address without threadInfo callback 470 * @tc.type: FUNC 471 */ 472HWTEST_F(SignalHandlerTest, SignalHandlerTest012, TestSize.Level2) 473{ 474 GTEST_LOG_(INFO) << "SignalHandlerTest012: start."; 475 pid_t pid = fork(); 476 if (pid < 0) { 477 GTEST_LOG_(ERROR) << "Failed to fork new test process."; 478 } else if (pid == 0) { 479 int32_t initAllocSz = 10; 480 int32_t reallocSz = 20; 481 // alloc a buffer 482 int8_t* addr = reinterpret_cast<int8_t*>(malloc(initAllocSz)); 483 // overwrite the control block 484 int8_t* newAddr = addr - initAllocSz; 485 (void)memset_s(newAddr, initAllocSz, 0, initAllocSz); 486 addr = reinterpret_cast<int8_t*>(realloc(reinterpret_cast<void*>(addr), reallocSz)); 487 free(addr); 488 // force crash if not crash in realloc 489 abort(); 490 } else { 491 sleep(2); // 2 : wait for cppcrash generating 492 auto file = GetCppCrashFileName(pid); 493 ASSERT_FALSE(file.empty()); 494 } 495 GTEST_LOG_(INFO) << "SignalHandlerTest012: end."; 496} 497 498/** 499 * @tc.name: SignalHandlerTest013 500 * @tc.desc: test add 100 thread info callback and do nothing 501 * @tc.type: FUNC 502 */ 503HWTEST_F(SignalHandlerTest, SignalHandlerTest013, TestSize.Level2) 504{ 505 GTEST_LOG_(INFO) << "SignalHandlerTest013: start."; 506 std::vector<std::thread> threads; 507 const int testThreadCount = 100; 508 for (int i = 0; i < testThreadCount - 1; i++) { 509 threads.push_back(std::thread (TestThread2, i, SIGSEGV, testThreadCount, true)); 510 } 511 512 for (auto& thread : threads) { 513 if (thread.joinable()) { 514 thread.join(); 515 } 516 } 517 auto file = GetCppCrashFileName(getpid()); 518 ASSERT_TRUE(file.empty()); 519 GTEST_LOG_(INFO) << "SignalHandlerTest013: end."; 520} 521 522void TestCallbackFunc() 523{} 524 525/** 526 * @tc.name: SignalHandlerTest015 527 * @tc.desc: test DFX_SetAppRunningUniqueId 528 * @tc.type: FUNC 529 */ 530HWTEST_F(SignalHandlerTest, SignalHandlerTest015, TestSize.Level2) 531{ 532 bool isSuccess = DFX_SetAppRunningUniqueId != nullptr; 533 if (!isSuccess) { 534 ASSERT_FALSE(isSuccess); 535 return; 536 } 537 /** 538 * @tc.steps: step1. 539 * case: appRunningId == nullptr, len= 0 540 * @tc.expected: ret == -1 541 * */ 542 int ret = DFX_SetAppRunningUniqueId(nullptr, 0); 543 ASSERT_EQ(ret, -1); 544 545 /** 546 * @tc.steps: step2. 547 * case: appRunningId == nullptr, len= MAX_APP_RUNNING_UNIQUE_ID_LEN 548 * @tc.expected: ret == -1 549 * */ 550 ret = DFX_SetAppRunningUniqueId(nullptr, MAX_APP_RUNNING_UNIQUE_ID_LEN); 551 ASSERT_EQ(ret, -1); 552 553 /** 554 * @tc.steps: step3. 555 * case: appRunningId != nullptr, len= 0 556 * @tc.expected: ret == 0 557 * */ 558 constexpr char testId1[] = "App running unique test id"; 559 ret = DFX_SetAppRunningUniqueId(testId1, 0); 560 ASSERT_EQ(ret, 0); 561 562 /** 563 * @tc.steps: step4. 564 * case: appRunningId != nullptr, len= strleng(appRunningId) 565 * @tc.expected: ret == 0 566 * */ 567 ret = DFX_SetAppRunningUniqueId(testId1, strlen(testId1)); 568 ASSERT_EQ(ret, 0); 569 570 /** 571 * @tc.steps: step5. 572 * case: appRunningId != nullptr, len= MAX_APP_RUNNING_UNIQUE_ID_LEN + 1 573 * @tc.expected: ret == -1 574 * */ 575 constexpr size_t testLen = MAX_APP_RUNNING_UNIQUE_ID_LEN + 1; 576 ret = DFX_SetAppRunningUniqueId(testId1, testLen); 577 ASSERT_EQ(ret, -1); 578 579 /** 580 * @tc.steps: step6. 581 * case: appRunningId != nullptr, len= MAX_APP_RUNNING_UNIQUE_ID_LEN 582 * @tc.expected: ret == 0 583 * */ 584 constexpr char testId2[MAX_APP_RUNNING_UNIQUE_ID_LEN] = "App running unique test id"; 585 ret = DFX_SetAppRunningUniqueId(testId2, MAX_APP_RUNNING_UNIQUE_ID_LEN); 586 ASSERT_EQ(ret, -1); 587} 588 589/** 590 * @tc.name: SignalHandlerTest016 591 * @tc.desc: test ReportException 592 * @tc.type: FUNC 593 */ 594HWTEST_F(SignalHandlerTest, SignalHandlerTest016, TestSize.Level2) 595{ 596 GTEST_LOG_(INFO) << "SignalHandlerTest016: start."; 597 if (SetAsyncStackCallbackFunc != nullptr) { 598 SetAsyncStackCallbackFunc(reinterpret_cast<void*>(TestCallbackFunc)); 599 } 600 601 struct CrashDumpException exception; 602 exception.pid = 1; 603 exception.uid = 1; 604 exception.error = CRASH_SIGNAL_EMASKED; 605 int ret = ReportException(exception); 606 ASSERT_NE(ret, -1); 607 GTEST_LOG_(INFO) << "SignalHandlerTest016: end."; 608} 609} // namespace HiviewDFX 610} // namepsace OHOS 611