Thread: POSIX Signal Handling

  1. #1
    Registered User
    Join Date
    Jan 2007
    Posts
    18

    Question POSIX Signal Handling

    I'm trying to catch a floating point zero divide exception, but it doesn't seem to be working out and I can't figure out why the (minimal) code I have right now is:
    Code:
    #include <stdio.h>
    #include <signal.h>
    #include <unistd.h>
    
    void handle_zero(int sig_num){
      printf("caught zero divide");
    }
    
    int main(){
      float num1,num2;
    
      signal(SIGFPE,handle_zero);
    
      while (42){
      printf("divide: ");
    
      scanf("&#37;f %f", &num1, &num2);
      
      printf("result: %f\n",num1/num2);
    
      }
    
      return 0;
    }
    So that when I enter something like: 12.2 0.0 or 0 0 the signal isn't caught/triggered, however, when I changed it to read in two integers and divide them, it was caught.

    So what's the proper signal for floating point, or what am I doing wrong?

    Thanks.
    Last edited by nine-hundred; 04-12-2007 at 09:47 PM. Reason: added libraries

  2. #2
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    There are two issues here that I am aware of. One is that you shouldn't call any standard library functions in a signal handler (such as printf); the other being that the code presented may not recognize the fact that linking to the floating point library is required.

    [edit=1]http://cboard.cprogramming.com/showp...71&postcount=4
    [edit=2]https://cboard.cprogramming.com/showthread.php?p=347013
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  3. #3
    Registered User
    Join Date
    Jan 2007
    Posts
    18
    Hmm..alright, I'm new to this whole signal thing (as you can probably tell). Why is it bad to call library functions in handlers? The call to printf was just for debugging, to show that it was actually called, is there another simple way that I can tell it was called without resorting to printf? How do I force linkage to the floating point library?

    Thanks for the quick reply m8

    edit: sorry didn't see the links there, reading now, thanks

  4. #4
    Registered User
    Join Date
    Jan 2007
    Posts
    18
    Alright, after reading that I changed the code to make it more compliant (if I understood it properly):
    Code:
    #include <stdio.h>
    #include <signal.h>
    #include <unistd.h>
    
    int counter = 0;
    
    void handle_zero(int sig_num){
      counter++;
    }
    
    int main(){
      float num1,num2, num3;
    
      num3 = 1.0/1.0;
    
      signal(SIGFPE,handle_zero);
    
      while (42){
      printf("divide: ");
    
      scanf("%f %f",  &num1,  &num2);
    
      num3 = num1/num2;
    
      printf("result: %f\ncount: %d\n",num3,counter);
    
      }
    
      return 0;
    }
    But no matter how I enter in the zeros (0.0, 0, 0.00, etc) The counter still outputs 0, when I changed the code to work with integers I think it got caught in an infinite loop (other than the purposeful one) though...if that changes anything :-/

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    I think that you might have to rummage through some of the floating point library code to actually enable FP exceptions.

    Also, use
    volatile int counter = 0;
    Just in case the compiler decided that there was no way for counter to change from looking at your code.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Jan 2007
    Posts
    18
    Hmm...I've looked around in quite a few places and I think I'm stuck.. Does any one know if there is is an option that I need to do to enable it at compilation? I'm using gcc...

    I will change that to volatile though, thanks m8

  7. #7
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by nine-hundred View Post
    I
    So that when I enter something like: 12.2 0.0 or 0 0 the signal isn't caught/triggered, however, when I changed it to read in two integers and divide them, it was caught.
    I assume you are on an x86 system, Linux possibly? By default, the FPU is configured to produce the value "infinity" when you divide by zero (or "not a number" if you divide zero by zero). It does NOT trigger an exception, you do NOT get a signal.

    You must reprogram the FPU to generate an exception for divide-by-zero. The way you do this is platform-dependent.

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by nine-hundred View Post
    Hmm..alright, I'm new to this whole signal thing (as you can probably tell). Why is it bad to call library functions in handlers?
    The problem is, what happens when you receive a signal while some standard library function is in the middle of executing? More specifically, what happens if you get a signal while in the middle of printf()? The C library may or may not be reentrant. It is certainly not guaranteed to be. So the effects of calling a library function from a signal handler are undefined, except for a certain class of functions which are known to be reentrant.

    You get away with it in this case because the particular signal you are trapping is (usually) only produced during a floating point exception. So the chances that you are inside a library function when the signal is delivered are exceedingly small -- pretty much the only way it could happen is if somebody sent you the signal deliberately with kill().

    The call to printf was just for debugging, to show that it was actually called, is there another simple way that I can tell it was called without resorting to printf?
    Set a flag in the signal handler. After the line of code which does the division, check if this flag is set -- if it is, a divide by zero occurred. But this is silly -- it's far easier, and more efficient, to simply check the denominator before doing the division in the first place.

    How do I force linkage to the floating point library?
    Add "-lm" to the link line.

  9. #9
    Registered User
    Join Date
    Jan 2007
    Posts
    18
    oh ok, thanks for the info...this is getting a bit complicated, I think I will have to research it some more before I can do what I want with it. Thanks again, very thorough

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. signal handling and exception handling
    By lehe in forum C++ Programming
    Replies: 2
    Last Post: 06-15-2009, 10:01 PM
  2. Signal and exception handling
    By nts in forum C++ Programming
    Replies: 23
    Last Post: 11-15-2007, 02:36 PM
  3. Signal Handling
    By DarrenY in forum C Programming
    Replies: 4
    Last Post: 06-04-2006, 11:30 AM
  4. Signal Handling - Are they part of ANSI C?
    By Stanley S in forum C Programming
    Replies: 3
    Last Post: 12-21-2005, 07:49 AM
  5. signal handling
    By trekker in forum C Programming
    Replies: 2
    Last Post: 07-05-2002, 02:52 AM