ISO/ IEC 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.