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