#define HH_SENF_Scheduler_Scheduler_ 1
// Custom includes
+#include <boost/utility.hpp>
#include "../Utils/Logger/SenfLog.hh"
#include "FdEvent.hh"
#include "TimerEvent.hh"
/** \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
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////////////////////////////////////////
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
-using namespace senf;
-
namespace {
char const * SOCK_PATH = "/tmp/sched_test.sock";
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<b ? b-a : a-b) < ClockService::milliseconds(100);
+ return (a<b ? b-a : a-b) < senf::ClockService::milliseconds(100);
}
- ClockService::clock_type sigtime (0);
+ senf::ClockService::clock_type sigtime (0);
void sigusr(siginfo_t const &)
{
- sigtime = ClockService::now();
+ sigtime = senf::ClockService::now();
senf::scheduler::terminate();
}
}
}
-BOOST_AUTO_UNIT_TEST(testScheduler)
+void schedulerTest()
{
int pid = start_server();
BOOST_REQUIRE (pid);
{
senf::scheduler::TimerEvent timer1 ("testTimer1", &timeout,
- ClockService::now()+ClockService::milliseconds(200));
+ senf::ClockService::now()+senf::ClockService::milliseconds(200));
senf::scheduler::TimerEvent timer2 ("testTimer2", &timeout,
- ClockService::now()+ClockService::milliseconds(400));
+ senf::ClockService::now()+senf::ClockService::milliseconds(400));
event = senf::scheduler::FdEvent::EV_NONE;
- ClockService::clock_type t (ClockService::now());
+ senf::ClockService::clock_type t (senf::ClockService::now());
BOOST_CHECK_NO_THROW( senf::scheduler::process() );
- BOOST_CHECK_PREDICATE( is_close, (ClockService::now()-t) (ClockService::milliseconds(200)) );
+ BOOST_CHECK_PREDICATE( is_close, (senf::ClockService::now()-t) (senf::ClockService::milliseconds(200)) );
BOOST_CHECK( timeoutCalled );
BOOST_CHECK( ! timer1.enabled() );
BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_NONE );
- BOOST_CHECK_PREDICATE( is_close, (ClockService::now()) (senf::scheduler::eventTime()) );
+ BOOST_CHECK_PREDICATE( is_close, (senf::ClockService::now()) (senf::scheduler::eventTime()) );
timeoutCalled = false;
BOOST_CHECK_NO_THROW( senf::scheduler::process() );
- BOOST_CHECK_PREDICATE( is_close, (ClockService::now()-t) (ClockService::milliseconds(400)) );
+ BOOST_CHECK_PREDICATE( is_close, (senf::ClockService::now()-t) (senf::ClockService::milliseconds(400)) );
BOOST_CHECK( timeoutCalled );
BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_NONE );
BOOST_CHECK( ! timer2.enabled() );
BOOST_WARN_MESSAGE( false, "A 'Scheduler task hanging' error is expected to be signaled here." );
BOOST_CHECK_NO_THROW( timer1.action(&blockingHandler) );
- BOOST_CHECK_NO_THROW( timer1.timeout(ClockService::now()) );
+ BOOST_CHECK_NO_THROW( timer1.timeout(senf::ClockService::now()) );
BOOST_CHECK_NO_THROW( senf::scheduler::process() );
BOOST_CHECK_EQUAL( senf::scheduler::hangCount(), 1u );
}
{
senf::scheduler::TimerEvent timer ("testWatchdog", &timeout,
- ClockService::now()+ClockService::milliseconds(400));
+ senf::ClockService::now()+senf::ClockService::milliseconds(400));
senf::scheduler::SignalEvent sig (SIGUSR1, &sigusr);
- ClockService::clock_type t = ClockService::now();
+ senf::ClockService::clock_type t = senf::ClockService::now();
::kill(::getpid(), SIGUSR1);
- delay(100);
+ delay(200);
BOOST_CHECK_NO_THROW( senf::scheduler::process() );
- BOOST_CHECK_PREDICATE( is_close, (ClockService::now()) (t+ClockService::milliseconds(200)) );
- BOOST_CHECK_PREDICATE( is_close, (sigtime) (t+ClockService::milliseconds(200)) );
+ 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() );
}
BOOST_CHECK( eventCount >= 8u );
- BOOST_CHECK( ! senf::scheduler::usingHiresTimers() );
-
+
///////////////////////////////////////////////////////////////////////////
close(sock);
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_