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