1/* 2 * Copyright (c) 2024 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#ifndef _GNU_SOURCE 16#define _GNU_SOURCE 1 17#endif 18 19#include "dfx_dumprequest.h" 20 21#include <fcntl.h> 22#include <poll.h> 23#include <pthread.h> 24#include <sched.h> 25#include <signal.h> 26#include <sigchain.h> 27#include <stdint.h> 28#include <stdio.h> 29#include <sys/capability.h> 30#include <sys/mman.h> 31#include <sys/prctl.h> 32#include <sys/syscall.h> 33#include <sys/time.h> 34#include <sys/types.h> 35#include <sys/uio.h> 36#include <sys/wait.h> 37#include <time.h> 38#include <unistd.h> 39#include "dfx_define.h" 40#include "dfx_dump_request.h" 41#include "dfx_signalhandler_exception.h" 42#include "errno.h" 43#include "linux/capability.h" 44#include "stdbool.h" 45#include "string.h" 46#ifndef DFX_SIGNAL_LIBC 47#include <securec.h> 48#include "dfx_cutil.h" 49#include "dfx_log.h" 50#else 51#include "musl_cutil.h" 52#include "musl_log.h" 53#endif 54 55#include "info/fatal_message.h" 56 57#ifdef LOG_DOMAIN 58#undef LOG_DOMAIN 59#define LOG_DOMAIN 0xD002D11 60#endif 61 62#ifdef LOG_TAG 63#undef LOG_TAG 64#define LOG_TAG "DfxSignalHandler" 65#endif 66 67#ifndef F_SETPIPE_SZ 68#define F_SETPIPE_SZ 1031 69#endif 70 71#define NUMBER_SIXTYFOUR 64 72#define INHERITABLE_OFFSET 32 73 74static struct ProcessDumpRequest *g_request = NULL; 75static void *g_reservedChildStack = NULL; 76 77enum PIPE_FD_TYPE { 78 WRITE_TO_DUMP, 79 READ_FROM_DUMP_TO_MAIN, 80 READ_FORM_DUMP_TO_VIRTUAL, 81 PIPE_MAX, 82}; 83 84static int g_pipeFds[PIPE_MAX][2] = { 85 {-1, -1}, 86 {-1, -1}, 87 {-1, -1} 88}; 89 90static const int SIGNALHANDLER_TIMEOUT = 10000; // 10000 us 91static const int ALARM_TIME_S = 10; 92enum DumpPreparationStage { 93 CREATE_PIPE_FAIL = 1, 94 SET_PIPE_LEN_FAIL, 95 WRITE_PIPE_FAIL, 96 INHERIT_CAP_FAIL, 97 EXEC_FAIL, 98}; 99 100static const char* GetCrashDescription(const int32_t errCode) 101{ 102 size_t i; 103 104 for (i = 0; i < sizeof(g_crashExceptionMap) / sizeof(g_crashExceptionMap[0]); i++) { 105 if (errCode == g_crashExceptionMap[i].errCode) { 106 return g_crashExceptionMap[i].str; 107 } 108 } 109 return g_crashExceptionMap[i - 1].str; /* the end of map is "unknown reason" */ 110} 111 112static void FillCrashExceptionAndReport(const int err) 113{ 114 struct CrashDumpException exception; 115 (void)memset_s(&exception, sizeof(struct CrashDumpException), 0, sizeof(struct CrashDumpException)); 116 exception.pid = g_request->pid; 117 exception.uid = (int32_t)(g_request->uid); 118 exception.error = err; 119 exception.time = (int64_t)(GetTimeMilliseconds()); 120 if (strncpy_s(exception.message, sizeof(exception.message), GetCrashDescription(err), 121 sizeof(exception.message) - 1) != 0) { 122 DFXLOGE("strcpy exception message fail"); 123 return; 124 } 125 ReportException(exception); 126} 127 128static int32_t InheritCapabilities(void) 129{ 130 struct __user_cap_header_struct capHeader; 131 (void)memset_s(&capHeader, sizeof(capHeader), 0, sizeof(capHeader)); 132 133 capHeader.version = _LINUX_CAPABILITY_VERSION_3; 134 capHeader.pid = 0; 135 struct __user_cap_data_struct capData[2]; 136 if (capget(&capHeader, &capData[0]) == -1) { 137 DFXLOGE("Failed to get origin cap data"); 138 return -1; 139 } 140 141 capData[0].inheritable = capData[0].permitted; 142 capData[1].inheritable = capData[1].permitted; 143 if (capset(&capHeader, &capData[0]) == -1) { 144 DFXLOGE("Failed to set cap data, errno(%{public}d)", errno); 145 return -1; 146 } 147 148 uint64_t ambCap = capData[0].inheritable; 149 ambCap = ambCap | (((uint64_t)capData[1].inheritable) << INHERITABLE_OFFSET); 150 for (size_t i = 0; i < NUMBER_SIXTYFOUR; i++) { 151 if (ambCap & ((uint64_t)1)) { 152 if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, 0) < 0) { 153 DFXLOGE("Failed to change the ambient capability set, errno(%{public}d)", errno); 154 } 155 } 156 ambCap = ambCap >> 1; 157 } 158 return 0; 159} 160 161static const int SIGCHAIN_DUMP_SIGNAL_LIST[] = { 162 SIGDUMP, SIGLEAK_STACK 163}; 164 165static const int SIGCHAIN_CRASH_SIGNAL_LIST[] = { 166 SIGILL, SIGABRT, SIGBUS, SIGFPE, 167 SIGSEGV, SIGSTKFLT, SIGSYS, SIGTRAP 168}; 169 170static void SetInterestedSignalMasks(int how) 171{ 172 sigset_t set; 173 sigemptyset(&set); 174 for (size_t i = 0; i < sizeof(SIGCHAIN_DUMP_SIGNAL_LIST) / sizeof(SIGCHAIN_DUMP_SIGNAL_LIST[0]); i++) { 175 sigaddset(&set, SIGCHAIN_DUMP_SIGNAL_LIST[i]); 176 } 177 for (size_t i = 0; i < sizeof(SIGCHAIN_CRASH_SIGNAL_LIST) / sizeof(SIGCHAIN_CRASH_SIGNAL_LIST[0]); i++) { 178 sigaddset(&set, SIGCHAIN_CRASH_SIGNAL_LIST[i]); 179 } 180 sigprocmask(how, &set, NULL); 181} 182 183static void CloseFds(void) 184{ 185 const int closeFdCount = 1024; 186 for (int i = 0; i < closeFdCount; i++) { 187 syscall(SYS_close, i); 188 } 189} 190 191static void DFX_SetUpEnvironment(void) 192{ 193 // clear stdout and stderr 194 int devNull = OHOS_TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)); 195 if (devNull < 0) { 196 DFXLOGE("Failed to open dev/null."); 197 return; 198 } 199 200 OHOS_TEMP_FAILURE_RETRY(dup2(devNull, STDOUT_FILENO)); 201 OHOS_TEMP_FAILURE_RETRY(dup2(devNull, STDERR_FILENO)); 202 syscall(SYS_close, devNull); 203 SetInterestedSignalMasks(SIG_BLOCK); 204} 205 206static void DFX_SetUpSigAlarmAction(void) 207{ 208 if (signal(SIGALRM, SIG_DFL) == SIG_ERR) { 209 DFXLOGW("Default signal alarm error!"); 210 } 211 sigset_t set; 212 sigemptyset(&set); 213 sigaddset(&set, SIGALRM); 214 sigprocmask(SIG_UNBLOCK, &set, NULL); 215} 216 217static int DFX_ExecDump(void) 218{ 219 DFX_SetUpEnvironment(); 220 DFX_SetUpSigAlarmAction(); 221 alarm(ALARM_TIME_S); 222 int pipefd[2] = {-1, -1}; 223 // create pipe for passing request to processdump 224 if (g_request->dumpMode == SPLIT_MODE) { 225 if (syscall(SYS_pipe2, pipefd, 0) != 0) { 226 DFXLOGE("Failed to create pipe for transfering context, errno(%{public}d)", errno); 227 return CREATE_PIPE_FAIL; 228 } 229 } else { 230 pipefd[0] = g_pipeFds[WRITE_TO_DUMP][0]; 231 pipefd[1] = g_pipeFds[WRITE_TO_DUMP][1]; 232 } 233 234 ssize_t writeLen = (long)(sizeof(struct ProcessDumpRequest)); 235 if (fcntl(pipefd[1], F_SETPIPE_SZ, writeLen) < writeLen) { 236 DFXLOGE("Failed to set pipe buffer size, errno(%{public}d).", errno); 237 return SET_PIPE_LEN_FAIL; 238 } 239 240 struct iovec iovs[1] = { 241 { 242 .iov_base = g_request, 243 .iov_len = sizeof(struct ProcessDumpRequest) 244 }, 245 }; 246 if (OHOS_TEMP_FAILURE_RETRY(writev(pipefd[1], iovs, 1)) != writeLen) { 247 DFXLOGE("Failed to write pipe, errno(%{public}d)", errno); 248 return WRITE_PIPE_FAIL; 249 } 250 OHOS_TEMP_FAILURE_RETRY(dup2(pipefd[0], STDIN_FILENO)); 251 if (pipefd[0] != STDIN_FILENO) { 252 syscall(SYS_close, pipefd[0]); 253 } 254 syscall(SYS_close, pipefd[1]); 255 256 if (InheritCapabilities() != 0) { 257 DFXLOGE("Failed to inherit Capabilities from parent."); 258 FillCrashExceptionAndReport(CRASH_SIGNAL_EINHERITCAP); 259 return INHERIT_CAP_FAIL; 260 } 261 DFXLOGW("execl processdump."); 262#ifdef DFX_LOG_HILOG_BASE 263 execl("/system/bin/processdump", "processdump", "-signalhandler", NULL); 264#else 265 execl("/bin/processdump", "processdump", "-signalhandler", NULL); 266#endif 267 DFXLOGE("Failed to execl processdump, errno(%{public}d)", errno); 268 FillCrashExceptionAndReport(CRASH_SIGNAL_EEXECL); 269 return errno; 270} 271 272static pid_t ForkBySyscall(void) 273{ 274#ifdef SYS_fork 275 return syscall(SYS_fork); 276#else 277 return syscall(SYS_clone, SIGCHLD, 0); 278#endif 279} 280 281static bool SetDumpState(void) 282{ 283 if (prctl(PR_SET_DUMPABLE, 1) != 0) { 284 DFXLOGE("Failed to set dumpable, errno(%{public}d).", errno); 285 return false; 286 } 287 288 if (prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY) != 0) { 289 if (errno != EINVAL) { 290 DFXLOGE("Failed to set ptracer, errno(%{public}d).", errno); 291 return false; 292 } 293 } 294 return true; 295} 296 297static void RestoreDumpState(int prevState, bool isTracerStatusModified) 298{ 299 prctl(PR_SET_DUMPABLE, prevState); 300 if (isTracerStatusModified == true) { 301 prctl(PR_SET_PTRACER, 0); 302 } 303} 304 305static void SetSelfThreadParam(const char* name, int priority) 306{ 307 pthread_setname_np(pthread_self(), name); 308 struct sched_param schedParam; 309 schedParam.sched_priority = priority; 310 pthread_setschedparam(pthread_self(), SCHED_FIFO, &schedParam); 311} 312 313static bool WaitProcessExit(int childPid, const char* name) 314{ 315 int ret = -1; 316 int status = 0; 317 int startTime = (int)time(NULL); 318 bool isSuccess = false; 319 DFXLOGI("(%{public}ld) wait %{public}s(%{public}d) exit.", syscall(SYS_gettid), name, childPid); 320 do { 321 errno = 0; 322 ret = waitpid(childPid, &status, WNOHANG); 323 if (ret < 0) { 324 DFXLOGE("Failed to wait child process terminated, errno(%{public}d)", errno); 325 return isSuccess; 326 } 327 328 if (ret == childPid) { 329 isSuccess = true; 330 break; 331 } 332 333 if ((int)time(NULL) - startTime > PROCESSDUMP_TIMEOUT) { 334 DFXLOGI("(%{public}ld) wait for (%{public}d) timeout", syscall(SYS_gettid), childPid); 335 isSuccess = false; 336 break; 337 } 338 usleep(SIGNALHANDLER_TIMEOUT); // sleep 10ms 339 } while (1); 340 341 DFXLOGI("(%{public}ld) wait for %{public}s(%{public}d) return with ret(%{public}d), status(%{public}d)", 342 syscall(SYS_gettid), name, childPid, ret, status); 343 if (WIFEXITED(status)) { 344 int exitCode = WEXITSTATUS(status); 345 DFXLOGI("wait %{public}s(%{public}d) exit code: %{public}d", name, childPid, exitCode); 346 } else if (WIFSIGNALED(status)) { 347 int sigNum = WTERMSIG(status); 348 DFXLOGI("wait %{public}s(%{public}d) exit with sig: %{public}d", name, childPid, sigNum); 349 } 350 return isSuccess; 351} 352 353static void Exit(int flag) 354{ 355 _exit(flag); // Avoid crashes that occur when directly using the _exit() 356} 357 358static int ForkAndExecProcessDump(void) 359{ 360 int childPid = -1; 361 SetSelfThreadParam("dump_tmp_thread", 0); 362 363 // set privilege for dump ourself 364 int prevDumpableStatus = prctl(PR_GET_DUMPABLE); 365 bool isTracerStatusModified = SetDumpState(); 366 if (!isTracerStatusModified) { 367 FillCrashExceptionAndReport(CRASH_SIGNAL_ESETSTATE); 368 goto out; 369 } 370 371 // fork a child process that could ptrace us 372 childPid = ForkBySyscall(); 373 if (childPid == 0) { 374 g_request->dumpMode = SPLIT_MODE; 375 DFXLOGI("The exec processdump pid(%{public}ld).", syscall(SYS_getpid)); 376 Exit(DFX_ExecDump()); 377 } else if (childPid < 0) { 378 DFXLOGE("[%{public}d]: Failed to fork child process, errno(%{public}d).", __LINE__, errno); 379 FillCrashExceptionAndReport(CRASH_SIGNAL_EFORK); 380 goto out; 381 } 382 WaitProcessExit(childPid, "processdump"); 383out: 384 RestoreDumpState(prevDumpableStatus, isTracerStatusModified); 385 return 0; 386} 387 388static int CloneAndDoProcessDump(void* arg) 389{ 390 (void)arg; 391 DFXLOGI("The clone thread(%{public}ld).", syscall(SYS_gettid)); 392 g_request->recycleTid = syscall(SYS_gettid); 393 return ForkAndExecProcessDump(); 394} 395 396static bool StartProcessdump(void) 397{ 398 uint64_t startTime = GetAbsTimeMilliSeconds(); 399 pid_t pid = ForkBySyscall(); 400 if (pid < 0) { 401 DFXLOGE("Failed to fork dummy processdump(%{public}d)", errno); 402 return false; 403 } else if (pid == 0) { 404 pid_t processDumpPid = ForkBySyscall(); 405 if (processDumpPid < 0) { 406 DFXLOGE("Failed to fork processdump(%{public}d)", errno); 407 _exit(0); 408 } else if (processDumpPid > 0) { 409 _exit(0); 410 } else { 411 uint64_t endTime; 412 int tid; 413 ParseSiValue(&g_request->siginfo, &endTime, &tid); 414 uint64_t curTime = GetAbsTimeMilliSeconds(); 415 DFXLOGW("start processdump, fork spend time %{public}" PRIu64 "ms", curTime - startTime); 416 if (endTime != 0) { 417 DFXLOGW("dump remain %{public}" PRId64 "ms", endTime - curTime); 418 } 419 if (endTime == 0 || endTime > curTime) { 420 DFX_ExecDump(); 421 } else { 422 DFXLOGW("current has spend all time, not execl processdump"); 423 } 424 _exit(0); 425 } 426 } 427 428 if (waitpid(pid, NULL, 0) <= 0) { 429 DFXLOGE("failed to wait dummy processdump(%{public}d)", errno); 430 } 431 return true; 432} 433 434static bool StartVMProcessUnwind(void) 435{ 436 uint32_t startTime = GetAbsTimeMilliSeconds(); 437 pid_t pid = ForkBySyscall(); 438 if (pid < 0) { 439 DFXLOGE("Failed to fork vm process(%{public}d)", errno); 440 return false; 441 } else if (pid == 0) { 442 pid_t vmPid = ForkBySyscall(); 443 if (vmPid == 0) { 444 DFXLOGW("start vm process, fork spend time %{public}" PRIu64 "ms", GetAbsTimeMilliSeconds() - startTime); 445 syscall(SYS_close, g_pipeFds[WRITE_TO_DUMP][0]); 446 pid_t pids[PID_MAX] = {0}; 447 pids[REAL_PROCESS_PID] = GetRealPid(); 448 pids[VIRTUAL_PROCESS_PID] = syscall(SYS_getpid); 449 OHOS_TEMP_FAILURE_RETRY(write(g_pipeFds[WRITE_TO_DUMP][1], pids, sizeof(pids))); 450 syscall(SYS_close, g_pipeFds[WRITE_TO_DUMP][1]); 451 452 uint32_t finishUnwind = OPE_FAIL; 453 syscall(SYS_close, g_pipeFds[READ_FORM_DUMP_TO_VIRTUAL][1]); 454 OHOS_TEMP_FAILURE_RETRY(read(g_pipeFds[READ_FORM_DUMP_TO_VIRTUAL][0], &finishUnwind, sizeof(finishUnwind))); 455 syscall(SYS_close, g_pipeFds[READ_FORM_DUMP_TO_VIRTUAL][0]); 456 DFXLOGI("processdump unwind finish, exit vm pid = %{public}d", pids[VIRTUAL_PROCESS_PID]); 457 _exit(0); 458 } else { 459 DFXLOGI("exit dummy vm process"); 460 _exit(0); 461 } 462 } 463 464 if (waitpid(pid, NULL, 0) <= 0) { 465 DFXLOGE("failed to wait dummy vm process(%{public}d)", errno); 466 } 467 return true; 468} 469 470static void CleanFd(int *pipeFd) 471{ 472 if (*pipeFd != -1) { 473 syscall(SYS_close, *pipeFd); 474 *pipeFd = -1; 475 } 476} 477 478static void CleanPipe(void) 479{ 480 for (size_t i = 0; i < PIPE_MAX; i++) { 481 CleanFd(&g_pipeFds[i][0]); 482 CleanFd(&g_pipeFds[i][1]); 483 } 484} 485 486static bool InitPipe(void) 487{ 488 for (int i = 0; i < PIPE_MAX; i++) { 489 if (syscall(SYS_pipe2, g_pipeFds[i], 0) == -1) { 490 DFXLOGE("create pipe fail, errno(%{public}d)", errno); 491 FillCrashExceptionAndReport(CRASH_SIGNAL_ECREATEPIPE); 492 CleanPipe(); 493 return false; 494 } 495 } 496 497 g_request->pmPipeFd[0] = g_pipeFds[READ_FROM_DUMP_TO_MAIN][0]; 498 g_request->pmPipeFd[1] = g_pipeFds[READ_FROM_DUMP_TO_MAIN][1]; 499 g_request->vmPipeFd[0] = g_pipeFds[READ_FORM_DUMP_TO_VIRTUAL][0]; 500 g_request->vmPipeFd[1] = g_pipeFds[READ_FORM_DUMP_TO_VIRTUAL][1]; 501 return true; 502} 503 504static bool ReadPipeTimeout(int fd, uint64_t timeout, uint32_t* value) 505{ 506 if (fd < 0 || value == NULL) { 507 return false; 508 } 509 struct pollfd pfds[1]; 510 pfds[0].fd = fd; 511 pfds[0].events = POLLIN; 512 513 uint64_t startTime = GetTimeMilliseconds(); 514 uint64_t endTime = startTime + timeout; 515 int pollRet = -1; 516 do { 517 pollRet = poll(pfds, 1, timeout); 518 if ((pollRet > 0) && (pfds[0].revents && POLLIN)) { 519 if (OHOS_TEMP_FAILURE_RETRY(read(fd, value, sizeof(uint32_t))) == 520 (long int)(sizeof(uint32_t))) { 521 return true; 522 } 523 } 524 525 uint64_t now = GetTimeMilliseconds(); 526 if (now >= endTime || now < startTime) { 527 break; 528 } else { 529 timeout = endTime - now; 530 } 531 } while (pollRet < 0 && errno == EINTR); 532 FillCrashExceptionAndReport(CRASH_SIGNAL_EREADPIPE); 533 DFXLOGE("read pipe failed , errno(%{public}d)", errno); 534 return false; 535} 536 537static bool ReadProcessDumpGetRegsMsg(void) 538{ 539 CleanFd(&g_pipeFds[READ_FROM_DUMP_TO_MAIN][1]); 540 541 DFXLOGI("start wait processdump read registers"); 542 const uint64_t readRegsTimeout = 5000; // 5s 543 uint32_t isFinishGetRegs = OPE_FAIL; 544 if (ReadPipeTimeout(g_pipeFds[READ_FROM_DUMP_TO_MAIN][0], readRegsTimeout, &isFinishGetRegs)) { 545 if (isFinishGetRegs == OPE_SUCCESS) { 546 DFXLOGI("processdump have get all registers ."); 547 return true; 548 } 549 } 550 551 return false; 552} 553 554static void ReadUnwindFinishMsg(int sig) 555{ 556 if (sig == SIGDUMP) { 557 return; 558 } 559 560 DFXLOGI("start wait processdump unwind"); 561 const uint64_t unwindTimeout = 10000; // 10s 562 uint32_t isExitAfterUnwind = OPE_CONTINUE; 563 if (ReadPipeTimeout(g_pipeFds[READ_FROM_DUMP_TO_MAIN][0], unwindTimeout, &isExitAfterUnwind)) { 564 DFXLOGI("processdump unwind finish"); 565 } else { 566 DFXLOGE("wait processdump unwind finish timeout"); 567 } 568} 569 570static int ProcessDump(int sig) 571{ 572 int prevDumpableStatus = prctl(PR_GET_DUMPABLE); 573 bool isTracerStatusModified = SetDumpState(); 574 575 if (!InitPipe()) { 576 return -1; 577 } 578 g_request->dumpMode = FUSION_MODE; 579 580 do { 581 uint64_t endTime; 582 int tid; 583 ParseSiValue(&g_request->siginfo, &endTime, &tid); 584 if (endTime != 0 && endTime <= GetAbsTimeMilliSeconds()) { 585 DFXLOGW("enter processdump has coat all time, just exit"); 586 break; 587 } 588 if (!StartProcessdump()) { 589 DFXLOGE("start processdump fail"); 590 break; 591 } 592 593 if (!ReadProcessDumpGetRegsMsg()) { 594 break; 595 } 596 597 if (!StartVMProcessUnwind()) { 598 DFXLOGE("start vm process unwind fail"); 599 break; 600 } 601 ReadUnwindFinishMsg(sig); 602 } while (false); 603 604 CleanPipe(); 605 RestoreDumpState(prevDumpableStatus, isTracerStatusModified); 606 return 0; 607} 608 609static void ForkAndDoProcessDump(int sig) 610{ 611 int prevDumpableStatus = prctl(PR_GET_DUMPABLE); 612 bool isTracerStatusModified = SetDumpState(); 613 int childPid = ForkBySyscall(); 614 if (childPid == 0) { 615 CloseFds(); 616 g_request->vmNsPid = syscall(SYS_getpid); 617 g_request->vmPid = GetRealPid(); 618 DFXLOGI("The vm pid(%{public}d:%{public}d).", g_request->vmPid, g_request->vmNsPid); 619 DFX_SetUpSigAlarmAction(); 620 alarm(ALARM_TIME_S); 621 _exit(ForkAndExecProcessDump()); 622 } else if (childPid < 0) { 623 DFXLOGE("[%{public}d]: Failed to fork child process, errno(%{public}d).", __LINE__, errno); 624 RestoreDumpState(prevDumpableStatus, isTracerStatusModified); 625 ForkAndExecProcessDump(); 626 return; 627 } 628 629 DFXLOGI("Start wait for VmProcess(%{public}d) exit.", childPid); 630 errno = 0; 631 if (!WaitProcessExit(childPid, "VmProcess") && 632 sig != SIGDUMP && 633 sig != SIGLEAK_STACK) { 634 DFXLOGI("Wait VmProcess(%{public}d) exit timeout in handling critical signal.", childPid); 635 FillCrashExceptionAndReport(CRASH_SIGNAL_EWAITEXIT); 636 // do not left vm process 637 kill(childPid, SIGKILL); 638 } 639 640 RestoreDumpState(prevDumpableStatus, isTracerStatusModified); 641} 642 643int DfxDumpRequest(int sig, struct ProcessDumpRequest *request, void *reservedChildStack) 644{ 645 int ret = 0; 646 if (request == NULL || reservedChildStack == NULL) { 647 DFXLOGE("Failed to DumpRequest because of error parameters!"); 648 return ret; 649 } 650 g_request = request; 651 g_reservedChildStack = reservedChildStack; 652 if (ProcessDump(sig) == 0) { 653 ret = sig == SIGDUMP || sig == SIGLEAK_STACK; 654 return ret; 655 } 656 657 if (sig != SIGDUMP) { 658 ret = sig == SIGLEAK_STACK ? true : false; 659 ForkAndDoProcessDump(sig); 660 } else { 661 ret = true; 662 int recycleTid = clone(CloneAndDoProcessDump, reservedChildStack,\ 663 CLONE_THREAD | CLONE_SIGHAND | CLONE_VM, NULL); 664 if (recycleTid == -1) { 665 DFXLOGE("Failed to clone thread for recycle dump process, errno(%{public}d)", errno); 666 } 667 } 668 return ret; 669} 670