Unix Programming - Signal Call

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > October 2004 > Signal Call





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author Signal Call
Amit Sharma

2004-10-02, 9:13 pm

Hi,
I want to write a program, where until we give the value of j as
non zero, it should go on asking us values of i and j, displaying the
message "Division by zero: Floating point exception" for every input
of j as zero. Once we give the value of both i and j as non-zero, it
displays i/j and terminates.

This is the sample code i tried:
#include <signal.h>
#include <stdio.h>
#inclue <stdlib.h>

void sig_s(int signo);
void Divide();

void main( )
{
signal(SIGFPE,sig_s);
Divide();

}
void Divide()
{
int i,j,k;
printf("Enter a number\n");
scanf("%d",&i);
printf("another number\n");
scanf("%d",&j);
if( (i==0) && (j==0))
{
printf("Total is %d\n",0);
exit(0);
}
else
{
printf("Total is %d\n",i/j);
}
}

void sig_s(int signo)
{
signal(SIGFPE,sig_s);
printf("Division by zero:Floating point exception\n");
Divide();
}

It works fine as you give the denominator as zero and ask for the new
number but if you give the valid values also (e.g. i=10, j=5) Then
also it went into the Signal handler function and call the signal
handler recursively.
Could you please suggest me how i can acheive this ??

Thanks,
Amit
Pascal Bourguignon

2004-10-02, 9:13 pm

sharma.am@gmail.com (Amit Sharma) writes:

> Hi,
> I want to write a program, where until we give the value of j as
> non zero, it should go on asking us values of i and j, displaying the
> message "Division by zero: Floating point exception" for every input
> of j as zero. Once we give the value of both i and j as non-zero, it
> displays i/j and terminates.
>
> This is the sample code i tried:
> #include <signal.h>
> #include <stdio.h>
> #inclue <stdlib.h>
>
> void sig_s(int signo);
> void Divide();
>
> void main( )
> {
> signal(SIGFPE,sig_s);
> Divide();
>
> }
> void Divide()
> {
> int i,j,k;
> printf("Enter a number\n");
> scanf("%d",&i);
> printf("another number\n");
> scanf("%d",&j);
> if( (i==0) && (j==0))
> {
> printf("Total is %d\n",0);


Big bug here! 0/0 is undefined.

sin x
For example, lim ------- = 1, not 0.
x->0 x


> exit(0);
> }
> else
> {
> printf("Total is %d\n",i/j);
> }
> }
>
> void sig_s(int signo)
> {
> signal(SIGFPE,sig_s);
> printf("Division by zero:Floating point exception\n");
> Divide();
> }
>
> It works fine as you give the denominator as zero and ask for the new
> number but if you give the valid values also (e.g. i=10, j=5) Then
> also it went into the Signal handler function and call the signal
> handler recursively.
> Could you please suggest me how i can acheive this ??


By not calling Divide recursively in the signal handler!



Very little can and should be done in a signal handler.
For example, a printf is out of question here.

The best way, is to always test for a null denominator before every
division (or prove your pre-conditions!).

For example, instead of writting:

printf("another number\n");
scanf("%d",&j);

you should write:

do{
printf("please enter a denominator (non-null integer):\n");
scanf("%d",&j);
if(j==0){
printf("Invalid denominator. Try again.\n");
}
}while(j==0);


Now, if you really want to trap SIGFPE, you should read this:

According to POSIX, the behaviour of a process is undefined after
it ignores a SIGFPE, SIGILL, or SIGSEGV signal that was not gen_
erated by the kill(2) or the raise(3) functions. Integer divi_
sion by zero has undefined result. On some architectures it will
generate a SIGFPE signal. (Also dividing the most negative inte_
ger by -1 may generate SIGFPE.) Ignoring this signal might lead
to an endless loop.

That means that one cannot return from a SIG_FPE signal handler with
the hope of returning to the instructions after the divide. Indeed,
on Linux 2.4, even when signal(SIGFPE,SIG_IGN); in the handler,
returning the handler will retry the division. On some system, you
could hack the trap, see for example:

http://publib16.boulder.ibm.com/pse...oint_except.htm

but this is not portable. The best bet to handle SIG_FPE is to use
longjmp. But remember that on some systems, 1/0 may return MAX_INT
without exception.



#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>

static jmp_buf divide_by_zero_jmp;

static void sig_s(int signo){
signal(SIGFPE,sig_s);
longjmp(divide_by_zero_jmp,1);
}

static void divide(void){
int i,j,k;
if(setjmp(divide_by_zero_jmp)){
printf("Division by zero: Floating point exception.\n");
}
for(;;){
printf("Enter a numerator: ");
fflush(stdout);
scanf("%d",&i);
printf("Enter a denominator (non null): ");
fflush(stdout);
scanf("%d",&j);
if((i==0)&&(j==0)){
printf("Quotient undefined.\n");
fflush(stdout);
}else{
k=i/j;
printf("Quotient is %d\n",k);
fflush(stdout);
break;
}}}


int main(void){
signal(SIGFPE,sig_s);
divide();
return(0);
}


$ ./a
Enter a numerator: -2147483648 ||
Enter a denominator (non null): -1 || !!!
Division by zero: Floating point exception. ||
Enter a numerator: -1
Enter a denominator (non null): 0
Division by zero: Floating point exception.
Enter a numerator: 1
Enter a denominator (non null): -1
Quotient is -1

--
__Pascal Bourguignon__ http://www.informatimago.com/

Our enemies are innovative and resourceful, and so are we. They never
stop thinking about new ways to harm our country and our people, and
neither do we.
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com