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() 呼び出しを使用しました。これら 2 つのケースでは動作が異なります (コア ダンプは、デフォルト ハンドラーが呼び出されたと想定しています) が、どちらもシグナル ハンドラーを 2 回以上呼び出しませんか? 理由はありますか?

4

0 に答える 0