1// Copyright 2010 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/misc.hpp"
30
31#if defined(HAVE_CONFIG_H)
32#   include "config.h"
33#endif
34
35extern "C" {
36#include <signal.h>
37}
38
39#include <cerrno>
40#include <cstddef>
41
42#include "utils/format/macros.hpp"
43#include "utils/logging/macros.hpp"
44#include "utils/signals/exceptions.hpp"
45
46namespace signals = utils::signals;
47
48
49/// Number of the last valid signal.
50const int utils::signals::last_signo = LAST_SIGNO;
51
52
53/// Resets a signal handler to its default behavior.
54///
55/// \param signo The number of the signal handler to reset.
56///
57/// \throw signals::system_error If there is a problem trying to reset the
58///     signal handler to its default behavior.
59void
60signals::reset(const int signo)
61{
62    struct ::sigaction sa;
63    sa.sa_handler = SIG_DFL;
64    sigemptyset(&sa.sa_mask);
65    sa.sa_flags = 0;
66
67    if (::sigaction(signo, &sa, NULL) == -1) {
68        const int original_errno = errno;
69        throw system_error(F("Failed to reset signal %s") % signo,
70                           original_errno);
71    }
72}
73
74
75/// Resets all signals to their default handlers.
76///
77/// \return True if all signals could be reset properly; false otherwise.
78bool
79signals::reset_all(void)
80{
81    bool ok = true;
82
83    for (int signo = 1; signo <= signals::last_signo; ++signo) {
84        if (signo == SIGKILL || signo == SIGSTOP) {
85            // Don't attempt to reset immutable signals.
86        } else {
87            try {
88                signals::reset(signo);
89            } catch (const signals::error& e) {
90#if defined(SIGTHR)
91                if (signo == SIGTHR) {
92                    // If FreeBSD's libthr is loaded, it prevents us from
93                    // modifying SIGTHR (at least in 11.0-CURRENT as of
94                    // 2015-01-28).  Skip failures for this signal if they
95                    // happen to avoid this corner case.
96                    continue;
97                }
98#endif
99                LW(e.what());
100                ok = false;
101            }
102        }
103    }
104
105    return ok;
106}
107