From: g0dil Date: Wed, 18 Feb 2009 12:52:32 +0000 (+0000) Subject: Scheduler: Make senf::scheduler::hangCount() reset the hang counter X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=b5d7667a0ee87f023a74df607b582b976241dcf7;p=senf.git Scheduler: Make senf::scheduler::hangCount() reset the hang counter Scheduler: Implement BlockSignals helper class git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1124 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Scheduler/FIFORunner.cci b/Scheduler/FIFORunner.cci index d363dac..04afdcd 100644 --- a/Scheduler/FIFORunner.cci +++ b/Scheduler/FIFORunner.cci @@ -124,9 +124,10 @@ prefix_ unsigned senf::scheduler::detail::FIFORunner::taskTimeout() } prefix_ unsigned senf::scheduler::detail::FIFORunner::hangCount() - const { - return hangCount_; + unsigned hc (hangCount_); + hangCount_ = 0; + return hc; } prefix_ senf::scheduler::detail::FIFORunner::iterator diff --git a/Scheduler/FIFORunner.hh b/Scheduler/FIFORunner.hh index 27b626f..0573d9a 100644 --- a/Scheduler/FIFORunner.hh +++ b/Scheduler/FIFORunner.hh @@ -103,7 +103,7 @@ namespace detail { void startWatchdog(); void stopWatchdog(); - unsigned hangCount() const; + unsigned hangCount(); iterator begin() const; iterator end() const; diff --git a/Scheduler/Scheduler.cc b/Scheduler/Scheduler.cc index 3203d20..f40bf69 100644 --- a/Scheduler/Scheduler.cc +++ b/Scheduler/Scheduler.cc @@ -132,6 +132,33 @@ prefix_ senf::log::time_type senf::scheduler::LogTimeSource::operator()() return eventTime(); } +/////////////////////////////////////////////////////////////////////////// +// senf::scheduler::BlockSignals + +prefix_ senf::scheduler::BlockSignals::BlockSignals(bool initiallyBlocked) + : blocked_ (false) +{ + ::sigfillset(&allSigs_); + if (initiallyBlocked) + block(); +} + +prefix_ void senf::scheduler::BlockSignals::block() +{ + if (blocked_) + return; + ::sigprocmask(SIG_BLOCK, &allSigs_, &savedSigs_); + blocked_ = true; +} + +prefix_ void senf::scheduler::BlockSignals::unblock() +{ + if (!blocked_) + return; + ::sigprocmask(SIG_SETMASK, &savedSigs_, 0); + blocked_ = false; +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ diff --git a/Scheduler/Scheduler.cci b/Scheduler/Scheduler.cci index e85c4a5..b20de6e 100644 --- a/Scheduler/Scheduler.cci +++ b/Scheduler/Scheduler.cci @@ -77,6 +77,20 @@ prefix_ bool senf::scheduler::usingHiresTimers() detail::TimerDispatcher::instance().timerSource()) == 0; } +/////////////////////////////////////////////////////////////////////////// +// senf::scheduler::BlockSignals + +prefix_ senf::scheduler::BlockSignals::~BlockSignals() +{ + unblock(); +} + +prefix_ bool senf::scheduler::BlockSignals::blocked() + const +{ + return blocked_; +} + ///////////////////////////////cci.e/////////////////////////////////////// #undef prefix_ diff --git a/Scheduler/Scheduler.hh b/Scheduler/Scheduler.hh index 142f8eb..033c016 100644 --- a/Scheduler/Scheduler.hh +++ b/Scheduler/Scheduler.hh @@ -28,6 +28,7 @@ #define HH_SENF_Scheduler_Scheduler_ 1 // Custom includes +#include #include "../Utils/Logger/SenfLog.hh" #include "FdEvent.hh" #include "TimerEvent.hh" @@ -229,7 +230,10 @@ namespace scheduler { /** \brief Current task watchdog timeout */ unsigned taskTimeout(); - /** \brief Number of watchdog events */ + /** \brief Number of watchdog events + + calling hangCount() will reset the counter to 0 + */ unsigned hangCount(); /** \brief Switch to using hi resolution timers @@ -291,6 +295,44 @@ namespace scheduler { senf::log::time_type operator()() const; }; + /** \brief Temporarily block all signals + + This class is used to temporarily block all signals in a critical section. + + \code + // Begin critical section + { + senf::scheduler::BlockSignals signalBlocker; + + // critical code executed with all signals blocked + } + // End critical section + \endcode + + You need to take care not to block since even the watchdog timer will be disabled while + executing within a critical section. + */ + class BlockSignals + : boost::noncopyable + { + public: + BlockSignals(bool initiallyBlocked=true); + ///< Block signals until end of scope + /**< \param[in] initiallyBlocked set to \c false to not + automatically block signals initially */ + ~BlockSignals(); ///< Release all signal blocks + + void block(); ///< Block signals if not blocked + void unblock(); ///< Unblock signals if blocked + bool blocked() const; ///< \c true, if signals currently blocked, \c false + ///< otherwise + + private: + bool blocked_; + sigset_t allSigs_; + sigset_t savedSigs_; + }; + }} ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Scheduler/Scheduler.test.cc b/Scheduler/Scheduler.test.cc index c23b6c9..b8c5b50 100644 --- a/Scheduler/Scheduler.test.cc +++ b/Scheduler/Scheduler.test.cc @@ -45,8 +45,6 @@ #define prefix_ ///////////////////////////////cc.p//////////////////////////////////////// -using namespace senf; - namespace { char const * SOCK_PATH = "/tmp/sched_test.sock"; @@ -186,16 +184,16 @@ namespace { callback(handle.fd_,event); } - bool is_close(ClockService::clock_type a, ClockService::clock_type b) + bool is_close(senf::ClockService::clock_type a, senf::ClockService::clock_type b) { - return (a= 8u ); - BOOST_CHECK( ! senf::scheduler::usingHiresTimers() ); - + /////////////////////////////////////////////////////////////////////////// close(sock); @@ -328,6 +325,56 @@ BOOST_AUTO_UNIT_TEST(testScheduler) BOOST_CHECK (stop_server(pid)); } +BOOST_AUTO_UNIT_TEST(testSchedulerPollTimers) +{ + BOOST_CHECK( ! senf::scheduler::usingHiresTimers() ); + schedulerTest(); +} + +BOOST_AUTO_UNIT_TEST(testSchedulerHiresTimers) +{ + senf::scheduler::hiresTimers(); + BOOST_CHECK( senf::scheduler::usingHiresTimers() ); + schedulerTest(); + senf::scheduler::loresTimers(); + BOOST_CHECK( ! senf::scheduler::usingHiresTimers() ); +} + +namespace { + + void sigme() + { + senf::scheduler::BlockSignals signalBlocker; + signalBlocker.block(); + signalBlocker.unblock(); + BOOST_CHECK( ! signalBlocker.blocked() ); + signalBlocker.unblock(); + signalBlocker.block(); + BOOST_CHECK( signalBlocker.blocked() ); + ::kill(::getpid(), SIGUSR1); + delay(200); + } + +} + +BOOST_AUTO_UNIT_TEST(blockSignals) +{ + senf::scheduler::TimerEvent signaler ("sigme", &sigme, senf::ClockService::now()); + senf::scheduler::TimerEvent timer ( + "testWatchdog", &timeout, senf::ClockService::now()+senf::ClockService::milliseconds(400)); + senf::scheduler::SignalEvent sig (SIGUSR1, &sigusr); + + senf::ClockService::clock_type t = senf::ClockService::now(); + BOOST_CHECK_NO_THROW( senf::scheduler::process() ); + + BOOST_CHECK_PREDICATE( is_close, + (senf::ClockService::now()) + (t+senf::ClockService::milliseconds(200)) ); + BOOST_CHECK_PREDICATE( is_close, (sigtime) (t+senf::ClockService::milliseconds(200)) ); + + BOOST_CHECK_NO_THROW( senf::scheduler::process() ); +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_