1
#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;
}

This code produce the following output:

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
.
.
.

Why is the signal handler only called once? I used the raise() call to avoid the core dump I got when division by zero occurred. The behaviour is different in these two cases (core dump assumes default handler was called), but none of them calls the signal handler more than once? Any ideas why?

Bugsy
  • 103
  • 7
  • 2
    You're supposed to use `sigsetjmp`, `siglongjmp` instead of manually resetting the signal mask. However, I'm not sure if this is relevant to your problem. – Nate Eldredge Oct 07 '21 at 17:31
  • It seems to work when I switched to sigsetjmp/siglongjmp. That's great! Such a fast response. Thanks! I will have to study the details about these calls, but it sure changed the behaviour. – Bugsy Oct 07 '21 at 17:47

0 Answers0