mar@hpclmar.HP.COM (Michelle Ruscetta) (09/25/87)
Question about signal(): Should the return from a signal handling routine specified by a call to signal() go to the instruction which caused the signal, or to the instruction immediately following that which caused the signal? For example: void (*p_my_handler)(); main() { extern void my_handler(); int y = 0; int x = 3; p_my_handler = my_handler: signal(SIGFPE, p_my_handler); x = x/y; /* should my_handler return to here? */ printf("return from signal\n"); /* or should my_handler return to here? */ } void my_handler() { signal(SIGFPE, SIG_IGN); /* do something useful */ signal(SIGFPE, p_my_handler); } --------------------------- I have run this example on two different machines, with different results; (both were running implementations of System V) one returned to the statement following that which cause the signal (the printf), and the other returned to the instruction which caused the signal -- hence throwing the program into an infinite loop continuously executing x/y and catching the floating point exception. I know it is not very good practice to return from signal-handlers but this question came up in a discussion and I would be interested to hear opinions as to which is the 'correct' way for signal to handle this.
gwyn@brl-smoke.UUCP (09/28/87)
In article <720001@hpclmar.HP.COM> mar@hpclmar.HP.COM (Michelle Ruscetta) writes: > Should the return from a signal handling routine specified by a call > to signal() go to the instruction which caused the signal, or to the > instruction immediately following that which caused the signal? If it's an asynchronous trap, it should complete the interrupted instruction sequence. If it's a synchronous trap (e.g. SIGFPE), there is no "right" answer. Presumably the synchronous exception occurred because some machine operation had invalid operands; unless you can be sure that the signal handler has fixed the operands (which is almost never the case, due to code optimization etc.), retrying the faulting instruction would just cause another trap. Portable, robust programs should not just return from a SIGFPE handler.
matt@oddjob.UUCP (10/01/87)
Michelle Ruscetta writes:
)
) Question about signal():
)
) Should the return from a signal handling routine specified by a call
) to signal() go to the instruction which caused the signal, or to the
) instruction immediately following that which caused the signal?
)
) For example: ...
)
) I have run this example on two different machines, with different results;
) [one resumed at the instruction after the FPE], and the other returned
) to the instruction which caused the signal
Was the second machine a VAX-11/750? If I remember rightly, 750's
have a microcode bug in the treatment of floating point exceptions
which causes exactly the behavior you say.
________________________________________________________
Matt University matt@oddjob.uchicago.edu
Crawford of Chicago {astrovax,ihnp4}!oddjob!matt
rneitzel@udenva.UUCP (RICHARD NEITZEL ) (10/01/87)
In article <720001@hpclmar.HP.COM> mar@hpclmar.HP.COM (Michelle Ruscetta) writes: > > Question about signal(): > > Should the return from a signal handling routine specified by a call > to signal() go to the instruction which caused the signal, or to the > instruction immediately following that which caused the signal? > > For example: > > void (*p_my_handler)(); > > main() > { > extern void my_handler(); > int y = 0; > int x = 3; > p_my_handler = my_handler: > signal(SIGFPE, p_my_handler); > x = x/y; /* should my_handler return to here? */ > printf("return from signal\n"); /* or should my_handler return to here? */ > } In my opinion this depends partially on the way in which you look at the problem. Returning to the line that caused the signal might well trigger the signal again, putting the program into an infinite loop. After all, the chances of your signal handling routine knowing EXACTLY what to do are slim. There is however the problem that a C line does not map to a single machine instruction. For example, suppose that the line above where changed to: x = x/y + (x - y); Now, do you want the entire line to complete, even if the division triggers a signal? More then likely, yes you do. The answer probably is that there need to be two classes of signals (whether in fact or in conception), synchronous and asynchronous. The first should be used for events that are of a fixed nature, such as floating point exceptions. The latter are for events that are unpredictable. Further, synchronous signals should be limited to events from which you do not normally exspect to return, while the other case is for events that do not require that the normal program flow be terminated. It is my opinion that the best solution would be to have these two types of signals, but barring that I would prefer that all signals behave in an asynchronous nature, leaving it to the user to use those signals that are inappropriate in a strictly synchronous manner. 'I'd gladly pay you Tuesday for a hamburger today' Richard Neitzel
mar@hpclmar.UUCP (10/02/87)
/ hpclmar:comp.unix.questions / matt@oddjob.UChicago.EDU (I am not a Grook) / 3:43 pm Sep 30, 1987 / > Was the second machine a VAX-11/750? If I remember rightly, 750's > have a microcode bug in the treatment of floating point exceptions > which causes exactly the behavior you say. > ________________________________________________________ > Matt University matt@oddjob.uchicago.edu > Crawford of Chicago {astrovax,ihnp4}!oddjob!matt No, one machine was a 68020-based architecture (the hp9000s320) and the other was the HPPA (risc) architecture (hp9000s840). The s320 began execution after the line which caused the floating-point trap. The s840 begins execution at the instruction which caused the floating-point trap (causing the given program goes into an infinite loop).
john@frog.UUCP (John Woods, Software) (10/06/87)
In article <4248@udenva.UUCP>, rneitzel@udenva.UUCP (RICHARD NEITZEL ) writes: > In article <720001@hpclmar.HP.COM> mar@hpclmar.HP.COM (Michelle Ruscetta) writes: > > Question about signal(): > > Should the return from a signal handling routine specified by a call > > to signal() go to the instruction which caused the signal, or to the > > instruction immediately following that which caused the signal? > > void (*p_my_handler)(); > > main() > > { > > extern void my_handler(); > > int y = 0; > > int x = 3; > > p_my_handler = my_handler: > > signal(SIGFPE, p_my_handler); > > x = x/y; /* should my_handler return to here? */ > > printf("return from signal\n"); /* or to here? */ > > } > I would argue that the signal should return to the instruction causing the problem, if it returns at all. Presumably, your handler will either fix up the problem to allow the instruction to complete correctly (e.g., it would determine that one of the arguments is 0.0, print a message, stuff a 1.0 into the register or temporary, and return), it would bypass the effects of the instruction and advance the program counter that will be returned to (e.g., it prints a message, stores an IEEE infinity into the result of the instruction (register, memory location, whatever), bumps the PC, and returns), or it prints out an error message, maybe a stack backtrace, and craps out again with a core dump. Note that two of these aren't portable things. Furthermore, they may become impossible in processors with separate, asynchronous, floating point units (e.g. the venerable PDP-11), or with lots of internal pipelining: how does one "properly" re-do divf fr0,fr1 inc r0 addf fr1,fr2 if the divf gets an exception AFTER the 'inc r0' has executed? In short, it is probably easiest to offer to repair damage from an exception if the exception handler is told which instruction faulted and is allowed to return to it, but in the *general* case the only useful thing a signal handler can do in this case is: my_FPE_handler() { fprintf(stderr,"Ah, geez, a floating point exception happened!\n"); abort(); } -- John Woods, Charles River Data Systems, Framingham MA, (617) 626-1101 ...!decvax!frog!john, ...!mit-eddie!jfw, jfw@eddie.mit.edu "Cutting the space budget really restores my faith in humanity. It eliminates dreams, goals, and ideals and lets us get straight to the business of hate, debauchery, and self-annihilation." -- Johnny Hart
gwyn@brl-smoke.ARPA (Doug Gwyn ) (10/08/87)
In article <1659@frog.UUCP> john@frog.UUCP (John Woods, Software) writes:
-... Presumably, your handler will either fix
-up the problem to allow the instruction to complete correctly (e.g., it
-would determine that one of the arguments is 0.0, print a message, stuff a
-1.0 into the register or temporary, and return)...
It is not in general possible to "fix up the problem" with portable C code.
You shouldn't print messages from signal handlers; the associated library
routines are in general non-reentrant due to possibly incomplete manipulation
of internal data structures when interrupted.
-... but in the *general* case the only useful thing a signal
-handler can do in this case is:
-my_FPE_handler() {
- fprintf(stderr,"Ah, geez, a floating point exception happened!\n");
- abort();
-}
No, it is often the case that an error flag can be set and a longjmp()
performed to reenter the application's main control loop.