xref: /netbsd-src/external/bsd/atf/dist/tools/signals.cpp (revision fd47ea3b40d298c9ba54aa9de2014566b9795699)
1d780102eSjmmv //
2d780102eSjmmv // Automated Testing Framework (atf)
3d780102eSjmmv //
4d780102eSjmmv // Copyright (c) 2007 The NetBSD Foundation, Inc.
5d780102eSjmmv // All rights reserved.
6d780102eSjmmv //
7d780102eSjmmv // Redistribution and use in source and binary forms, with or without
8d780102eSjmmv // modification, are permitted provided that the following conditions
9d780102eSjmmv // are met:
10d780102eSjmmv // 1. Redistributions of source code must retain the above copyright
11d780102eSjmmv //    notice, this list of conditions and the following disclaimer.
12d780102eSjmmv // 2. Redistributions in binary form must reproduce the above copyright
13d780102eSjmmv //    notice, this list of conditions and the following disclaimer in the
14d780102eSjmmv //    documentation and/or other materials provided with the distribution.
15d780102eSjmmv //
16d780102eSjmmv // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17d780102eSjmmv // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18d780102eSjmmv // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19d780102eSjmmv // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20d780102eSjmmv // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21d780102eSjmmv // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22d780102eSjmmv // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23d780102eSjmmv // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24d780102eSjmmv // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25d780102eSjmmv // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26d780102eSjmmv // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27d780102eSjmmv // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28d780102eSjmmv //
29d780102eSjmmv 
30d780102eSjmmv extern "C" {
31d780102eSjmmv #include <signal.h>
32d780102eSjmmv #include <unistd.h>
33d780102eSjmmv }
34d780102eSjmmv 
35d780102eSjmmv #include <cerrno>
36d780102eSjmmv #include <cstdlib>
37d780102eSjmmv 
38d780102eSjmmv #include "exceptions.hpp"
39d780102eSjmmv #include "signals.hpp"
40d780102eSjmmv 
41d780102eSjmmv namespace impl = tools::signals;
42d780102eSjmmv #define IMPL_NAME "tools::signals"
43d780102eSjmmv 
44*fd47ea3bSjmmv #define LAST_SIGNO 63
45d780102eSjmmv const int impl::last_signo = LAST_SIGNO;
46d780102eSjmmv 
47d780102eSjmmv // ------------------------------------------------------------------------
48d780102eSjmmv // The "signal_holder" class.
49d780102eSjmmv // ------------------------------------------------------------------------
50d780102eSjmmv 
51d780102eSjmmv namespace {
52d780102eSjmmv 
53d780102eSjmmv static bool happened[LAST_SIGNO + 1];
54d780102eSjmmv 
55d780102eSjmmv static
56d780102eSjmmv void
holder_handler(const int signo)57d780102eSjmmv holder_handler(const int signo)
58d780102eSjmmv {
59d780102eSjmmv     happened[signo] = true;
60d780102eSjmmv }
61d780102eSjmmv 
62d780102eSjmmv } // anonymous namespace
63d780102eSjmmv 
signal_holder(const int signo)64d780102eSjmmv impl::signal_holder::signal_holder(const int signo) :
65d780102eSjmmv     m_signo(signo),
66d780102eSjmmv     m_sp(NULL)
67d780102eSjmmv {
68d780102eSjmmv     happened[signo] = false;
69d780102eSjmmv     m_sp = new signal_programmer(m_signo, holder_handler);
70d780102eSjmmv }
71d780102eSjmmv 
~signal_holder(void)72d780102eSjmmv impl::signal_holder::~signal_holder(void)
73d780102eSjmmv {
74d780102eSjmmv     if (m_sp != NULL)
75d780102eSjmmv         delete m_sp;
76d780102eSjmmv 
77d780102eSjmmv     if (happened[m_signo])
78d780102eSjmmv         ::kill(::getpid(), m_signo);
79d780102eSjmmv }
80d780102eSjmmv 
81d780102eSjmmv void
process(void)82d780102eSjmmv impl::signal_holder::process(void)
83d780102eSjmmv {
84d780102eSjmmv     if (happened[m_signo]) {
85d780102eSjmmv         delete m_sp;
86d780102eSjmmv         m_sp = NULL;
87d780102eSjmmv         happened[m_signo] = false;
88d780102eSjmmv         ::kill(::getpid(), m_signo);
89d780102eSjmmv         m_sp = new signal_programmer(m_signo, holder_handler);
90d780102eSjmmv     }
91d780102eSjmmv }
92d780102eSjmmv 
93d780102eSjmmv // ------------------------------------------------------------------------
94d780102eSjmmv // The "signal_programmer" class.
95d780102eSjmmv // ------------------------------------------------------------------------
96d780102eSjmmv 
signal_programmer(const int signo,const handler h)97d780102eSjmmv impl::signal_programmer::signal_programmer(const int signo, const handler h) :
98d780102eSjmmv     m_signo(signo),
99d780102eSjmmv     m_handler(h),
100d780102eSjmmv     m_programmed(false)
101d780102eSjmmv {
102d780102eSjmmv     struct ::sigaction sa;
103d780102eSjmmv 
104d780102eSjmmv     sa.sa_handler = m_handler;
105d780102eSjmmv     sigemptyset(&sa.sa_mask);
106d780102eSjmmv     sa.sa_flags = 0;
107d780102eSjmmv 
108d780102eSjmmv     if (::sigaction(m_signo, &sa, &m_oldsa) == -1)
109d780102eSjmmv         throw tools::system_error(IMPL_NAME, "Could not install handler for "
110d780102eSjmmv                                 "signal", errno);
111d780102eSjmmv     m_programmed = true;
112d780102eSjmmv }
113d780102eSjmmv 
~signal_programmer(void)114d780102eSjmmv impl::signal_programmer::~signal_programmer(void)
115d780102eSjmmv {
116d780102eSjmmv     unprogram();
117d780102eSjmmv }
118d780102eSjmmv 
119d780102eSjmmv void
unprogram(void)120d780102eSjmmv impl::signal_programmer::unprogram(void)
121d780102eSjmmv {
122d780102eSjmmv     if (m_programmed) {
123d780102eSjmmv         if (::sigaction(m_signo, &m_oldsa, NULL) == -1)
124d780102eSjmmv             std::abort();
125d780102eSjmmv         m_programmed = false;
126d780102eSjmmv     }
127d780102eSjmmv }
128d780102eSjmmv 
129d780102eSjmmv // ------------------------------------------------------------------------
130d780102eSjmmv // Free functions.
131d780102eSjmmv // ------------------------------------------------------------------------
132d780102eSjmmv 
133d780102eSjmmv void
reset(const int signo)134d780102eSjmmv impl::reset(const int signo)
135d780102eSjmmv {
136d780102eSjmmv     struct ::sigaction sa;
137d780102eSjmmv 
138d780102eSjmmv     sa.sa_handler = SIG_DFL;
139d780102eSjmmv     sigemptyset(&sa.sa_mask);
140d780102eSjmmv     sa.sa_flags = 0;
141d780102eSjmmv 
142d780102eSjmmv     (void)::sigaction(signo, &sa, NULL);
143d780102eSjmmv }
144