在 Android 中,仿生加载器为 statrtup 上的每个进程设置默认信号处理程序:
void debugger_init()
{
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_sigaction = debugger_signal_handler;
act.sa_flags = SA_RESTART | SA_SIGINFO;
sigemptyset(&act.sa_mask);
sigaction(SIGILL, &act, NULL);
sigaction(SIGABRT, &act, NULL);
sigaction(SIGBUS, &act, NULL);
sigaction(SIGFPE, &act, NULL);
sigaction(SIGSEGV, &act, NULL);
sigaction(SIGSTKFLT, &act, NULL);
sigaction(SIGPIPE, &act, NULL);
}
我想将其设置回默认值,这意味着我想忽略这些信号并且将发生默认处理程序(核心转储)
如何恢复已执行的操作?我想忽略所有这些,就好像上面的函数从未被调用过
阅读 signal(7)、sigaction(2),也许还有 signal(2)。
你可以打电话
signal(SIGILL, SIG_DFL);
signal(SIGABRT, SIG_DFL);
等早期的
main
(动态加载后进入)
您还可以使用
sigaction
,并将 sa_handler
设置为 SIG_DFL
当然,如果您想在
main
之前默认处理这些信号,事情会更加棘手,例如在一些静态构造函数中!
我发现当混合使用 sigaction 和 signal 来设置一个进程时,可能会导致意外的行为。
来自上面发布的信号(2)(如果 8 年前没有这个警告,我不会感到惊讶):
警告:signal() 的行为因 UNIX 版本而异, 并且在不同版本的历史上也有所不同 Linux。 避免使用它:使用 sigaction(2) 代替。
查看https://docs.oracle.com/cd/E19455-01/806-5257/tlib-49639/index.html
int pthread_sigmask(int how, const sigset_t *new, sigset_t *old);
当new的值为NULL时,how的值不重要,线程的信号掩码不变。因此,要查询当前被阻止的信号,请为 new 参数分配 NULL 值。
所以我想你可以用它来获取当前的 sigmask 并擦除每个
sigset_t tempSet;
pthread_sigmask(SIG_SETMASK, NULL, &tempSet);
sigdelset(&tempSet, /*Signal you don't want to handle*/);
sigdelset(&tempSet, /*repeat for each signal*/);
pthread_sigmask(SIG_SETMASK, &tempSet, NULL);
与 sigact 几乎相同,用于查询信号的当前操作,来自 sigaction(2)
sigaction() 可以使用 NULL 第二个参数来调用来查询 当前的信号处理程序。
我不清楚,就我而言,在第一次调用 sigaction 时使用 SIGKILL 会产生什么后果
struct sigaction sigAct;
sigaction(SIGKILL, NULL, &sigAct);
sigAct.sa_handler = SIG_DFL; // Ensure default handling of Kill signal
sigaction(/*Signal you don't want to handle*/, &sigAct, NULL);
sigaction(/*repeat for each signal*/, &sigAct, NULL);
使用 siggetmask 已被 sigprocmask 废弃,并且 sigprocmask 仅适用于单线程环境。
void debugger_signal_handler(int)
{
//code......
struct sigaction sa;
sa.sa_handler = SIG_DFL;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(sig, &sa, NULL);
}
您可以使用 SIG_DFL(流的默认值)重置信号处理程序的行为。