Messages in this thread |  | | Date | Thu, 27 Jun 1996 10:09:21 -0600 (MDT) | From | Marc Aurele La France <> | Subject | [Take II] On SIGCHLD signal semantics |
| |
Good day.
This is the readme file for tsi.sigchld.diff.gz which I have uploaded to ftp://ftp.lmh.ox.ac.uk. This is essentially a copy of the Documentation/sigchld.txt file that is inserted by this kernel change.
-------------------------------------------------------------------------------
This kernel contains changes to fix Linux's implementation of SystemV SIGCHLD signal semantics. Specifically, a wait* system call can no longer return the process id of a child process that exited while its parent's SIGCHLD signal handler was SIG_IGN. Previously, this was only true if such a child exited before its parent invoked the wait* system call.
This change will adversely affect programmes that invoke the wait* system call with an inherited SIGCHLD signal handler of SIG_IGN. Under previous kernels, such a call would succeed only if a child exited while its parent was already sleeping in the wait* system call. Otherwise, the call would fail. This meant the programme's behaviour had a timing dependancy. Under this kernel, a wait* system call with an inherited SIGCHLD signal handler of SIG_IGN will always fail. This means programmes that expect BSD-style SIGCHLD signal semantics (where SIG_IGN is equivalent to SIG_DFL) will fail. As a workaround, POSIX suggests that applications always set their SIGCHLD signal handler before calling one of the wait* functions.
Unfortunately, few programmes actually do this. In fact, most BSD utilities that have been ported to Linux fall into this category. Thus, all such applications should be changed to run properly under Linux, regardless of the SIGCHLD signal handler they inherit. A daunting task, to be sure. Rather than requiring this, a number of alternatives have been proposed in an ongoing discussion on the linux-kernel mailing list to address, or help address, this incompatibility between this kernel and BSD. These alternatives modify the above default behaviour in various ways, and, for discussion purposes, have been implemented as compilation options. Unless otherwise specified, these options can be used independently of each other. A description of these options follows. If you have other suggestions, I'd be happy to hear them!
If POSIX_SIGCHLD is #define'd in kernel/exit.c, the kernel will produce warnings when an application makes a wait* system call with a SIGCHLD signal handler it inherited from its parent, or when a child process exits while its parent process is still using an inherited SIGCHLD signal handler of SIG_IGN. These warnings are only intended to highlight the problem, and do not, by themselves, solve it. The warnings are:
Message: Process name1 (pid num1) waits for its children but ignores their signals because it inherited this behaviour from name2.
Explanation: - The name2 programme set its SIGCHLD handler to SIG_IGN. - The name2 programme invoked the name1 programme through one of the exec* system calls. - The name1 programme executed one of the wait* system calls to wait for one or more of its child processes to terminate.
Remedy: - The name2 programme probably needs to be changed to reset its SIGCHLD handler to SIG_DFL before invoking name1. - The name1 programme probably needs to be changed to set its SIGCHLD to SIG_DFL before executing the wait* system call.
Message: Process name1 (pid num1) ignores signals from its children but inherited this behaviour from name2.
Explanation: - The name2 programme set its SIGCHLD handler to SIG_IGN. - The name2 programme invoked the name1 programme through one of the exec* system calls. - One of the name1 programme's child processes terminated.
Remedy: - The name2 programme should probably be changed to reset its SIGCHLD handler to SIG_DFL before invoking name1. - The name1 programme probably needs to be changed to initialize its SIGCHLD handler to either SIG_DFL or SIG_IGN, depending on whether or not it makes a wait* system call.
Message: Process name (pid num) waits for its children but does not ensure it listens to its children.
Explanation: - The name programme executed a wait* system call without doing anything about its SIGCHLD handler.
Remedy: - The name programme should probably be changed to set its SIGCHLD handler to SIG_DFL before executing the wait* system call. Otherwise, it runs the risk of inheriting a SIGCHLD handler of SIG_IGN from a buggy parent process.
To reduce message volume, only one warning is ever produced for the same process. Also, the third of the above messages is never produced twice in a row for the same programme (but different processes).
If BSD_SIGCHLD is #define'd in kernel/exit.c, the above SystemV behaviour is modified such that a wait* system call will never return the process id of a child process that exited while its parent SIGCHLD signal handler was *explicitly* set to (rather than inherited as) SIG_IGN. The end result of this is that applications will be affected by BSD-style SIGCHLD signal semantics from the time they are exec'ed to the time they set their SIGCHLD signal handler, after which SystemV semantics take over. The downside of this is that applications that save and later restore their SIGCHLD signal handler will lose the inherited aspect of that handler. This last point can somewhat be dealt with by the next compilation option.
When a programme is exec'ed, this kernel sets a flag to indicate that the programme's SIGCHLD signal handler was inherited as SIG_IGN. This flag is normally reset when the programme sets its SIGCHLD signal handler. If BSD_SIGCHLD is #define'd in kernel/signal.c however, this flag is only reset when the programme redundantly sets its SIGCHLD signal handler to SIG_IGN. This means that, if BSD_SIGCHLD is also #define'd in kernel/exit.c, chances are high(er) that BSD-style SIGCHLD signal semantics are put back in force when the application restores an inherited SIGCHLD handler of SIG_IGN. The downside here is that it is unlikely the application is aware that its SIGCHLD signal semantics are being changed in this fashion. In addition, this mechanism is not fool-proof.
If BSD_SIGCHLD is defined in fs/exec.c, this kernel will produce a warning when a programme is about to inherit a SIGCHLD signal handler of SIG_IGN and will reset this handler to SIG_DFL. Thus SIG_IGN can never be inherited, which effectively disables the functionality introduced by #define'ing BSD_SIGCHLD in kernel/exit.c and kernel/signal.c, along with all but the last of the warnings produced by #define'ing POSIX_SIGCHLD in kernel/exit.c. The message produced by this option is of the form
Message: Process name1 (pid n) was prevented from causing name2 to inherit SIG_IGN as its SIGCHLD signal handler.
Explanation: The name1 programme was ignoring its children while executing an exec* system call to invoke the name2 programme.
Kernel action: The name2 programme will inherit a SIGCHLD signal handler of SIG_DFL.
There are pros and cons in this option also. This is, by far, the most technically sound solution proposed so far, simply because it minimizes the number of adversely affected applications. This option breaks those programmes that depend on inheriting SIG_IGN as a SIGCHLD handler. The only reliable justification for this dependence that I can think of is the use of an inherited SIGCHLD signal handler as some kind of on/off parameter, but this mechanism can be replaced by a more obvious form of parameter passing. The other downside of this option is that it contravenes POSIX, or, at least, the letter of POSIX. POSIX.1 leaves as unspecified the behaviour of SIG_IGN as a SIGCHLD signal handler, and yet, does not disallow (or leave as unspecified) the inheritance of this behaviour. The rationale section of POSIX.1 tries to compensate for this by recommending that applications not depend on an inherited SIGCHLD signal handler, but this simply ignores the large base of existing programmes that don't implement this recommendation. I suppose one could argue that leaving the behaviour of SIG_IGN as unspecified also implies leaving the inheritance of this behaviour as unspecified, but this might only be wishful thinking on my part. Thus POSIX.1 appears inconsistent in this respect, if one accepts that the 'P' in 'POSIX' stands for 'Portable'...
Note that just because an application is mentionned in one of the above messages, it might well be the case that the application does not call one of the wait system call variants directly. There are also a number of C library calls, such as system() and pclose(), that implicitly issue a wait* system call on their caller's behalf.
I will attempt to address in a timely fashion any questions or concerns about this change that are addressed to Marc Aurele La France <tsi@ualberta.ca>.
-------------------------------------------------------------------------------
.. or to the linux-kernel mailing list.
Marc.
+----------------------------------+-----------------------------------+ | Marc Aurele La France | work: 1-403-492-9310 | | Computing and Network Services | fax: 1-403-492-1729 | | 352 General Services Building | email: tsi@ualberta.ca | | University of Alberta +-----------------------------------+ | Edmonton, Alberta | | | T6G 2H1 | Standard disclaimers apply | | CANADA | | +----------------------------------+-----------------------------------+
|  |