| <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: <a rel="next" accesskey="n" href="Nonreentrancy.html#Nonreentrancy">Nonreentrancy</a>, |
| Previous: <a rel="previous" accesskey="p" href="Signals-in-Handler.html#Signals-in-Handler">Signals in Handler</a>, |
| Up: <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—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, &w, WNOHANG | WUNTRACED); |
| } |
| while (pid <= 0 && errno == EINTR); |
| |
| if (pid <= 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->next) |
| if (p->pid == pid) { |
| p->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->have_status = 1; |
| |
| /* <span class="roman">If process has terminated, stop waiting for its output.</span> */ |
| if (WIFSIGNALED (w) || WIFEXITED (w)) |
| if (p->input_descriptor) |
| FD_CLR (p->input_descriptor, &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->next) |
| if (p->have_status) { |
| ... <span class="roman">Examine </span><code>p->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->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->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->next) |
| if (p->have_status) { |
| ... <span class="roman">Examine </span><code>p->status</code> ... |
| } |
| } |
| } |
| </pre> |
| </body></html> |
| |