1 // Copyright 2012 Google Inc. 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 31 extern "C" { 32 #include <signal.h> 33 #include <unistd.h> 34 } 35 36 #include <cstdlib> 37 #include <cstring> 38 #include <set> 39 40 #include "utils/sanity.hpp" 41 #include "utils/signals/exceptions.hpp" 42 #include "utils/signals/programmer.hpp" 43 44 namespace signals = utils::signals; 45 46 47 namespace { 48 49 50 /// The interrupt signal that fired, or -1 if none. 51 static volatile int fired_signal = -1; 52 53 54 /// Collection of PIDs. 55 typedef std::set< pid_t > pids_set; 56 57 58 /// List of processes to kill upon reception of a signal. 59 static pids_set pids_to_kill; 60 61 62 /// Programmer status for the SIGHUP signal. 63 static std::auto_ptr< signals::programmer > sighup_handler; 64 /// Programmer status for the SIGINT signal. 65 static std::auto_ptr< signals::programmer > sigint_handler; 66 /// Programmer status for the SIGTERM signal. 67 static std::auto_ptr< signals::programmer > sigterm_handler; 68 69 70 /// Signal mask to restore after exiting a signal inhibited section. 71 static sigset_t old_sigmask; 72 73 74 /// Whether there is an interrupts_handler object in existence or not. 75 bool interrupts_handler_active = false; 76 77 78 /// Whether there is an interrupts_inhibiter object in existence or not. 79 bool interrupts_inhibiter_active = false; 80 81 82 /// Generic handler to capture interrupt signals. 83 /// 84 /// From this handler, we record that an interrupt has happened so that 85 /// check_interrupt() can know whether there execution has to be stopped or not. 86 /// We also terminate any of our child processes (started by the 87 /// utils::process::children class) so that any ongoing wait(2) system calls 88 /// terminate. 89 /// 90 /// \param signo The signal that caused this handler to be called. 91 static void 92 signal_handler(const int signo) 93 { 94 static const char* message = "[-- Signal caught; please wait for " 95 "cleanup --]\n"; 96 if (::write(STDERR_FILENO, message, std::strlen(message)) == -1) { 97 // We are exiting: the message printed here is only for informational 98 // purposes. If we fail to print it (which probably means something 99 // is really bad), there is not much we can do within the signal 100 // handler, so just ignore this. 101 } 102 103 fired_signal = signo; 104 105 for (pids_set::const_iterator iter = pids_to_kill.begin(); 106 iter != pids_to_kill.end(); ++iter) { 107 // Redirecting the interrupt signal to our child processes does NOT 108 // guarantee that they also terminate. For that to happen, we'd need to 109 // SIGKILL them. 110 // 111 // *However*, because we use this code to invoke the kyua-testers only, 112 // and because we assume that such processes are well-behaved and 113 // terminate according to our expectations, we do it this way, which 114 // allows the testers to know which specific signal made them terminate. 115 (void)::kill(*iter, signo); 116 } 117 } 118 119 120 /// Installs signal handlers for potential interrupts. 121 /// 122 /// \pre Must not have been called before. 123 /// \post The various sig*_handler global variables are atomically updated. 124 static void 125 setup_handlers(void) 126 { 127 PRE(sighup_handler.get() == NULL); 128 PRE(sigint_handler.get() == NULL); 129 PRE(sigterm_handler.get() == NULL); 130 131 // Create the handlers on the stack first so that, if any of them fails, the 132 // stack unwinding cleans things up. 133 std::auto_ptr< signals::programmer > tmp_sighup_handler( 134 new signals::programmer(SIGHUP, signal_handler)); 135 std::auto_ptr< signals::programmer > tmp_sigint_handler( 136 new signals::programmer(SIGINT, signal_handler)); 137 std::auto_ptr< signals::programmer > tmp_sigterm_handler( 138 new signals::programmer(SIGTERM, signal_handler)); 139 140 // Now, update the global pointers, which is an operation that cannot fail. 141 sighup_handler = tmp_sighup_handler; 142 sigint_handler = tmp_sigint_handler; 143 sigterm_handler = tmp_sigterm_handler; 144 } 145 146 147 /// Uninstalls the signal handlers installed by setup_handlers(). 148 static void 149 cleanup_handlers(void) 150 { 151 sighup_handler->unprogram(); sighup_handler.reset(NULL); 152 sigint_handler->unprogram(); sigint_handler.reset(NULL); 153 sigterm_handler->unprogram(); sigterm_handler.reset(NULL); 154 } 155 156 157 158 /// Masks the signals installed by setup_handlers(). 159 static void 160 mask_signals(void) 161 { 162 sigset_t mask; 163 sigemptyset(&mask); 164 sigaddset(&mask, SIGHUP); 165 sigaddset(&mask, SIGINT); 166 sigaddset(&mask, SIGTERM); 167 #if defined(__minix) && !defined(NDEBUG) 168 const int ret = 169 #endif /* defined(__minix) && !defined(NDEBUG) */ 170 ::sigprocmask(SIG_BLOCK, &mask, &old_sigmask); 171 INV(ret != -1); 172 } 173 174 175 /// Resets the signal masking put in place by mask_signals(). 176 static void 177 unmask_signals(void) 178 { 179 #if defined(__minix) && !defined(NDEBUG) 180 const int ret = 181 #endif /* defined(__minix) && !defined(NDEBUG) */ 182 ::sigprocmask(SIG_SETMASK, &old_sigmask, NULL); 183 INV(ret != -1); 184 } 185 186 187 } // anonymous namespace 188 189 190 /// Constructor that sets up the signal handlers. 191 signals::interrupts_handler::interrupts_handler(void) 192 { 193 PRE(!interrupts_handler_active); 194 setup_handlers(); 195 interrupts_handler_active = true; 196 } 197 198 199 /// Destructor that removes the signal handlers. 200 signals::interrupts_handler::~interrupts_handler(void) 201 { 202 cleanup_handlers(); 203 interrupts_handler_active = false; 204 } 205 206 207 /// Constructor that sets up signal masking. 208 signals::interrupts_inhibiter::interrupts_inhibiter(void) 209 { 210 PRE(!interrupts_inhibiter_active); 211 mask_signals(); 212 interrupts_inhibiter_active = true; 213 } 214 215 216 /// Destructor that removes signal masking. 217 signals::interrupts_inhibiter::~interrupts_inhibiter(void) 218 { 219 unmask_signals(); 220 interrupts_inhibiter_active = false; 221 } 222 223 224 /// Checks if an interrupt has fired. 225 /// 226 /// Calls to this function should be sprinkled in strategic places through the 227 /// code protected by an interrupts_handler object. 228 /// 229 /// \throw interrupted_error If there has been an interrupt. 230 void 231 signals::check_interrupt(void) 232 { 233 if (fired_signal != -1) 234 throw interrupted_error(fired_signal); 235 } 236 237 238 /// Registers a child process to be killed upon reception of an interrupt. 239 /// 240 /// \pre Must be called with interrupts being inhibited. The caller must ensure 241 /// that the call call to fork() and the addition of the PID happen atomically. 242 /// 243 /// \param pid The PID of the child process. Must not have been yet regsitered. 244 void 245 signals::add_pid_to_kill(const pid_t pid) 246 { 247 PRE(interrupts_inhibiter_active); 248 PRE(pids_to_kill.find(pid) == pids_to_kill.end()); 249 pids_to_kill.insert(pid); 250 } 251 252 253 /// Unregisters a child process previously registered via add_pid_to_kill(). 254 /// 255 /// \pre Must be called with interrupts being inhibited. This is not necessary, 256 /// but pushing this to the caller simplifies our logic and provides consistency 257 /// with the add_pid_to_kill() call. 258 /// 259 /// \param pid The PID of the child process. Must have been registered 260 /// previously, and the process must have already been awaited for. 261 void 262 signals::remove_pid_to_kill(const pid_t pid) 263 { 264 PRE(interrupts_inhibiter_active); 265 PRE(pids_to_kill.find(pid) != pids_to_kill.end()); 266 pids_to_kill.erase(pid); 267 } 268