Skip to content

https://xtuly.cn/article/android-crash-clear-context 一段关于信号异常的示例

cpp

//
// Created by Ylarod on 2022/11/30.
//

#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>

#ifndef NELEM
#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
#endif

const int signal_array[] = {SIGILL, SIGABRT, SIGBUS, SIGFPE, SIGSEGV, SIGSTKFLT, SIGSYS};
struct sigaction old_signal_handlers[NELEM(signal_array)];

void signal_handler(int signal, siginfo_t *info, void *context){
    const int code = info->si_code;
    printf("signal %d, code: %d, pid: %d, uid: %d, tid: %d\n",
           signal,
           code,
           info->si_pid,
           info->si_uid,
           info->si_tid
    );

    // 清理context,直接memset也不是不行
    auto* ucontext = (ucontext_t*)context;
    ucontext->uc_mcontext.sp = 0;
    ucontext->uc_mcontext.pc = 0;
    ucontext->uc_mcontext.pstate = 0;
    ucontext->uc_stack.ss_sp = nullptr;
    ucontext->uc_stack.ss_size = 0;
    for (unsigned long long& reg : ucontext->uc_mcontext.regs) {
        reg = 0;
    }

    int index = -1;
    for (int i = 0; i < NELEM(signal_array); ++i) {
        if (signal_array[i] == signal) {
            index = i;
            break;
        }
    }
    if (index == -1) {
        exit(code);
    }
    // 调用之前的异常处理函数,如果不调用不会出现 tombstone
    struct sigaction old = old_signal_handlers[index];
    old.sa_sigaction(signal, info, context);
}

void make_crash(int type){
    kill(getpid(), signal_array[type - 1]);
}

void init(){
    struct sigaction handler = {
            .sa_flags = SA_SIGINFO,
            .sa_sigaction = signal_handler,
    };
    for (int i = 0; i < NELEM(signal_array); ++i) {
        sigaction(signal_array[i], &handler, &old_signal_handlers[i]);
    }
}

int main(int argc, char** argv){
    init();
    if (argc == 2){
        int type = atoi(argv[1]);
        make_crash(type);
    }
}