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