Don't use antiquated BSD API's that require global variable, use posix timers

instead.
This commit is contained in:
christos 2011-12-18 22:34:06 +00:00
parent 2e4fce7c78
commit 7bfd5c4933
2 changed files with 47 additions and 37 deletions

View File

@ -27,9 +27,7 @@
// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
extern "C" {
#include <signal.h>
}
#include <csignal>
#include <cerrno>
@ -46,56 +44,69 @@ namespace impl = atf::atf_run;
// Auxiliary functions.
// ------------------------------------------------------------------------
namespace sigalrm {
bool m_fired = false;
impl::timer* m_timer = NULL;
static
void
handler(const int signo)
handler(int signo, siginfo_t *si, void *uc)
{
PRE(signo == SIGALRM);
impl::timer *timer = static_cast<impl::timer *>(si->si_value.sival_ptr);
m_fired = true;
m_timer->timeout_callback();
timer->setfired();
timer->timeout_callback();
}
} // anonymous namespace
// ------------------------------------------------------------------------
// The "timer" class.
// ------------------------------------------------------------------------
impl::timer::timer(const unsigned int seconds)
impl::timer::timer(const unsigned int seconds) : m_fired(false)
{
sigalrm::m_fired = false;
sigalrm::m_timer = this;
m_sigalrm.reset(new signal_programmer(SIGALRM, sigalrm::handler));
struct sigaction sa;
::sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = ::handler;
if (::sigaction(SIGALRM, &sa, &m_old_sa) == -1)
throw system_error(IMPL_NAME "::timer::timer",
"Failed to set signal handler", errno);
::itimerval timeval;
timeval.it_interval.tv_sec = 0;
timeval.it_interval.tv_usec = 0;
timeval.it_value.tv_sec = seconds;
timeval.it_value.tv_usec = 0;
::sigevent se;
se.sigev_notify = SIGEV_SIGNAL;
se.sigev_signo = SIGALRM;
se.sigev_value.sival_ptr = static_cast<void *>(this);
se.sigev_notify_function = NULL;
se.sigev_notify_attributes = NULL;
if (::timer_create(CLOCK_MONOTONIC, &se, &m_timer) == -1) {
::sigaction(SIGALRM, &m_old_sa, NULL);
throw system_error(IMPL_NAME "::timer::timer",
"Failed to create timer", errno);
}
if (::setitimer(ITIMER_REAL, &timeval, &m_old_timeval) == -1)
::itimerspec it;
it.it_interval.tv_sec = 0;
it.it_interval.tv_nsec = 0;
it.it_value.tv_sec = seconds;
it.it_value.tv_nsec = 0;
if (::timer_settime(m_timer, 0, &it, &m_old_it) == -1) {
::sigaction(SIGALRM, &m_old_sa, NULL);
::timer_delete(m_timer);
throw system_error(IMPL_NAME "::timer::timer",
"Failed to program timer", errno);
}
}
impl::timer::~timer(void)
{
const int ret = ::setitimer(ITIMER_REAL, &m_old_timeval, NULL);
int ret = ::timer_delete(m_timer);
INV(ret != -1);
ret = ::sigaction(SIGALRM, &m_old_sa, NULL);
INV(ret != -1);
sigalrm::m_timer = NULL;
sigalrm::m_fired = false;
}
bool
impl::timer::fired(void)
const
{
return sigalrm::m_fired;
return m_fired;
}
// ------------------------------------------------------------------------
@ -121,5 +132,5 @@ impl::child_timer::timeout_callback(void)
// Should use killpg(2) but, according to signal(7), using this system
// call in a signal handler context is not safe.
::kill(m_pid, SIGKILL);
::killpg(-m_pid, SIGKILL);
}

View File

@ -30,12 +30,8 @@
#if !defined(_ATF_RUN_ALARM_HPP_)
#define _ATF_RUN_ALARM_HPP_
extern "C" {
#include <sys/time.h>
#include <sys/types.h>
}
#include <memory>
#include <ctime>
#include <csignal>
#include "atf-c++/utils.hpp"
@ -49,14 +45,17 @@ class signal_programmer;
// ------------------------------------------------------------------------
class timer : utils::noncopyable {
::itimerval m_old_timeval;
std::auto_ptr< signal_programmer > m_sigalrm;
::timer_t m_timer;
::itimerspec m_old_it;
struct sigaction m_old_sa;
bool m_fired;
public:
timer(const unsigned int);
virtual ~timer(void);
bool fired(void) const;
void setfired(void) { m_fired = true; }
virtual void timeout_callback(void) = 0;
};