blob: e1ff12d550699f5a7d53577106e24aa58f943d15 [file] [log] [blame]
<html lang="en">
<head>
<title>Merged Signals - The GNU C Library</title>
<meta http-equiv="Content-Type" content="text/html">
<meta name="description" content="The GNU C Library">
<meta name="generator" content="makeinfo 4.13">
<link title="Top" rel="start" href="index.html#Top">
<link rel="up" href="Defining-Handlers.html#Defining-Handlers" title="Defining Handlers">
<link rel="prev" href="Signals-in-Handler.html#Signals-in-Handler" title="Signals in Handler">
<link rel="next" href="Nonreentrancy.html#Nonreentrancy" title="Nonreentrancy">
<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
<!--
This file documents the GNU C library.
This is Edition 0.12, last updated 2007-10-27,
of `The GNU C Library Reference Manual', for version
2.8 (Sourcery G++ Lite 2011.03-41).
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002,
2003, 2007, 2008, 2010 Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with the
Invariant Sections being ``Free Software Needs Free Documentation''
and ``GNU Lesser General Public License'', the Front-Cover texts being
``A GNU Manual'', and with the Back-Cover Texts as in (a) below. A
copy of the license is included in the section entitled "GNU Free
Documentation License".
(a) The FSF's Back-Cover Text is: ``You have the freedom to
copy and modify this GNU manual. Buying copies from the FSF
supports it in developing GNU and promoting software freedom.''-->
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
pre.display { font-family:inherit }
pre.format { font-family:inherit }
pre.smalldisplay { font-family:inherit; font-size:smaller }
pre.smallformat { font-family:inherit; font-size:smaller }
pre.smallexample { font-size:smaller }
pre.smalllisp { font-size:smaller }
span.sc { font-variant:small-caps }
span.roman { font-family:serif; font-weight:normal; }
span.sansserif { font-family:sans-serif; font-weight:normal; }
--></style>
<link rel="stylesheet" type="text/css" href="../cs.css">
</head>
<body>
<div class="node">
<a name="Merged-Signals"></a>
<p>
Next:&nbsp;<a rel="next" accesskey="n" href="Nonreentrancy.html#Nonreentrancy">Nonreentrancy</a>,
Previous:&nbsp;<a rel="previous" accesskey="p" href="Signals-in-Handler.html#Signals-in-Handler">Signals in Handler</a>,
Up:&nbsp;<a rel="up" accesskey="u" href="Defining-Handlers.html#Defining-Handlers">Defining Handlers</a>
<hr>
</div>
<h4 class="subsection">24.4.5 Signals Close Together Merge into One</h4>
<p><a name="index-handling-multiple-signals-2933"></a><a name="index-successive-signals-2934"></a><a name="index-merging-of-signals-2935"></a>
If multiple signals of the same type are delivered to your process
before your signal handler has a chance to be invoked at all, the
handler may only be invoked once, as if only a single signal had
arrived. In effect, the signals merge into one. This situation can
arise when the signal is blocked, or in a multiprocessing environment
where the system is busy running some other processes while the signals
are delivered. This means, for example, that you cannot reliably use a
signal handler to count signals. The only distinction you can reliably
make is whether at least one signal has arrived since a given time in
the past.
<p>Here is an example of a handler for <code>SIGCHLD</code> that compensates for
the fact that the number of signals received may not equal the number of
child processes that generate them. It assumes that the program keeps track
of all the child processes with a chain of structures as follows:
<pre class="smallexample"> struct process
{
struct process *next;
/* <span class="roman">The process ID of this child.</span> */
int pid;
/* <span class="roman">The descriptor of the pipe or pseudo terminal</span>
<span class="roman">on which output comes from this child.</span> */
int input_descriptor;
/* <span class="roman">Nonzero if this process has stopped or terminated.</span> */
sig_atomic_t have_status;
/* <span class="roman">The status of this child; 0 if running,</span>
<span class="roman">otherwise a status value from </span><code>waitpid</code><span class="roman">.</span> */
int status;
};
struct process *process_list;
</pre>
<p>This example also uses a flag to indicate whether signals have arrived
since some time in the past&mdash;whenever the program last cleared it to
zero.
<pre class="smallexample"> /* <span class="roman">Nonzero means some child's status has changed</span>
<span class="roman">so look at </span><code>process_list</code><span class="roman"> for the details.</span> */
int process_status_change;
</pre>
<p>Here is the handler itself:
<pre class="smallexample"> void
sigchld_handler (int signo)
{
int old_errno = errno;
while (1) {
register int pid;
int w;
struct process *p;
/* <span class="roman">Keep asking for a status until we get a definitive result.</span> */
do
{
errno = 0;
pid = waitpid (WAIT_ANY, &amp;w, WNOHANG | WUNTRACED);
}
while (pid &lt;= 0 &amp;&amp; errno == EINTR);
if (pid &lt;= 0) {
/* <span class="roman">A real failure means there are no more</span>
<span class="roman">stopped or terminated child processes, so return.</span> */
errno = old_errno;
return;
}
/* <span class="roman">Find the process that signaled us, and record its status.</span> */
for (p = process_list; p; p = p-&gt;next)
if (p-&gt;pid == pid) {
p-&gt;status = w;
/* <span class="roman">Indicate that the </span><code>status</code><span class="roman"> field</span>
<span class="roman">has data to look at. We do this only after storing it.</span> */
p-&gt;have_status = 1;
/* <span class="roman">If process has terminated, stop waiting for its output.</span> */
if (WIFSIGNALED (w) || WIFEXITED (w))
if (p-&gt;input_descriptor)
FD_CLR (p-&gt;input_descriptor, &amp;input_wait_mask);
/* <span class="roman">The program should check this flag from time to time</span>
<span class="roman">to see if there is any news in </span><code>process_list</code><span class="roman">.</span> */
++process_status_change;
}
/* <span class="roman">Loop around to handle all the processes</span>
<span class="roman">that have something to tell us.</span> */
}
}
</pre>
<p>Here is the proper way to check the flag <code>process_status_change</code>:
<pre class="smallexample"> if (process_status_change) {
struct process *p;
process_status_change = 0;
for (p = process_list; p; p = p-&gt;next)
if (p-&gt;have_status) {
... <span class="roman">Examine </span><code>p-&gt;status</code> ...
}
}
</pre>
<p class="noindent">It is vital to clear the flag before examining the list; otherwise, if a
signal were delivered just before the clearing of the flag, and after
the appropriate element of the process list had been checked, the status
change would go unnoticed until the next signal arrived to set the flag
again. You could, of course, avoid this problem by blocking the signal
while scanning the list, but it is much more elegant to guarantee
correctness by doing things in the right order.
<p>The loop which checks process status avoids examining <code>p-&gt;status</code>
until it sees that status has been validly stored. This is to make sure
that the status cannot change in the middle of accessing it. Once
<code>p-&gt;have_status</code> is set, it means that the child process is stopped
or terminated, and in either case, it cannot stop or terminate again
until the program has taken notice. See <a href="Atomic-Usage.html#Atomic-Usage">Atomic Usage</a>, for more
information about coping with interruptions during accesses of a
variable.
<p>Here is another way you can test whether the handler has run since the
last time you checked. This technique uses a counter which is never
changed outside the handler. Instead of clearing the count, the program
remembers the previous value and sees whether it has changed since the
previous check. The advantage of this method is that different parts of
the program can check independently, each part checking whether there
has been a signal since that part last checked.
<pre class="smallexample"> sig_atomic_t process_status_change;
sig_atomic_t last_process_status_change;
...
{
sig_atomic_t prev = last_process_status_change;
last_process_status_change = process_status_change;
if (last_process_status_change != prev) {
struct process *p;
for (p = process_list; p; p = p-&gt;next)
if (p-&gt;have_status) {
... <span class="roman">Examine </span><code>p-&gt;status</code> ...
}
}
}
</pre>
</body></html>