JTC1/SC22/WG14
N789
SC22/WG14 N789
Changes to signal handling
Clive D.W. Feather
clive@demon.net
1997-10-22
Abstract
========
The section of the Standard on signals greatly restricts the actions that
a signal handler can take. In particular, there are places where the
Standard appears to require the program to enter an infinite loop. N773
item 13 attempted to clean up this situation; after discussion at Menlo
Park, this paper is a further pass on this matter.
Discussion
==========
There are effectively three ways that a signal handler can be invoked:
(1) through raise ();
(2) from some internal asynchronous event, such as a floating-point error;
(3) from some external asynchronous event, such as a termination request.
For the purposes of this paper, it is assumed that the second and third
cases are distinguished by signal number, with SIGFPE, SIGILL, and SIGSEGV
falling into (2) and all others into (3).
There are four ways a signal handler can complete:
(1) returning
(2) calling exit()
(3) calling abort()
(4) calling longjmp()
All of these have potential problems; for example, an asynchrous signal
might interrupt a call to malloc(), and that might prevent the proper
closing of files as part of exit(). The consensus view was that:
* signals invoked through raise() should be allowed to do any of these;
* external asynchronous signal handlers should be allowed to return.
* all asynchronous signal handlers should be allowed to terminate the
program, but should not cause the malloc() problems. The best way to do
this is to introduce a new _exit() function that *only* terminates the
program.
In addition, the proposal cleans up some wording issues.
Proposal
========
[References are to draft 11 pre 3.]
In subclause 7.10.2.1 (The longjmp function), delete paragraph 4.
As it bypasses ... undefined.
Change the last sentence of subclause 7.11.1.1 (The signal function)
paragraph 2 from:
Such a function is called a signal handler.
to:
An invocation of such a function because of a signal, or (recursively)
of any further functions called by that invocation (other than functions
in the standard library), is called a /signal handler/.
Change subclause 7.11.1.1 paragraphs 3 and 4 from:
When a signal occurs,
...
the value of errno is indeterminate.[189]
to:
When a signal occurs and /func/ points to a function, it is
implementation-defined whether the equivalent of
/signal (sig, SIG_DFL)/ is executed or the implementation prevents
some implementation-defined set of signals (at least including /sig/)
from occuring until the current signal handling has completed; in
the case of SIGILL, the implementation may alternatively define that
no action is taken. Then the equivalent of /(*func)(sig);/ is
executed. If and when the function returns, if the value of /sig/ is
/SIGFPE/, /SIGILL/, /SIGSEGV/, or any other implementation-defined
value corresponding to a computational exception, the behavior is
undefined; otherwise the program will resume execution at the point
it was interrupted.
If the signal occurs as the result of calling the /abort/ or /raise/
function, the signal handler shall not call the /raise/ function.
If the signal occurs other than as the result of calling the /abort/
or /raise/ function, the behavior is undefined if the signal handler
refers to any object with static storage duration other than by
assigning a value to an object declared as /volatile sig_atomic_t/,
or the signal handler calls any function in the standard library other
than the /abort/ function, the /_exit/ function, or the /signal/
function with the first argument equal to the signal number
corresponding to the signal that caused the invocation of the handler.
Furthermore, if such a call to the /signal/ function results in a
/SIG_ERR/ return, the value of /errno/ is indeterminate. [189]
In subclause 7.11.1.1 paragraph 7, change:
... for the most recent call to /signal/ for ...
to:
... for the most recent successful call to /signal/ for ...
In subclause 7.11.2.1 (The raise function), change paragraph 2 from:
The /raise/ function sends the signal /sig/ to the executing
program.
to:
The /raise/ function carries out the actions described in subclause
7.11.1.1 for the signal /sig/. If a signal handler is called, the
/raise/ function shall not return until after the signal handler does.
Add a new subclause 7.14.4.4 within 7.14.4 (Communication with the
environment), renumbering subsequent subclauses.
7.14.4.4 The _exit function
Synopsis
#include <stdlib.h>
void _exit (int status);
Description
The /_exit/ function causes normal program termination to occur
immediately. Control is returned to the host environment. The status
returned is determined in the same manner as for the /exit/ function.
It is implementation-defined whether open output streams are flushed
or open streams closed or temporary files removed.