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 30extern "C" { 31#include <signal.h> 32} 33 34#include <cerrno> 35 36#include "atf-c++/detail/exceptions.hpp" 37#include "atf-c++/detail/sanity.hpp" 38 39#include "signals.hpp" 40#include "timer.hpp" 41 42namespace impl = atf::atf_run; 43#define IMPL_NAME "atf::atf_run" 44 45// ------------------------------------------------------------------------ 46// Auxiliary functions. 47// ------------------------------------------------------------------------ 48 49namespace sigalrm { 50 51bool m_fired = false; 52impl::timer* m_timer = NULL; 53 54void 55handler(const int signo) 56{ 57 PRE(signo == SIGALRM); 58 59 m_fired = true; 60 m_timer->timeout_callback(); 61} 62 63} // anonymous namespace 64 65// ------------------------------------------------------------------------ 66// The "timer" class. 67// ------------------------------------------------------------------------ 68 69impl::timer::timer(const unsigned int seconds) 70{ 71 sigalrm::m_fired = false; 72 sigalrm::m_timer = this; 73 m_sigalrm.reset(new signal_programmer(SIGALRM, sigalrm::handler)); 74 75 ::itimerval timeval; 76 timeval.it_interval.tv_sec = 0; 77 timeval.it_interval.tv_usec = 0; 78 timeval.it_value.tv_sec = seconds; 79 timeval.it_value.tv_usec = 0; 80 81 if (::setitimer(ITIMER_REAL, &timeval, &m_old_timeval) == -1) 82 throw system_error(IMPL_NAME "::timer::timer", 83 "Failed to program timer", errno); 84} 85 86impl::timer::~timer(void) 87{ 88 const int ret = ::setitimer(ITIMER_REAL, &m_old_timeval, NULL); 89 INV(ret != -1); 90 sigalrm::m_timer = NULL; 91 sigalrm::m_fired = false; 92} 93 94bool 95impl::timer::fired(void) 96 const 97{ 98 return sigalrm::m_fired; 99} 100 101// ------------------------------------------------------------------------ 102// The "child_timer" class. 103// ------------------------------------------------------------------------ 104 105impl::child_timer::child_timer(const unsigned int seconds, const pid_t pid, 106 volatile bool& terminate) : 107 timer(seconds), 108 m_pid(pid), 109 m_terminate(terminate) 110{ 111} 112 113impl::child_timer::~child_timer(void) 114{ 115} 116 117void 118impl::child_timer::timeout_callback(void) 119{ 120 m_terminate = true; 121 122 // Should use killpg(2) but, according to signal(7), using this system 123 // call in a signal handler context is not safe. 124 ::kill(m_pid, SIGKILL); 125} 126