• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 #include "dfx_signal_handler.h"
16 
17 #ifndef _GNU_SOURCE
18 #define _GNU_SOURCE 1
19 #endif
20 
21 #include <fcntl.h>
22 #include <pthread.h>
23 #include <sched.h>
24 #include <signal.h>
25 #include <sigchain.h>
26 #include <stdint.h>
27 #include <stdio.h>
28 #include <sys/capability.h>
29 #include <sys/mman.h>
30 #include <sys/prctl.h>
31 #include <sys/syscall.h>
32 #include <sys/time.h>
33 #include <sys/types.h>
34 #include <sys/uio.h>
35 #include <sys/wait.h>
36 #include <time.h>
37 #include <unistd.h>
38 #include "dfx_define.h"
39 #include "dfx_dump_request.h"
40 #include "errno.h"
41 #include "linux/capability.h"
42 #include "stdbool.h"
43 #include "string.h"
44 #ifndef DFX_SIGNAL_LIBC
45 #include <securec.h>
46 #include "dfx_cutil.h"
47 #include "dfx_log.h"
48 #else
49 #include "musl_cutil.h"
50 #include "musl_log.h"
51 #endif
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 #if defined (__LP64__)
64 #define RESERVED_CHILD_STACK_SIZE (32 * 1024)  // 32K
65 #else
66 #define RESERVED_CHILD_STACK_SIZE (16 * 1024)  // 16K
67 #endif
68 
69 #define BOOL int
70 #define TRUE 1
71 #define FALSE 0
72 
73 #ifndef NSIG
74 #define NSIG 64
75 #endif
76 
77 #ifndef F_SETPIPE_SZ
78 #define F_SETPIPE_SZ 1031
79 #endif
80 
81 #define NUMBER_SIXTYFOUR 64
82 #define INHERITABLE_OFFSET 32
83 
84 #ifndef __MUSL__
InitHandler(void)85 void __attribute__((constructor)) InitHandler(void)
86 {
87     DFX_InstallSignalHandler();
88 }
89 #endif
90 
91 static struct ProcessDumpRequest g_request;
92 static void *g_reservedChildStack = NULL;
93 static pthread_mutex_t g_signalHandlerMutex = PTHREAD_MUTEX_INITIALIZER;
94 static int g_pipefd[2] = {-1, -1};
95 static BOOL g_hasInit = FALSE;
96 static const int SIGNALHANDLER_TIMEOUT = 10000; // 10000 us
97 static const int ALARM_TIME_S = 10;
98 static int g_prevHandledSignal = SIGDUMP;
99 static struct sigaction g_oldSigactionList[NSIG] = {};
100 static thread_local ThreadInfoCallBack threadInfoCallBack = NULL;
101 enum DumpPreparationStage {
102     CREATE_PIPE_FAIL = 1,
103     SET_PIPE_LEN_FAIL,
104     WRITE_PIPE_FAIL,
105     INHERIT_CAP_FAIL,
106     EXEC_FAIL,
107 };
108 
109 TraceInfo HiTraceGetId(void) __attribute__((weak));
FillTraceIdLocked(struct ProcessDumpRequest * request)110 static void FillTraceIdLocked(struct ProcessDumpRequest* request)
111 {
112     if (HiTraceGetId == NULL || request == NULL) {
113         return;
114     }
115 
116     TraceInfo id = HiTraceGetId();
117     memcpy(&(request->traceInfo), &id, sizeof(TraceInfo));
118 }
119 
120 const char* GetLastFatalMessage(void) __attribute__((weak));
SetThreadInfoCallback(ThreadInfoCallBack func)121 void SetThreadInfoCallback(ThreadInfoCallBack func)
122 {
123     threadInfoCallBack = func;
124 }
FillLastFatalMessageLocked(int32_t sig,void * context)125 static void FillLastFatalMessageLocked(int32_t sig, void *context)
126 {
127     if (sig != SIGABRT && threadInfoCallBack != NULL) {
128         threadInfoCallBack(g_request.lastFatalMessage, sizeof(g_request.lastFatalMessage), context);
129         return;
130     }
131 
132     if (GetLastFatalMessage == NULL) {
133         DFXLOG_ERROR("Could not find GetLastFatalMessage func");
134         return;
135     }
136 
137     const char* lastFatalMessage = GetLastFatalMessage();
138     if (lastFatalMessage == NULL) {
139         DFXLOG_ERROR("Could not find last message");
140         return;
141     }
142 
143     size_t len = strlen(lastFatalMessage);
144     if (len > MAX_FATAL_MSG_SIZE) {
145         DFXLOG_ERROR("Last message is longer than MAX_FATAL_MSG_SIZE");
146         return;
147     }
148 
149     (void)strncpy(g_request.lastFatalMessage, lastFatalMessage, sizeof(g_request.lastFatalMessage) - 1);
150 }
151 
FillDumpRequest(int sig,siginfo_t * si,void * context)152 static void FillDumpRequest(int sig, siginfo_t *si, void *context)
153 {
154     memset(&g_request, 0, sizeof(g_request));
155     g_request.type = sig;
156     g_request.pid = GetRealPid();
157     g_request.nsPid = syscall(SYS_getpid);
158     g_request.tid = syscall(SYS_gettid);
159     g_request.uid = getuid();
160     g_request.reserved = 0;
161     g_request.timeStamp = GetTimeMilliseconds();
162 
163     GetThreadNameByTid(g_request.tid, g_request.threadName, sizeof(g_request.threadName));
164     GetProcessName(g_request.processName, sizeof(g_request.processName));
165 
166     memcpy(&(g_request.siginfo), si, sizeof(siginfo_t));
167     memcpy(&(g_request.context), context, sizeof(ucontext_t));
168 
169     FillTraceIdLocked(&g_request);
170     FillLastFatalMessageLocked(sig, context);
171 }
172 
InheritCapabilities(void)173 static int32_t InheritCapabilities(void)
174 {
175     struct __user_cap_header_struct capHeader;
176     memset(&capHeader, 0, sizeof(capHeader));
177 
178     capHeader.version = _LINUX_CAPABILITY_VERSION_3;
179     capHeader.pid = 0;
180     struct __user_cap_data_struct capData[2];
181     if (capget(&capHeader, &capData[0]) == -1) {
182         DFXLOG_ERROR("Failed to get origin cap data");
183         return -1;
184     }
185 
186     capData[0].inheritable = capData[0].permitted;
187     capData[1].inheritable = capData[1].permitted;
188     if (capset(&capHeader, &capData[0]) == -1) {
189         DFXLOG_ERROR("Failed to set cap data");
190         return -1;
191     }
192 
193     uint64_t ambCap = capData[0].inheritable;
194     ambCap = ambCap | (((uint64_t)capData[1].inheritable) << INHERITABLE_OFFSET);
195     for (size_t i = 0; i < NUMBER_SIXTYFOUR; i++) {
196         if (ambCap & ((uint64_t)1)) {
197             (void)prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, 0);
198         }
199         ambCap = ambCap >> 1;
200     }
201     return 0;
202 }
203 
204 static const int SIGCHAIN_SIGNAL_LIST[] = {
205     SIGABRT, SIGBUS, SIGDUMP, SIGFPE,
206     SIGSEGV, SIGSTKFLT, SIGSYS, SIGTRAP,
207 };
208 static const int SIGACTION_SIGNAL_LIST[] = {
209     SIGILL,
210 };
211 
SetInterestedSignalMasks(int how)212 static void SetInterestedSignalMasks(int how)
213 {
214     sigset_t set;
215     sigemptyset(&set);
216     for (size_t i = 0; i < sizeof(SIGCHAIN_SIGNAL_LIST) / sizeof(SIGCHAIN_SIGNAL_LIST[0]); i++) {
217         sigaddset(&set, SIGCHAIN_SIGNAL_LIST[i]);
218     }
219     sigprocmask(how, &set, NULL);
220 }
221 
DFX_SetUpEnvironment()222 static void DFX_SetUpEnvironment()
223 {
224     // avoiding fd exhaust
225     const int closeFdCount = 1024;
226     for (int i = 0; i < closeFdCount; i++) {
227         syscall(SYS_close, i);
228     }
229     // clear stdout and stderr
230     int devNull = OHOS_TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
231     if (devNull < 0) {
232         DFXLOG_ERROR("Failed to open dev/null.");
233         return;
234     }
235 
236     OHOS_TEMP_FAILURE_RETRY(dup2(devNull, STDOUT_FILENO));
237     OHOS_TEMP_FAILURE_RETRY(dup2(devNull, STDERR_FILENO));
238     syscall(SYS_close, devNull);
239     SetInterestedSignalMasks(SIG_BLOCK);
240 }
241 
DFX_SetUpSigAlarmAction(void)242 static void DFX_SetUpSigAlarmAction(void)
243 {
244     if (signal(SIGALRM, SIG_DFL) == SIG_ERR) {
245         DFXLOG_WARN("Default signal alarm error!");
246     }
247     sigset_t set;
248     sigemptyset(&set);
249     sigaddset(&set, SIGALRM);
250     sigprocmask(SIG_UNBLOCK, &set, NULL);
251 }
252 
DFX_ExecDump(void)253 static int DFX_ExecDump(void)
254 {
255     DFX_SetUpEnvironment();
256     DFX_SetUpSigAlarmAction();
257     alarm(ALARM_TIME_S);
258     // create pipe for passing request to processdump
259     if (pipe(g_pipefd) != 0) {
260         DFXLOG_ERROR("Failed to create pipe for transfering context.");
261         return CREATE_PIPE_FAIL;
262     }
263     ssize_t writeLen = (long)(sizeof(struct ProcessDumpRequest));
264     if (fcntl(g_pipefd[1], F_SETPIPE_SZ, writeLen) < writeLen) {
265         DFXLOG_ERROR("Failed to set pipe buffer size.");
266         return SET_PIPE_LEN_FAIL;
267     }
268 
269     struct iovec iovs[1] = {
270         {
271             .iov_base = &g_request,
272             .iov_len = sizeof(struct ProcessDumpRequest)
273         },
274     };
275     ssize_t realWriteSize = OHOS_TEMP_FAILURE_RETRY(writev(g_pipefd[1], iovs, 1));
276     if ((ssize_t)writeLen != realWriteSize) {
277         DFXLOG_ERROR("Failed to write pipe.");
278         return WRITE_PIPE_FAIL;
279     }
280     OHOS_TEMP_FAILURE_RETRY(dup2(g_pipefd[0], STDIN_FILENO));
281     if (g_pipefd[0] != STDIN_FILENO) {
282         syscall(SYS_close, g_pipefd[0]);
283     }
284     syscall(SYS_close, g_pipefd[1]);
285 
286     if (InheritCapabilities() != 0) {
287         DFXLOG_ERROR("Failed to inherit Capabilities from parent.");
288         return INHERIT_CAP_FAIL;
289     }
290     DFXLOG_INFO("execl processdump.");
291 #ifdef DFX_LOG_USE_HILOG_BASE
292     execl("/system/bin/processdump", "processdump", "-signalhandler", NULL);
293 #else
294     execl("/bin/processdump", "processdump", "-signalhandler", NULL);
295 #endif
296     DFXLOG_ERROR("Failed to execl processdump, errno: %d(%s)", errno, strerror(errno));
297     return errno;
298 }
299 
IsMainThread(void)300 static bool IsMainThread(void)
301 {
302     if (syscall(SYS_getpid) == 1) {
303         if (syscall(SYS_gettid) == 1) {
304             return true;
305         }
306     } else {
307         if (syscall(SYS_getpid) == syscall(SYS_gettid)) {
308             return true;
309         }
310     }
311     return false;
312 }
313 
ExitIfSandboxPid(int sig)314 static void ExitIfSandboxPid(int sig)
315 {
316     // real init will not handle crash signal,
317     // crash in pid namespace may not exit even if rethrow the signal, use exit instead
318     if (syscall(SYS_getpid) == 1) {
319         DFXLOG_ERROR("Sandbox process is about to exit with signal %d.", sig);
320         _exit(sig);
321     }
322 }
323 
ResetAndRethrowSignalIfNeed(int sig,siginfo_t * si)324 static void ResetAndRethrowSignalIfNeed(int sig, siginfo_t *si)
325 {
326     if (sig == SIGDUMP) {
327         return;
328     }
329 
330     if (g_oldSigactionList[sig].sa_sigaction == NULL) {
331         signal(sig, SIG_DFL);
332     } else if (sigaction(sig, &(g_oldSigactionList[sig]), NULL) != 0) {
333         DFXLOG_ERROR("Failed to reset sig(%d).", sig);
334         signal(sig, SIG_DFL);
335     }
336 
337     if (syscall(SYS_rt_tgsigqueueinfo, syscall(SYS_getpid), syscall(SYS_gettid), sig, si) != 0) {
338         DFXLOG_ERROR("Failed to rethrow sig(%d), errno(%d).", sig, errno);
339     } else {
340         DFXLOG_INFO("Current process(%d) rethrow sig(%d).", syscall(SYS_getpid), sig);
341     }
342 }
343 
PauseMainThreadHandler(int sig)344 static void PauseMainThreadHandler(int sig)
345 {
346     DFXLOG_INFO("Crash(%d) in child thread(%d), lock main thread.", sig, syscall(SYS_gettid));
347     // only work when subthread crash and send SIGDUMP to mainthread.
348     pthread_mutex_lock(&g_signalHandlerMutex);
349     pthread_mutex_unlock(&g_signalHandlerMutex);
350     DFXLOG_INFO("Crash in child thread(%d), exit main thread.", syscall(SYS_gettid));
351 }
352 
BlockMainThreadIfNeed(int sig)353 static void BlockMainThreadIfNeed(int sig)
354 {
355     if (IsMainThread() || (sig == SIGDUMP)) {
356         return;
357     }
358 
359     DFXLOG_INFO("Try block main thread.");
360     (void)signal(SIGQUIT, PauseMainThreadHandler);
361     if (syscall(SYS_tgkill, syscall(SYS_getpid), syscall(SYS_getpid), SIGQUIT) != 0) {
362         DFXLOG_ERROR("Failed to send SIGQUIT to main thread, errno(%d).", errno);
363     }
364 }
365 
ForkBySyscall(void)366 static pid_t ForkBySyscall(void)
367 {
368 #ifdef SYS_fork
369     return syscall(SYS_fork);
370 #else
371     return syscall(SYS_clone, SIGCHLD, 0);
372 #endif
373 }
374 
SetDumpState(void)375 static bool SetDumpState(void)
376 {
377     if (prctl(PR_SET_DUMPABLE, 1) != 0) {
378         DFXLOG_ERROR("Failed to set dumpable, errno(%d).", errno);
379         return false;
380     }
381 
382     if (prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY) != 0) {
383         if (errno != EINVAL) {
384             DFXLOG_ERROR("Failed to set ptracer, errno(%d).", errno);
385             return false;
386         }
387     }
388     return true;
389 }
390 
RestoreDumpState(int prevState,bool isTracerStatusModified)391 static void RestoreDumpState(int prevState, bool isTracerStatusModified)
392 {
393     prctl(PR_SET_DUMPABLE, prevState);
394     if (isTracerStatusModified == true) {
395         prctl(PR_SET_PTRACER, 0);
396     }
397 }
398 
SetSelfThreadParam(const char * name,int priority)399 static void SetSelfThreadParam(const char* name, int priority)
400 {
401     pthread_setname_np(pthread_self(), name);
402     struct sched_param schedParam;
403     schedParam.sched_priority = priority;
404     pthread_setschedparam(pthread_self(), SCHED_FIFO, &schedParam);
405 }
406 
WaitProcessExit(int childPid,const char * name)407 static bool WaitProcessExit(int childPid, const char* name)
408 {
409     int ret = -1;
410     int status = 0;
411     int startTime = (int)time(NULL);
412     bool isSuccess = false;
413     DFXLOG_INFO("(%d) wait %s(%d) exit.", syscall(SYS_gettid), name, childPid);
414     do {
415         errno = 0;
416         ret = waitpid(childPid, &status, WNOHANG);
417         if (ret < 0) {
418             DFXLOG_ERROR("Failed to wait child process terminated, errno(%d)", errno);
419             return isSuccess;
420         }
421 
422         if (ret == childPid) {
423             isSuccess = true;
424             break;
425         }
426 
427         if ((int)time(NULL) - startTime > PROCESSDUMP_TIMEOUT) {
428             DFXLOG_INFO("(%d) wait for (%d) timeout", syscall(SYS_gettid), childPid);
429             isSuccess = false;
430             break;
431         }
432         usleep(SIGNALHANDLER_TIMEOUT); // sleep 10ms
433     } while (1);
434     DFXLOG_INFO("(%d) wait for (%d) return with ret(%d) status(%d)",
435         syscall(SYS_gettid), childPid, ret, status);
436     return isSuccess;
437 }
438 
ForkAndExecProcessDump(void)439 static int ForkAndExecProcessDump(void)
440 {
441     int childPid = -1;
442     SetSelfThreadParam("dump_tmp_thread", 0);
443 
444     // set privilege for dump ourself
445     int prevDumpableStatus = prctl(PR_GET_DUMPABLE);
446     bool isTracerStatusModified = SetDumpState();
447     if (!isTracerStatusModified) {
448         goto out;
449     }
450 
451     // fork a child process that could ptrace us
452     childPid = ForkBySyscall();
453     if (childPid == 0) {
454         DFXLOG_INFO("The exec processdump pid(%d).", syscall(SYS_getpid));
455         _exit(DFX_ExecDump());
456     } else if (childPid < 0) {
457         DFXLOG_ERROR("Failed to fork child process, errno(%d).", errno);
458         goto out;
459     }
460     WaitProcessExit(childPid, "processdump");
461 out:
462     RestoreDumpState(prevDumpableStatus, isTracerStatusModified);
463     pthread_mutex_unlock(&g_signalHandlerMutex);
464     return 0;
465 }
466 
CloneAndDoProcessDump(void * arg)467 static int CloneAndDoProcessDump(void* arg)
468 {
469     (void)arg;
470     DFXLOG_INFO("The clone thread(%d).", syscall(SYS_gettid));
471     g_request.recycleTid = syscall(SYS_gettid);
472     return ForkAndExecProcessDump();
473 }
474 
ForkAndDoProcessDump(int sig)475 static void ForkAndDoProcessDump(int sig)
476 {
477     int prevDumpableStatus = prctl(PR_GET_DUMPABLE);
478     bool isTracerStatusModified = SetDumpState();
479     int childPid = ForkBySyscall();
480     if (childPid == 0) {
481         g_request.vmNsPid = syscall(SYS_getpid);
482         g_request.vmPid = GetRealPid();
483         DFXLOG_INFO("The vm pid(%d:%d).", g_request.vmPid, g_request.vmNsPid);
484         DFX_SetUpSigAlarmAction();
485         alarm(ALARM_TIME_S);
486         _exit(ForkAndExecProcessDump());
487     } else if (childPid < 0) {
488         DFXLOG_ERROR("Failed to fork child process, errno(%d).", errno);
489         RestoreDumpState(prevDumpableStatus, isTracerStatusModified);
490         ForkAndExecProcessDump();
491         return;
492     }
493 
494     DFXLOG_INFO("Start wait for VmProcess(%d) exit.", childPid);
495     errno = 0;
496     if (!WaitProcessExit(childPid, "VmProcess") && sig != SIGDUMP) {
497         DFXLOG_INFO("Wait VmProcess(%d) exit timeout in handling critical signal.", childPid);
498         _exit(0);
499     }
500     RestoreDumpState(prevDumpableStatus, isTracerStatusModified);
501     pthread_mutex_unlock(&g_signalHandlerMutex);
502 }
503 
DFX_SigchainHandler(int sig,siginfo_t * si,void * context)504 static bool DFX_SigchainHandler(int sig, siginfo_t *si, void *context)
505 {
506     int pid = syscall(SYS_getpid);
507     int tid = syscall(SYS_gettid);
508     DFXLOG_INFO("DFX_SigchainHandler :: sig(%d), pid(%d), tid(%d).", sig, pid, tid);
509     bool ret = false;
510     if (sig == SIGDUMP) {
511         if (si->si_code != DUMP_TYPE_NATIVE) {
512             return true;
513         }
514 
515         if ((si->si_value.sival_int == 0) && (pid != tid)) {
516             DFXLOG_INFO("DFX_SigchainHandler :: mismatch request(%d), pid(%d), tid(%d).",
517                 si->si_value.sival_int, pid, tid);
518             return true;
519         }
520     }
521 
522     // crash signal should never be skipped
523     pthread_mutex_lock(&g_signalHandlerMutex);
524     if (g_prevHandledSignal != SIGDUMP) {
525         pthread_mutex_unlock(&g_signalHandlerMutex);
526         ExitIfSandboxPid(sig);
527         return ret;
528     }
529     BlockMainThreadIfNeed(sig);
530     g_prevHandledSignal = sig;
531 
532     FillDumpRequest(sig, si, context);
533     DFXLOG_INFO("DFX_SigchainHandler :: sig(%d), pid(%d), processName(%s), threadName(%s).",
534         sig, g_request.pid, g_request.processName, g_request.threadName);
535 
536     // for protecting g_reservedChildStack
537     // g_signalHandlerMutex will be unlocked in ForkAndExecProcessDump function
538     if (sig != SIGDUMP) {
539         ForkAndDoProcessDump(sig);
540         ExitIfSandboxPid(sig);
541     } else {
542         ret = true;
543         int recycleTid = clone(CloneAndDoProcessDump, g_reservedChildStack,\
544             CLONE_THREAD | CLONE_SIGHAND | CLONE_VM, NULL);
545         if (recycleTid == -1) {
546             DFXLOG_ERROR("Failed to clone thread for recycle dump process, errno(%d)", errno);
547             pthread_mutex_unlock(&g_signalHandlerMutex);
548         }
549     }
550 
551     DFXLOG_INFO("Finish handle signal(%d) in %d:%d", sig, g_request.pid, g_request.tid);
552     return ret;
553 }
554 
DFX_SignalHandler(int sig,siginfo_t * si,void * context)555 static void DFX_SignalHandler(int sig, siginfo_t *si, void *context)
556 {
557     DFX_SigchainHandler(sig, si, context);
558     ResetAndRethrowSignalIfNeed(sig, si);
559 }
560 
DFX_InstallSignalHandler(void)561 void DFX_InstallSignalHandler(void)
562 {
563     if (g_hasInit) {
564         return;
565     }
566 
567     // reserve stack for fork
568     g_reservedChildStack = mmap(NULL, RESERVED_CHILD_STACK_SIZE, \
569         PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, 1, 0);
570     if (g_reservedChildStack == NULL) {
571         DFXLOG_ERROR("Failed to alloc memory for child stack.");
572         return;
573     }
574     g_reservedChildStack = (void *)(((uint8_t *)g_reservedChildStack) + RESERVED_CHILD_STACK_SIZE - 1);
575 
576     struct signal_chain_action sigchain = {
577         .sca_sigaction = DFX_SigchainHandler,
578         .sca_mask = {},
579         .sca_flags = 0,
580     };
581     sigfillset(&sigchain.sca_mask);
582     for (size_t i = 0; i < sizeof(SIGCHAIN_SIGNAL_LIST) / sizeof(SIGCHAIN_SIGNAL_LIST[0]); i++) {
583         int32_t sig = SIGCHAIN_SIGNAL_LIST[i];
584         add_special_handler_at_last(sig, &sigchain);
585     }
586 
587     struct sigaction action;
588     memset(&action, 0, sizeof(action));
589     memset(&g_oldSigactionList, 0, sizeof(g_oldSigactionList));
590     sigfillset(&action.sa_mask);
591     action.sa_sigaction = DFX_SignalHandler;
592     action.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
593     for (size_t i = 0; i < sizeof(SIGACTION_SIGNAL_LIST) / sizeof(SIGACTION_SIGNAL_LIST[0]); i++) {
594         int32_t sig = SIGACTION_SIGNAL_LIST[i];
595         if (sigaction(sig, &action, &(g_oldSigactionList[sig])) != 0) {
596             DFXLOG_ERROR("Failed to register signal(%d)", sig);
597         }
598     }
599 
600     g_hasInit = TRUE;
601 }
602