#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <signal.h>
#include <setjmp.h>
#include <fenv.h>
static jmp_buf begin;
void sigAction(int signum, siginfo_t* siginfo, void* context)
{
sigset_t oset;
sigemptyset(&oset);
sigprocmask(SIG_BLOCK, NULL, &oset);
printf("sigAction: Signal %d received (%d, %d, 0x%x).\n",
signum, siginfo->si_signo, siginfo->si_code, siginfo->si_value);
printf("sigAction: Current sig mask 0x%x\n", oset);
longjmp(begin, 1);
}
void calc(float *val, float *s, float *u)
{
int jmpstat;
int save_exc;
sigset_t oset;
sigemptyset(&oset);
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
act.sa_sigaction = sigAction;
act.sa_flags |= SA_SIGINFO;
save_exc = fegetexcept();
printf("Current exceptions mask saved: 0x%x\n", save_exc);
(void)feenableexcept(FE_DIVBYZERO|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
printf("Exceptions are now enabled\n");
if( (jmpstat = setjmp(begin)) != 0 )
{
(void)fedisableexcept(FE_ALL_EXCEPT);
(void)feenableexcept(save_exc);
sigprocmask(SIG_BLOCK, NULL, &oset);
printf("Current sig mask after longjmp(): 0x%x\n", oset);
*val = 0;
return;
}
printf("Set signal handler 0x%x\n", act.sa_sigaction);
if (sigaction(SIGFPE, &act, NULL))
{
printf("Failed to set signal handler\n");
}
sigprocmask(SIG_BLOCK, NULL, &oset);
printf("Current sig mask: 0x%x\n", oset);
printf("Generate SIGFPE\n");
#if 0
*val = *s / *u;
#else
raise(SIGFPE);
#endif
printf("Back after signal handling\n");
(void)fedisableexcept(FE_ALL_EXCEPT);
(void)feenableexcept(save_exc);
}
int main(int argc, char *argv[])
{
int i = 0;
float val;
float s = 1;
float u = 0;
while(1)
{
printf("%d. In loop.\n", i++);
calc(&val, &s, &u);
sleep(1);
}
return 0;
}
此代码产生以下输出:
0. In loop.
Current exceptions mask saved: 0x0
Exceptions are now enabled
Set signal handler 0x400864
Current sig mask: 0x0
Generate SIGFPE
sigAction: Signal 8 received (8, -6, 0x0).
sigAction: Current sig mask 0xb1c4b000
Current sig mask after longjmp(): 0x0
1. In loop.
Current exceptions mask saved: 0x0
Exceptions are now enabled
Set signal handler 0x400864
Current sig mask: 0x0
Generate SIGFPE
Back after signal handling
2. In loop.
Current exceptions mask saved: 0x0
Exceptions are now enabled
Set signal handler 0x400864
Current sig mask: 0x0
Generate SIGFPE
Back after signal handling
.
.
.
为什么信号处理程序只调用一次?我使用 raise() 调用来避免发生被零除时得到的核心转储。这两种情况下的行为是不同的(核心转储假定调用了默认处理程序),但它们都没有多次调用信号处理程序?任何想法为什么?