• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <errno.h>
22 #include <fcntl.h>
23 #include <poll.h>
24 #include <pthread.h>
25 #include <sched.h>
26 #include <securec.h>
27 #include <signal.h>
28 #include <sigchain.h>
29 #include <stdatomic.h>
30 #include <stdbool.h>
31 #include <stdint.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <time.h>
35 #include <unistd.h>
36 #include <sys/capability.h>
37 #include <sys/mman.h>
38 #include <sys/prctl.h>
39 #include <sys/syscall.h>
40 #include <sys/time.h>
41 #include <sys/types.h>
42 #include <sys/uio.h>
43 #include <sys/wait.h>
44 #include <info/fatal_message.h>
45 #include <linux/capability.h>
46 
47 #include "dfx_cutil.h"
48 #include "dfx_define.h"
49 #include "dfx_dump_request.h"
50 #include "dfx_log.h"
51 #include "dfx_signalhandler_exception.h"
52 
53 #ifdef LOG_DOMAIN
54 #undef LOG_DOMAIN
55 #define LOG_DOMAIN 0xD002D11
56 #endif
57 
58 #ifdef LOG_TAG
59 #undef LOG_TAG
60 #define LOG_TAG "DfxSignalHandler"
61 #endif
62 
63 #ifndef F_SETPIPE_SZ
64 #define F_SETPIPE_SZ 1031
65 #endif
66 
67 #define NUMBER_SIXTYFOUR 64
68 #define INHERITABLE_OFFSET 32
69 #define HILOG_SNAPSHOT_LINES 1000
70 
71 static struct ProcessDumpRequest *g_request = NULL;
72 
73 static long g_blockExit = 0;
74 static long g_vmRealPid = 0;
75 static long g_unwindResult = 0;
76 static atomic_int g_dumpCount = 0;
77 static int g_dumpState = 0;
78 static pthread_mutex_t g_dumpMutex = PTHREAD_MUTEX_INITIALIZER;
79 static pthread_mutexattr_t g_dumpAttr;
80 
81 enum PIPE_FD_TYPE {
82     WRITE_TO_DUMP,
83     READ_FROM_DUMP_TO_CHILD,
84     PIPE_MAX,
85 };
86 
87 static int g_pipeFds[PIPE_MAX][2] = {
88     {-1, -1},
89     {-1, -1}
90 };
91 
92 static const int ALARM_TIME_S = 10;
93 static const uint32_t CRASH_SNAPSHOT_FLAG = 0x8;
94 static const int WAITPID_TIMEOUT = 3000; // 3000 : 3 sec timeout
95 enum DumpPreparationStage {
96     CREATE_PIPE_FAIL = 1,
97     SET_PIPE_LEN_FAIL,
98     WRITE_PIPE_FAIL,
99     INHERIT_CAP_FAIL,
100     EXEC_FAIL,
101 };
102 
103 static void CleanFd(int *pipeFd);
104 static void CleanPipe(void);
105 static bool InitPipe(void);
106 static bool ReadPipeTimeout(int fd, uint64_t timeout, uint32_t* value);
107 static bool ReadProcessDumpGetRegsMsg(void);
108 
109 #ifndef is_ohos_lite
110 DumpHiTraceIdStruct HiTraceChainGetId() __attribute__((weak));
111 #endif
112 
InitMutex(void)113 void __attribute__((constructor)) InitMutex(void)
114 {
115     pthread_mutexattr_init(&g_dumpAttr);
116     pthread_mutexattr_settype(&g_dumpAttr, PTHREAD_MUTEX_RECURSIVE);
117     pthread_mutex_init(&g_dumpMutex, &g_dumpAttr);
118 }
119 
DeinitMutex(void)120 void __attribute__((destructor)) DeinitMutex(void)
121 {
122     pthread_mutexattr_destroy(&g_dumpAttr);
123     pthread_mutex_destroy(&g_dumpMutex);
124 }
125 
ResetFlags(void)126 static void ResetFlags(void)
127 {
128     g_unwindResult = 0;
129     g_blockExit = 0;
130 }
131 
IsDumpSignal(int signo)132 static bool IsDumpSignal(int signo)
133 {
134     return signo == SIGDUMP || signo == SIGLEAK_STACK;
135 }
136 
FillCrashExceptionAndReport(const int err)137 static void FillCrashExceptionAndReport(const int err)
138 {
139     struct CrashDumpException exception;
140     (void)memset_s(&exception, sizeof(struct CrashDumpException), 0, sizeof(struct CrashDumpException));
141     exception.pid = g_request->pid;
142     exception.uid = (int32_t)(g_request->uid);
143     exception.error = err;
144     exception.time = (int64_t)(GetTimeMilliseconds());
145     if (strncpy_s(exception.message, sizeof(exception.message), GetCrashDescription(err),
146         sizeof(exception.message) - 1) != 0) {
147         DFXLOGE("strcpy exception message fail");
148         return;
149     }
150     ReportException(&exception);
151 }
152 
DFX_InheritCapabilities(void)153 int32_t DFX_InheritCapabilities(void)
154 {
155     struct __user_cap_header_struct capHeader;
156     (void)memset_s(&capHeader, sizeof(capHeader), 0, sizeof(capHeader));
157 
158     capHeader.version = _LINUX_CAPABILITY_VERSION_3;
159     capHeader.pid = 0;
160     struct __user_cap_data_struct capData[2];
161     if (capget(&capHeader, &capData[0]) == -1) {
162         DFXLOGE("Failed to get origin cap data");
163         return -1;
164     }
165 
166     capData[0].inheritable = capData[0].permitted;
167     capData[1].inheritable = capData[1].permitted;
168     if (capset(&capHeader, &capData[0]) == -1) {
169         DFXLOGE("Failed to set cap data, errno(%{public}d)", errno);
170         return -1;
171     }
172 
173     uint64_t ambCap = capData[0].inheritable;
174     ambCap = ambCap | (((uint64_t)capData[1].inheritable) << INHERITABLE_OFFSET);
175     for (size_t i = 0; i < NUMBER_SIXTYFOUR; i++) {
176         if (ambCap & ((uint64_t)1)) {
177             if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, 0) < 0) {
178                 DFXLOGE("Failed to change the ambient capability set, errno(%{public}d)", errno);
179             }
180         }
181         ambCap = ambCap >> 1;
182     }
183     return 0;
184 }
185 
186 static const int SIGCHAIN_DUMP_SIGNAL_LIST[] = {
187     SIGDUMP, SIGLEAK_STACK
188 };
189 
190 static const int SIGCHAIN_CRASH_SIGNAL_LIST[] = {
191     SIGILL, SIGABRT, SIGBUS, SIGFPE,
192     SIGSEGV, SIGSTKFLT, SIGSYS, SIGTRAP
193 };
194 
SetInterestedSignalMasks(int how)195 static void SetInterestedSignalMasks(int how)
196 {
197     sigset_t set;
198     sigemptyset(&set);
199     for (size_t i = 0; i < sizeof(SIGCHAIN_DUMP_SIGNAL_LIST) / sizeof(SIGCHAIN_DUMP_SIGNAL_LIST[0]); i++) {
200         sigaddset(&set, SIGCHAIN_DUMP_SIGNAL_LIST[i]);
201     }
202     for (size_t i = 0; i < sizeof(SIGCHAIN_CRASH_SIGNAL_LIST) / sizeof(SIGCHAIN_CRASH_SIGNAL_LIST[0]); i++) {
203         sigaddset(&set, SIGCHAIN_CRASH_SIGNAL_LIST[i]);
204     }
205     sigprocmask(how, &set, NULL);
206 }
207 
CloseFds(void)208 static void CloseFds(void)
209 {
210     const int startIndex = 128;  // 128 : avoid set pipe fail
211     const int closeFdCount = 1024;
212     for (int i = startIndex; i < closeFdCount; i++) {
213         syscall(SYS_close, i);
214     }
215 }
216 
DFX_SetUpEnvironment(void)217 static void DFX_SetUpEnvironment(void)
218 {
219     // clear stdout and stderr
220     int devNull = OHOS_TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
221     if (devNull < 0) {
222         DFXLOGE("Failed to open dev/null.");
223         return;
224     }
225 
226     OHOS_TEMP_FAILURE_RETRY(dup2(devNull, STDOUT_FILENO));
227     OHOS_TEMP_FAILURE_RETRY(dup2(devNull, STDERR_FILENO));
228     syscall(SYS_close, devNull);
229     SetInterestedSignalMasks(SIG_BLOCK);
230 }
231 
DFX_SetUpSigAlarmAction(void)232 static void DFX_SetUpSigAlarmAction(void)
233 {
234     if (signal(SIGALRM, SIG_DFL) == SIG_ERR) {
235         DFXLOGW("Default signal alarm error!");
236     }
237     sigset_t set;
238     sigemptyset(&set);
239     sigaddset(&set, SIGALRM);
240     sigprocmask(SIG_UNBLOCK, &set, NULL);
241 }
242 
DFX_ExecDump(void)243 static int DFX_ExecDump(void)
244 {
245     DFX_SetUpEnvironment();
246     DFX_SetUpSigAlarmAction();
247     alarm(ALARM_TIME_S);
248     int pipefd[2] = {-1, -1};
249     // create pipe for passing request to processdump
250     pipefd[0] = g_pipeFds[WRITE_TO_DUMP][0];
251     pipefd[1] = g_pipeFds[WRITE_TO_DUMP][1];
252 
253     ssize_t writeLen = (long)(sizeof(struct ProcessDumpRequest));
254     if (fcntl(pipefd[1], F_SETPIPE_SZ, writeLen) < writeLen) {
255         DFXLOGE("Failed to set pipe buffer size, errno(%{public}d).", errno);
256         return SET_PIPE_LEN_FAIL;
257     }
258 
259     struct iovec iovs[1] = {
260         {
261             .iov_base = g_request,
262             .iov_len = sizeof(struct ProcessDumpRequest)
263         },
264     };
265     if (OHOS_TEMP_FAILURE_RETRY(writev(pipefd[1], iovs, 1)) != writeLen) {
266         DFXLOGE("Failed to write pipe, errno(%{public}d)", errno);
267         return WRITE_PIPE_FAIL;
268     }
269     OHOS_TEMP_FAILURE_RETRY(dup2(pipefd[0], STDIN_FILENO));
270     if (pipefd[0] != STDIN_FILENO) {
271         syscall(SYS_close, pipefd[0]);
272     }
273     syscall(SYS_close, pipefd[1]);
274 
275     if (DFX_InheritCapabilities() != 0) {
276         DFXLOGE("Failed to inherit Capabilities from parent.");
277         FillCrashExceptionAndReport(CRASH_SIGNAL_EINHERITCAP);
278         return INHERIT_CAP_FAIL;
279     }
280     DFXLOGI("execl processdump.");
281     execl(PROCESSDUMP_PATH, "processdump", "-signalhandler", NULL);
282     DFXLOGE("Failed to execl processdump, errno(%{public}d)", errno);
283     FillCrashExceptionAndReport(CRASH_SIGNAL_EEXECL);
284     return errno;
285 }
286 
ForkBySyscall(void)287 static pid_t ForkBySyscall(void)
288 {
289 #ifdef SYS_fork
290     return syscall(SYS_fork);
291 #else
292     return syscall(SYS_clone, SIGCHLD, 0);
293 #endif
294 }
295 
DFX_SetDumpableState(void)296 bool DFX_SetDumpableState(void)
297 {
298     pthread_mutex_lock(&g_dumpMutex);
299     int expected = 0;
300     if (atomic_compare_exchange_strong(&g_dumpCount, &expected, 1)) {
301         g_dumpState = prctl(PR_GET_DUMPABLE);
302         if (prctl(PR_SET_DUMPABLE, 1) != 0) {
303             DFXLOGE("Failed to set dumpable, errno(%{public}d).", errno);
304             atomic_fetch_sub(&g_dumpCount, 1);
305             pthread_mutex_unlock(&g_dumpMutex);
306             return false;
307         }
308     } else {
309         atomic_fetch_add(&g_dumpCount, 1);
310     }
311     pthread_mutex_unlock(&g_dumpMutex);
312     return true;
313 }
314 
DFX_RestoreDumpableState(void)315 void DFX_RestoreDumpableState(void)
316 {
317     pthread_mutex_lock(&g_dumpMutex);
318     if (atomic_load(&g_dumpCount) > 0) {
319         atomic_fetch_sub(&g_dumpCount, 1);
320         if (atomic_load(&g_dumpCount) == 0) {
321             prctl(PR_SET_DUMPABLE, g_dumpState);
322         }
323     }
324     pthread_mutex_unlock(&g_dumpMutex);
325 }
326 
SetDumpState(void)327 static bool SetDumpState(void)
328 {
329     if (DFX_SetDumpableState() == false) {
330         return false;
331     }
332     if (prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY) != 0) {
333         if (errno != EINVAL) {
334             DFXLOGE("Failed to set ptracer, errno(%{public}d).", errno);
335             return false;
336         }
337     }
338     return true;
339 }
340 
RestoreDumpState(bool isTracerStatusModified)341 static void RestoreDumpState(bool isTracerStatusModified)
342 {
343     DFX_RestoreDumpableState();
344     if (isTracerStatusModified == true) {
345         prctl(PR_SET_PTRACER, 0);
346     }
347 }
348 
SafeDelayOneMillSec(void)349 static void SafeDelayOneMillSec(void)
350 {
351     struct timespec ts;
352     ts.tv_sec = 0;
353     ts.tv_nsec = 1000000; // 1000000 : 1ms
354     OHOS_TEMP_FAILURE_RETRY(nanosleep(&ts, &ts));
355 }
356 
WaitProcessExitTimeout(pid_t pid,int timeoutMs)357 static bool WaitProcessExitTimeout(pid_t pid, int timeoutMs)
358 {
359     if (timeoutMs <= 0) {
360         DFXLOGE("Invalid timeout value(%{public}d)", timeoutMs);
361         return false;
362     }
363     int status;
364     while (timeoutMs > 0) {
365         int res = waitpid(pid, &status, WNOHANG);
366         if (res > 0) {
367             break;
368         } else if (res < 0) {
369             DFXLOGE("failed to wait dummy, error(%{public}d)", errno);
370             break;
371         }
372         SafeDelayOneMillSec();
373         timeoutMs--;
374         if (timeoutMs == 0) {
375             DFXLOGI("waitpid %{public}d timeout", pid);
376             kill(pid, SIGKILL);
377             FillCrashExceptionAndReport(CRASH_SIGNAL_EWAITPIDTIMEOUT);
378             return false;
379         }
380     }
381     if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
382         return true;
383     }
384     DFXLOGE("dummy exit with error(%{public}d)", WEXITSTATUS(status));
385     return false;
386 }
387 
StartProcessdump(void)388 static bool StartProcessdump(void)
389 {
390     uint64_t startTime = GetAbsTimeMilliSecondsCInterce();
391     pid_t pid = ForkBySyscall();
392     if (pid < 0) {
393         DFXLOGE("Failed to fork dummy processdump(%{public}d)", errno);
394         return false;
395     } else if (pid == 0) {
396         if (!InitPipe()) {
397             DFXLOGE("init pipe fail");
398             syscall(SYS_exit, errno);
399         }
400         pid_t processDumpPid = ForkBySyscall();
401         if (processDumpPid < 0) {
402             DFXLOGE("Failed to fork processdump(%{public}d)", errno);
403             syscall(SYS_exit, errno);
404         } else if (processDumpPid > 0) {
405             int ret = ReadProcessDumpGetRegsMsg() == true ? 0 : errno;
406             DFXLOGI("exit the processdump parent process.");
407             syscall(SYS_exit, ret);
408         } else {
409             uint64_t endTime;
410             int tid;
411             ParseSiValue(&g_request->siginfo, &endTime, &tid);
412             uint64_t curTime = GetAbsTimeMilliSecondsCInterce();
413             DFXLOGI("start processdump, fork spend time %{public}" PRIu64 "ms", curTime - startTime);
414             if (endTime != 0) {
415                 DFXLOGI("dump remain %{public}" PRId64 "ms", endTime - curTime);
416             }
417             if (endTime == 0 || endTime > curTime) {
418                 g_request->blockCrashExitAddr = (intptr_t)&g_blockExit;
419                 g_request->vmProcRealPidAddr = (intptr_t)&g_vmRealPid;
420                 g_request->unwindResultAddr = (intptr_t)&g_unwindResult;
421                 DFX_ExecDump();
422             } else {
423                 DFXLOGI("current has spend all time, not execl processdump");
424             }
425             syscall(SYS_exit, 0);
426         }
427     }
428     return WaitProcessExitTimeout(pid, WAITPID_TIMEOUT);
429 }
430 
StartVMProcessUnwind(void)431 static bool StartVMProcessUnwind(void)
432 {
433     uint64_t startTime = GetAbsTimeMilliSecondsCInterce();
434     pid_t pid = ForkBySyscall();
435     if (pid < 0) {
436         DFXLOGE("Failed to fork vm process(%{public}d)", errno);
437         return false;
438     }
439     if (pid == 0) {
440         pid_t vmPid = ForkBySyscall();
441         if (vmPid == 0) {
442             DFXLOGI("start vm process, fork spend time %{public}" PRIu64 "ms",
443                     GetAbsTimeMilliSecondsCInterce() - startTime);
444             g_vmRealPid = GetRealPid();
445             DFXLOGI("vm prorcecc read pid = %{public}ld", g_vmRealPid);
446             syscall(SYS_exit, 0);
447         } else {
448             DFXLOGI("exit dummy vm process");
449             syscall(SYS_exit, 0);
450         }
451     }
452 
453     return WaitProcessExitTimeout(pid, WAITPID_TIMEOUT);
454 }
455 
CleanFd(int * pipeFd)456 static void CleanFd(int *pipeFd)
457 {
458     if (*pipeFd != -1) {
459         syscall(SYS_close, *pipeFd);
460         *pipeFd = -1;
461     }
462 }
463 
CleanPipe(void)464 static void CleanPipe(void)
465 {
466     for (size_t i = 0; i < PIPE_MAX; i++) {
467         CleanFd(&g_pipeFds[i][0]);
468         CleanFd(&g_pipeFds[i][1]);
469     }
470 }
471 
InitPipe(void)472 static bool InitPipe(void)
473 {
474     bool ret = true;
475     for (int i = 0; i < PIPE_MAX; i++) {
476         if (syscall(SYS_pipe2, g_pipeFds[i], 0) == -1) {
477             DFXLOGE("create pipe fail, errno(%{public}d)", errno);
478             ret = false;
479             CleanPipe();
480             break;
481         }
482     }
483     if (!ret) {
484         CloseFds();
485         for (int i = 0; i < PIPE_MAX; i++) {
486             if (syscall(SYS_pipe2, g_pipeFds[i], 0) == -1) {
487                 DFXLOGE("create pipe fail again, errno(%{public}d)", errno);
488                 FillCrashExceptionAndReport(CRASH_SIGNAL_ECREATEPIPE);
489                 CleanPipe();
490                 return false;
491             }
492         }
493     }
494 
495     g_request->childPipeFd[0] = g_pipeFds[READ_FROM_DUMP_TO_CHILD][0];
496     g_request->childPipeFd[1] = g_pipeFds[READ_FROM_DUMP_TO_CHILD][1];
497     return true;
498 }
499 
ReadPipeTimeout(int fd,uint64_t timeout,uint32_t * value)500 static bool ReadPipeTimeout(int fd, uint64_t timeout, uint32_t* value)
501 {
502     if (fd < 0 || value == NULL) {
503         return false;
504     }
505     struct pollfd pfds[1];
506     pfds[0].fd = fd;
507     pfds[0].events = POLLIN;
508 
509     uint64_t startTime = GetTimeMilliseconds();
510     uint64_t endTime = startTime + timeout;
511     int pollRet = -1;
512     do {
513         pollRet = poll(pfds, 1, timeout);
514         if ((pollRet > 0) && (pfds[0].revents && POLLIN)) {
515             if (OHOS_TEMP_FAILURE_RETRY(read(fd, value, sizeof(uint32_t))) ==
516                 (long int)(sizeof(uint32_t))) {
517                 return true;
518             }
519         }
520 
521         uint64_t now = GetTimeMilliseconds();
522         if (now >= endTime || now < startTime) {
523             break;
524         } else {
525             timeout = endTime - now;
526         }
527     } while (pollRet < 0 && errno == EINTR);
528     FillCrashExceptionAndReport(CRASH_SIGNAL_EREADPIPE);
529     DFXLOGE("read pipe failed , errno(%{public}d)", errno);
530     return false;
531 }
532 
ReadProcessDumpGetRegsMsg(void)533 static bool ReadProcessDumpGetRegsMsg(void)
534 {
535     CleanFd(&g_pipeFds[READ_FROM_DUMP_TO_CHILD][1]);
536 
537     DFXLOGI("start wait processdump read registers");
538     const uint64_t readRegsTimeout = 5000; // 5s
539     uint32_t isFinishGetRegs = OPE_FAIL;
540     if (ReadPipeTimeout(g_pipeFds[READ_FROM_DUMP_TO_CHILD][0], readRegsTimeout, &isFinishGetRegs)) {
541         if (isFinishGetRegs == OPE_SUCCESS) {
542             DFXLOGI("processdump have get all registers .");
543             return true;
544         }
545     }
546 
547     return false;
548 }
549 
SetKernelSnapshot(bool enable)550 static void SetKernelSnapshot(bool enable)
551 {
552     const char *filePath = "/proc/self/unexpected_die_catch";
553     if (access(filePath, F_OK) < 0) {
554         return;
555     }
556     int dieCatchFd = open(filePath, O_RDWR);
557     if (dieCatchFd < 0) {
558         DFXLOGE("Failed to open unexpecterd_die_catch %{public}d", errno);
559         return;
560     }
561     do {
562         char val[10] = {0}; // 10 : to save diecatch val
563         if (read(dieCatchFd, val, sizeof(val)) < 0) {
564             DFXLOGE("Failed to read unexpecterd_die_catch %{public}d", errno);
565             break;
566         }
567         if (lseek(dieCatchFd, 0, SEEK_SET) < 0) {
568             DFXLOGE("Failed to lseek unexpecterd_die_catch %{public}d", errno);
569             break;
570         }
571 
572         uint32_t num = (uint32_t)strtoul(val, NULL, 16); // 16 : val is hex
573         if (errno == ERANGE) {
574             DFXLOGE("Failed to cast unexpecterd_die_catch val to int %{public}d", errno);
575             break;
576         }
577         if (enable) {
578             num |= CRASH_SNAPSHOT_FLAG;
579         } else {
580             num &= (~CRASH_SNAPSHOT_FLAG);
581         }
582 
583         (void)memset_s(val, sizeof(val), 0, sizeof(val));
584         if (snprintf_s(val, sizeof(val), sizeof(val) - 1, "0x%x", num) < 0) {
585             DFXLOGE("Failed to format unexpecterd_die_catch val %{public}d", errno);
586             break;
587         }
588         if (write(dieCatchFd, val, sizeof(val)) < 0) {
589             DFXLOGE("Failed to write unexpecterd_die_catch %{public}d", errno);
590         }
591     } while (false);
592     syscall(SYS_close, dieCatchFd);
593 }
594 
ReadUnwindFinishMsg(int signo)595 static void ReadUnwindFinishMsg(int signo)
596 {
597     if (IsDumpSignal(signo)) {
598         return;
599     }
600 
601     DFXLOGI("crash processdump unwind finish, unwind success Flag %{public}ld, blockFlag %{public}ld",
602         g_unwindResult, g_blockExit);
603     if (g_unwindResult == CRASH_UNWIND_SUCCESS_FLAG) {
604         SetKernelSnapshot(false);
605     }
606     if (g_blockExit == CRASH_BLOCK_EXIT_FLAG) {
607         syscall(SYS_tgkill, g_request->nsPid, g_request->tid, SIGSTOP);
608     }
609 }
610 
ProcessDump(int signo)611 static int ProcessDump(int signo)
612 {
613     bool isTracerStatusModified = SetDumpState();
614     if (!IsDumpSignal(signo)) {
615         ResetFlags();
616         SetKernelSnapshot(true);
617 #ifndef is_ohos_lite
618         if (HiTraceChainGetId != NULL) {
619             DumpHiTraceIdStruct hitraceChainId = HiTraceChainGetId();
620             if (memcpy_s(&g_request->hitraceId, sizeof(g_request->hitraceId),
621                          &hitraceChainId, sizeof(hitraceChainId)) != 0) {
622                 DFXLOGE("memcpy hitrace fail");
623             }
624         }
625         HiLogRecordSnapshot(HILOG_SNAPSHOT_LINES, g_request->timeStamp);
626 #endif
627     }
628 
629     do {
630         uint64_t endTime;
631         int tid;
632         ParseSiValue(&g_request->siginfo, &endTime, &tid);
633         if (endTime != 0 && endTime <= GetAbsTimeMilliSecondsCInterce()) {
634             DFXLOGI("enter processdump has coat all time, just exit");
635             break;
636         }
637         if (!StartProcessdump()) {
638             DFXLOGE("start processdump fail");
639             break;
640         }
641 
642         if (!StartVMProcessUnwind()) {
643             DFXLOGE("start vm process unwind fail");
644             break;
645         }
646         ReadUnwindFinishMsg(signo);
647     } while (false);
648 
649     RestoreDumpState(isTracerStatusModified);
650     return 0;
651 }
652 
DfxDumpRequest(int signo,struct ProcessDumpRequest * request)653 void DfxDumpRequest(int signo, struct ProcessDumpRequest *request)
654 {
655     if (request == NULL) {
656         DFXLOGE("Failed to DumpRequest because of error parameters!");
657         return;
658     }
659     g_request = request;
660     ProcessDump(signo);
661 }
662