Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I ignore a SIGFPE resulting from division by zero?

I have a program which deliberately performs a divide by zero (and stores the result in a volatile variable) in order to halt in certain circumstances. However, I'd like to be able to disable this halting, without changing the macro that performs the division by zero.

Is there any way to ignore it?

I've tried using

#include <signal.h>
...
int main(void) {
  signal(SIGFPE, SIG_IGN);
  ...
}

but it still dies with the message "Floating point exception (core dumped)".

I don't actually use the value, so I don't really care what's assigned to the variable; 0, random, undefined...

EDIT: I know this is not the most portable, but it's intended for an embedded device which runs on many different OSes. The default halt action is to divide by zero; other platforms require different tricks to force a watchdog induced reboot (such as an infinite loop with interrupts disabled). For a PC (linux) test environment, I wanted to disable the halt on division by zero without relying on things like assert.

like image 774
Mikeage Avatar asked Dec 09 '22 22:12

Mikeage


1 Answers

Okay, first off, you ought to be using sigaction(2) instead of the deprecated signal().

Secondly, using SIGFPE for the purposes of terminating the program is patently absurd, as you should be raising a signal like SIGTERM or SIGUSR1 instead of jury-rigging some other signal for its side-effect and disregarding its semantic value. And more specifically, the man page for sigaction(2) has a NOTES section with a blurb about SIGFPE that indicates one or two ways your intended use of it is broken.

What you should do is raise(3) a signal when you want to terminate. Then, use the sa_handler field in the sigaction structure to change whether to ignore (SIG_IGN) or terminate (SIG_DFL) on that signal.

int main(void) {
  struct sigaction my_action;

  my_action.sa_handler = SIG_IGN;
  my_action.sa_flags = SA_RESTART;
  sigaction(SIGUSR1, &my_action, NULL);

  raise(SIGUSR1);  /* Ignored */

  my_action.sa_handler = SIG_DFL;
  sigaction(SIGUSR1, &my_action, NULL);

  raise(SIGUSR1); /* Terminates */

  return 0;
}

That said, I can't see why you'd use signals instead of a simple exit().

like image 137
Nietzche-jou Avatar answered Jan 08 '23 11:01

Nietzche-jou