summaryrefslogtreecommitdiffstats
path: root/unit/atf-src/tools/signals.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'unit/atf-src/tools/signals.cpp')
-rw-r--r--unit/atf-src/tools/signals.cpp146
1 files changed, 146 insertions, 0 deletions
diff --git a/unit/atf-src/tools/signals.cpp b/unit/atf-src/tools/signals.cpp
new file mode 100644
index 0000000..1e6c1ff
--- /dev/null
+++ b/unit/atf-src/tools/signals.cpp
@@ -0,0 +1,146 @@
+//
+// Automated Testing Framework (atf)
+//
+// Copyright (c) 2007 The NetBSD Foundation, Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
+// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+#if defined(HAVE_CONFIG_H)
+#include "config.h"
+#endif
+
+extern "C" {
+#include <signal.h>
+#include <unistd.h>
+}
+
+#include <cerrno>
+#include <cstdlib>
+
+#include "exceptions.hpp"
+#include "signals.hpp"
+
+namespace impl = tools::signals;
+#define IMPL_NAME "tools::signals"
+
+const int impl::last_signo = LAST_SIGNO;
+
+// ------------------------------------------------------------------------
+// The "signal_holder" class.
+// ------------------------------------------------------------------------
+
+namespace {
+
+static bool happened[LAST_SIGNO + 1];
+
+static
+void
+holder_handler(const int signo)
+{
+ happened[signo] = true;
+}
+
+} // anonymous namespace
+
+impl::signal_holder::signal_holder(const int signo) :
+ m_signo(signo),
+ m_sp(NULL)
+{
+ happened[signo] = false;
+ m_sp = new signal_programmer(m_signo, holder_handler);
+}
+
+impl::signal_holder::~signal_holder(void)
+{
+ if (m_sp != NULL)
+ delete m_sp;
+
+ if (happened[m_signo])
+ ::kill(::getpid(), m_signo);
+}
+
+void
+impl::signal_holder::process(void)
+{
+ if (happened[m_signo]) {
+ delete m_sp;
+ m_sp = NULL;
+ happened[m_signo] = false;
+ ::kill(::getpid(), m_signo);
+ m_sp = new signal_programmer(m_signo, holder_handler);
+ }
+}
+
+// ------------------------------------------------------------------------
+// The "signal_programmer" class.
+// ------------------------------------------------------------------------
+
+impl::signal_programmer::signal_programmer(const int signo, const handler h) :
+ m_signo(signo),
+ m_handler(h),
+ m_programmed(false)
+{
+ struct ::sigaction sa;
+
+ sa.sa_handler = m_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ if (::sigaction(m_signo, &sa, &m_oldsa) == -1)
+ throw tools::system_error(IMPL_NAME, "Could not install handler for "
+ "signal", errno);
+ m_programmed = true;
+}
+
+impl::signal_programmer::~signal_programmer(void)
+{
+ unprogram();
+}
+
+void
+impl::signal_programmer::unprogram(void)
+{
+ if (m_programmed) {
+ if (::sigaction(m_signo, &m_oldsa, NULL) == -1)
+ std::abort();
+ m_programmed = false;
+ }
+}
+
+// ------------------------------------------------------------------------
+// Free functions.
+// ------------------------------------------------------------------------
+
+void
+impl::reset(const int signo)
+{
+ struct ::sigaction sa;
+
+ sa.sa_handler = SIG_DFL;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ (void)::sigaction(signo, &sa, NULL);
+}