Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!usc!samsung!noose.ecn.purdue.edu!mentor.cc.purdue.edu!purdue!haven!adm!smoke!gwyn From: gwyn@smoke.brl.mil (Doug Gwyn) Newsgroups: comp.std.c Subject: Re: Question: signal and program termination Keywords: signal, exit, termination Message-ID: <15019@smoke.brl.mil> Date: 30 Jan 91 20:14:32 GMT References: <87792@tut.cis.ohio-state.edu> Organization: U.S. Army Ballistic Research Laboratory, APG, MD. Lines: 63 In article <87792@tut.cis.ohio-state.edu> writes: > occur by calling exit() within a handler? Clearly, any cleanup > functions set up by atexit() would have to be called. However, if > some data was left in an undefined state because of the signal, > then couldn't these exit functions completely fail? Sure; your code could easily have a bug like that. Note that it is quite difficult to write RELIABLE programs that consist of "concurrent" (or at least, asynchronous) communicating processes. This reliability issue is why I invariably recommend that the ONLY thing you do in a signal handler be to set a flag (of type sig_atomic_t), possibly alter the signal state via a call to signal(), and then resume execution, with the actual exception handling logic performed at one or more appropriate points within your main application code (where you know that the data structures are consistent). Otherwise, you have to lock out signals during "critical regions" etc. throughout the application, which is tedious and error-prone. > What happens if the handler > for SIGABRT is set to SIG_IGN and later abort() is called? The abort() implementation must in effect reset the state to SIG_DFL unless there is a signal handler function established already, before performing the raise(SIGABRT). SIG_IGN is not honored by abort(). > what happens if a user supplied handler is installed for SIGABRT... > Since abort() is not permitted to return, what would happen if > the handler decided to call exit(), longjmp(), or even worse > abort() again, rather than strictly returning? abort() never returns to the point at which it was invoked (I would say "never returns a value", except as a void function it doesn't have a value to return anyway). If the signal handler returns, abort() then terminates the process. Otherwise, it is possible for the program to continue by e.g. a longjmp() from the signal handler. If the signal handler invokes exit(), the normal semantics for exit() apply. If the signal handler invokes abort(), then the semantics for abort() are recursively invoked. Indeed, it is possible to produce a loop this way (presumably a stack overflow would eventually occur). >3) I would assume that signal handlers are permitted to raise other > signals. Say, if the default action for SIGINT's handler was to > terminate the program, would it be more appropriate to raise > SIGABRT or SIGTERM -- or should it just call exit() and suffer the > same problems mentioned in question 1? In the usual case that a SIGINT would be externally (asynchronously) generated, the standard says that the only standard function you may call in a strictly conforming signal handler would be signal(SIGINT,). In the case of a synchronous signal generated by raise() or abort(), you may safely use all the standard library functions, including raise(). As I mentioned previously, I don't recommend that an asynchronously invoked signal handler attempt to do much more than set a flag. > computational exception. Among the ANSI defined signals, which > ones do indicate a computational exception? SIGFPE. I would also expect that many implementations will choose to define the "computational exceptions" to include SIGILL and SIGSEGV, in order to be allowed to have undefined behavior if the signal handler attempts to return in those cases.