1// Copyright 2012 The Kyua Authors.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9//   notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright
11//   notice, this list of conditions and the following disclaimer in the
12//   documentation and/or other materials provided with the distribution.
13// * Neither the name of Google Inc. nor the names of its contributors
14//   may be used to endorse or promote products derived from this software
15//   without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29#include "utils/signals/interrupts.hpp"
30
31extern "C" {
32#include <sys/types.h>
33
34#include <signal.h>
35#include <unistd.h>
36}
37
38#include <cstdlib>
39#include <cstring>
40#include <set>
41
42#include "utils/logging/macros.hpp"
43#include "utils/process/operations.hpp"
44#include "utils/sanity.hpp"
45#include "utils/signals/exceptions.hpp"
46#include "utils/signals/programmer.hpp"
47
48namespace signals = utils::signals;
49namespace process = utils::process;
50
51
52namespace {
53
54
55/// The interrupt signal that fired, or -1 if none.
56static volatile int fired_signal = -1;
57
58
59/// Collection of PIDs.
60typedef std::set< pid_t > pids_set;
61
62
63/// List of processes to kill upon reception of a signal.
64static pids_set pids_to_kill;
65
66
67/// Programmer status for the SIGHUP signal.
68static std::auto_ptr< signals::programmer > sighup_handler;
69/// Programmer status for the SIGINT signal.
70static std::auto_ptr< signals::programmer > sigint_handler;
71/// Programmer status for the SIGTERM signal.
72static std::auto_ptr< signals::programmer > sigterm_handler;
73
74
75/// Signal mask to restore after exiting a signal inhibited section.
76static sigset_t global_old_sigmask;
77
78
79/// Whether there is an interrupts_handler object in existence or not.
80static bool interrupts_handler_active = false;
81
82
83/// Whether there is an interrupts_inhibiter object in existence or not.
84static std::size_t interrupts_inhibiter_active = 0;
85
86
87/// Generic handler to capture interrupt signals.
88///
89/// From this handler, we record that an interrupt has happened so that
90/// check_interrupt() can know whether there execution has to be stopped or not.
91/// We also terminate any of our child processes (started by the
92/// utils::process::children class) so that any ongoing wait(2) system calls
93/// terminate.
94///
95/// \param signo The signal that caused this handler to be called.
96static void
97signal_handler(const int signo)
98{
99    static const char* message = "[-- Signal caught; please wait for "
100        "cleanup --]\n";
101    if (::write(STDERR_FILENO, message, std::strlen(message)) == -1) {
102        // We are exiting: the message printed here is only for informational
103        // purposes.  If we fail to print it (which probably means something
104        // is really bad), there is not much we can do within the signal
105        // handler, so just ignore this.
106    }
107
108    fired_signal = signo;
109
110    for (pids_set::const_iterator iter = pids_to_kill.begin();
111        iter != pids_to_kill.end(); ++iter) {
112        process::terminate_group(*iter);
113    }
114}
115
116
117/// Installs signal handlers for potential interrupts.
118///
119/// \pre Must not have been called before.
120/// \post The various sig*_handler global variables are atomically updated.
121static void
122setup_handlers(void)
123{
124    PRE(sighup_handler.get() == NULL);
125    PRE(sigint_handler.get() == NULL);
126    PRE(sigterm_handler.get() == NULL);
127
128    // Create the handlers on the stack first so that, if any of them fails, the
129    // stack unwinding cleans things up.
130    std::auto_ptr< signals::programmer > tmp_sighup_handler(
131        new signals::programmer(SIGHUP, signal_handler));
132    std::auto_ptr< signals::programmer > tmp_sigint_handler(
133        new signals::programmer(SIGINT, signal_handler));
134    std::auto_ptr< signals::programmer > tmp_sigterm_handler(
135        new signals::programmer(SIGTERM, signal_handler));
136
137    // Now, update the global pointers, which is an operation that cannot fail.
138    sighup_handler = tmp_sighup_handler;
139    sigint_handler = tmp_sigint_handler;
140    sigterm_handler = tmp_sigterm_handler;
141}
142
143
144/// Uninstalls the signal handlers installed by setup_handlers().
145static void
146cleanup_handlers(void)
147{
148    sighup_handler->unprogram(); sighup_handler.reset(NULL);
149    sigint_handler->unprogram(); sigint_handler.reset(NULL);
150    sigterm_handler->unprogram(); sigterm_handler.reset(NULL);
151}
152
153
154
155/// Masks the signals installed by setup_handlers().
156///
157/// \param[out] old_sigmask The old signal mask to save via the
158///     \code oset \endcode argument with sigprocmask(2).
159static void
160mask_signals(sigset_t* old_sigmask)
161{
162    sigset_t mask;
163    sigemptyset(&mask);
164    sigaddset(&mask, SIGALRM);
165    sigaddset(&mask, SIGHUP);
166    sigaddset(&mask, SIGINT);
167    sigaddset(&mask, SIGTERM);
168    const int ret = ::sigprocmask(SIG_BLOCK, &mask, old_sigmask);
169    INV(ret != -1);
170}
171
172
173/// Resets the signal masking put in place by mask_signals().
174///
175/// \param[in] old_sigmask The old signal mask to restore via the
176///     \code set \endcode argument with sigprocmask(2).
177static void
178unmask_signals(sigset_t* old_sigmask)
179{
180    const int ret = ::sigprocmask(SIG_SETMASK, old_sigmask, NULL);
181    INV(ret != -1);
182}
183
184
185}  // anonymous namespace
186
187
188/// Constructor that sets up the signal handlers.
189signals::interrupts_handler::interrupts_handler(void) :
190    _programmed(false)
191{
192    PRE(!interrupts_handler_active);
193    setup_handlers();
194    _programmed = true;
195    interrupts_handler_active = true;
196}
197
198
199/// Destructor that removes the signal handlers.
200///
201/// Given that this is a destructor and it can't report errors back to the
202/// caller, the caller must attempt to call unprogram() on its own.
203signals::interrupts_handler::~interrupts_handler(void)
204{
205    if (_programmed) {
206        LW("Destroying still-programmed signals::interrupts_handler object");
207        try {
208            unprogram();
209        } catch (const error& e) {
210            UNREACHABLE;
211        }
212    }
213}
214
215
216/// Unprograms all signals captured by the interrupts handler.
217///
218/// \throw system_error If the unprogramming of any signal fails.
219void
220signals::interrupts_handler::unprogram(void)
221{
222    PRE(_programmed);
223
224    // Modify the control variables first before unprogramming the handlers.  If
225    // we fail to do the latter, we do not want to try again because we will not
226    // succeed (and we'll cause a crash due to failed preconditions).
227    _programmed = false;
228    interrupts_handler_active = false;
229
230    cleanup_handlers();
231    fired_signal = -1;
232}
233
234
235/// Constructor that sets up signal masking.
236signals::interrupts_inhibiter::interrupts_inhibiter(void)
237{
238    sigset_t old_sigmask;
239    mask_signals(&old_sigmask);
240    if (interrupts_inhibiter_active == 0) {
241        global_old_sigmask = old_sigmask;
242    }
243    ++interrupts_inhibiter_active;
244}
245
246
247/// Destructor that removes signal masking.
248signals::interrupts_inhibiter::~interrupts_inhibiter(void)
249{
250    if (interrupts_inhibiter_active > 1) {
251        --interrupts_inhibiter_active;
252    } else {
253        interrupts_inhibiter_active = false;
254        unmask_signals(&global_old_sigmask);
255    }
256}
257
258
259/// Checks if an interrupt has fired.
260///
261/// Calls to this function should be sprinkled in strategic places through the
262/// code protected by an interrupts_handler object.
263///
264/// Only one call to this function will raise an exception per signal received.
265/// This is to allow executing cleanup actions without reraising interrupt
266/// exceptions unless the user has fired another interrupt.
267///
268/// \throw interrupted_error If there has been an interrupt.
269void
270signals::check_interrupt(void)
271{
272    if (fired_signal != -1) {
273        const int original_fired_signal = fired_signal;
274        fired_signal = -1;
275        throw interrupted_error(original_fired_signal);
276    }
277}
278
279
280/// Registers a child process to be killed upon reception of an interrupt.
281///
282/// \pre Must be called with interrupts being inhibited.  The caller must ensure
283/// that the call call to fork() and the addition of the PID happen atomically.
284///
285/// \param pid The PID of the child process.  Must not have been yet regsitered.
286void
287signals::add_pid_to_kill(const pid_t pid)
288{
289    PRE(interrupts_inhibiter_active);
290    PRE(pids_to_kill.find(pid) == pids_to_kill.end());
291    pids_to_kill.insert(pid);
292}
293
294
295/// Unregisters a child process previously registered via add_pid_to_kill().
296///
297/// \pre Must be called with interrupts being inhibited.  This is not necessary,
298/// but pushing this to the caller simplifies our logic and provides consistency
299/// with the add_pid_to_kill() call.
300///
301/// \param pid The PID of the child process.  Must have been registered
302///     previously, and the process must have already been awaited for.
303void
304signals::remove_pid_to_kill(const pid_t pid)
305{
306    PRE(interrupts_inhibiter_active);
307    PRE(pids_to_kill.find(pid) != pids_to_kill.end());
308    pids_to_kill.erase(pid);
309}
310