0
#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() 调用来避免发生被零除时得到的核心转储。这两种情况下的行为是不同的(核心转储假定调用了默认处理程序),但它们都没有多次调用信号处理程序?任何想法为什么?

4

0 回答 0