1// 2// Automated Testing Framework (atf) 3// 4// Copyright (c) 2010 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 34extern "C" { 35#include <sys/time.h> 36} 37 38#include <cerrno> 39#include <csignal> 40#include <ctime> 41 42extern "C" { 43#include "atf-c/defs.h" 44} 45 46#include "atf-c++/detail/exceptions.hpp" 47#include "atf-c++/detail/sanity.hpp" 48 49#include "signals.hpp" 50#include "timer.hpp" 51 52namespace impl = atf::atf_run; 53#define IMPL_NAME "atf::atf_run" 54 55#if !defined(HAVE_TIMER_T) 56static impl::timer* compat_handle; 57#endif 58 59// ------------------------------------------------------------------------ 60// Auxiliary functions. 61// ------------------------------------------------------------------------ 62 63#if defined(HAVE_TIMER_T) 64static 65void 66handler(const int signo ATF_DEFS_ATTRIBUTE_UNUSED, siginfo_t* si, 67 void* uc ATF_DEFS_ATTRIBUTE_UNUSED) 68{ 69 impl::timer* timer = static_cast< impl::timer* >(si->si_value.sival_ptr); 70 timer->set_fired(); 71 timer->timeout_callback(); 72} 73#else 74static 75void 76handler(const int signo ATF_DEFS_ATTRIBUTE_UNUSED, 77 siginfo_t* si ATF_DEFS_ATTRIBUTE_UNUSED, 78 void* uc ATF_DEFS_ATTRIBUTE_UNUSED) 79{ 80 compat_handle->set_fired(); 81 compat_handle->timeout_callback(); 82} 83#endif 84 85// ------------------------------------------------------------------------ 86// The "timer" class. 87// ------------------------------------------------------------------------ 88 89struct impl::timer::impl { 90#if defined(HAVE_TIMER_T) 91 ::timer_t m_timer; 92 ::itimerspec m_old_it; 93#else 94 ::itimerval m_old_it; 95#endif 96 97 struct ::sigaction m_old_sa; 98 volatile bool m_fired; 99 100 impl(void) : m_fired(false) 101 { 102 } 103}; 104 105impl::timer::timer(const unsigned int seconds) : 106 m_pimpl(new impl()) 107{ 108 struct ::sigaction sa; 109 sigemptyset(&sa.sa_mask); 110 sa.sa_flags = SA_SIGINFO; 111 sa.sa_sigaction = ::handler; 112 if (::sigaction(SIGALRM, &sa, &m_pimpl->m_old_sa) == -1) 113 throw system_error(IMPL_NAME "::timer::timer", 114 "Failed to set signal handler", errno); 115 116#if defined(HAVE_TIMER_T) 117 struct ::sigevent se; 118 se.sigev_notify = SIGEV_SIGNAL; 119 se.sigev_signo = SIGALRM; 120 se.sigev_value.sival_ptr = static_cast< void* >(this); 121 se.sigev_notify_function = NULL; 122 se.sigev_notify_attributes = NULL; 123 if (::timer_create(CLOCK_MONOTONIC, &se, &m_pimpl->m_timer) == -1) { 124 ::sigaction(SIGALRM, &m_pimpl->m_old_sa, NULL); 125 throw system_error(IMPL_NAME "::timer::timer", 126 "Failed to create timer", errno); 127 } 128 129 struct ::itimerspec it; 130 it.it_interval.tv_sec = 0; 131 it.it_interval.tv_nsec = 0; 132 it.it_value.tv_sec = seconds; 133 it.it_value.tv_nsec = 0; 134 if (::timer_settime(m_pimpl->m_timer, 0, &it, &m_pimpl->m_old_it) == -1) { 135 ::sigaction(SIGALRM, &m_pimpl->m_old_sa, NULL); 136 ::timer_delete(m_pimpl->m_timer); 137 throw system_error(IMPL_NAME "::timer::timer", 138 "Failed to program timer", errno); 139 } 140#else 141 ::itimerval it; 142 it.it_interval.tv_sec = 0; 143 it.it_interval.tv_usec = 0; 144 it.it_value.tv_sec = seconds; 145 it.it_value.tv_usec = 0; 146 if (::setitimer(ITIMER_REAL, &it, &m_pimpl->m_old_it) == -1) { 147 ::sigaction(SIGALRM, &m_pimpl->m_old_sa, NULL); 148 throw system_error(IMPL_NAME "::timer::timer", 149 "Failed to program timer", errno); 150 } 151 INV(compat_handle == NULL); 152 compat_handle = this; 153#endif 154} 155 156impl::timer::~timer(void) 157{ 158#if defined(HAVE_TIMER_T) 159 { 160 const int ret = ::timer_delete(m_pimpl->m_timer); 161 INV(ret != -1); 162 } 163#else 164 { 165 const int ret = ::setitimer(ITIMER_REAL, &m_pimpl->m_old_it, NULL); 166 INV(ret != -1); 167 } 168#endif 169 const int ret = ::sigaction(SIGALRM, &m_pimpl->m_old_sa, NULL); 170 INV(ret != -1); 171 172#if !defined(HAVE_TIMER_T) 173 compat_handle = NULL; 174#endif 175} 176 177bool 178impl::timer::fired(void) 179 const 180{ 181 return m_pimpl->m_fired; 182} 183 184void 185impl::timer::set_fired(void) 186{ 187 m_pimpl->m_fired = true; 188} 189 190// ------------------------------------------------------------------------ 191// The "child_timer" class. 192// ------------------------------------------------------------------------ 193 194impl::child_timer::child_timer(const unsigned int seconds, const pid_t pid, 195 volatile bool& terminate) : 196 timer(seconds), 197 m_pid(pid), 198 m_terminate(terminate) 199{ 200} 201 202impl::child_timer::~child_timer(void) 203{ 204} 205 206void 207impl::child_timer::timeout_callback(void) 208{ 209 static const timespec ts = { 1, 0 }; 210 m_terminate = true; 211 ::kill(-m_pid, SIGTERM); 212 ::nanosleep(&ts, NULL); 213 if (::kill(-m_pid, 0) != -1) 214 ::kill(-m_pid, SIGKILL); 215} 216