24 #include <senf/config.hh> 45 static void watchdogDefaultOutput(std::string
const & taskName, std::string
const & checkPointName, std::string
const & backTrace,
46 unsigned periodInMs,
unsigned numPeriods)
48 senf::IGNORE( write(1,
"*** Scheduler task hanging (pid ", 32) );
50 ::snprintf(pid, 7,
"%6d", ::getpid());
52 senf::IGNORE( write(1, pid, 6) );
53 senf::IGNORE( write(1,
"): ", 3) );
54 senf::IGNORE( write(1, taskName.c_str(), taskName.size()) );
55 if (!checkPointName.empty()) {
56 senf::IGNORE( write(1,
" Last Checkpoint: ", 19));
57 senf::IGNORE( write(1, checkPointName.c_str(), checkPointName.size()) );
59 senf::IGNORE( write(1,
"\n", 1) );
61 if (!backTrace.empty()) {
62 senf::IGNORE( write(1,
"Task was initialized at\n", 24) );
63 senf::IGNORE( write(1, backTrace.c_str(), backTrace.size()) );
64 senf::IGNORE( write(1,
"\n", 1) );
72 prefix_ senf::scheduler::detail::FIFORunner::FIFORunner()
73 : tasks_ (), next_ (tasks_.end()), watchdogRunning_ (
false), watchdogMs_ (1000),
74 watchdogAbort_ (
false), watchdogCheckpoint_(
nullptr), runningTask_(
nullptr),
75 watchdogCallback_(::watchdogDefaultOutput),
76 watchdogCount_(0), hangCount_ (0), yield_ (
false)
79 ::memset(&ev, 0,
sizeof(ev));
80 ev.sigev_notify = SIGEV_SIGNAL;
81 ev.sigev_signo = SIGURG;
82 ev.sigev_value.sival_ptr =
this;
83 if (timer_create(CLOCK_MONOTONIC, &ev, &watchdogId_) < 0)
87 ::memset(&sa, 0,
sizeof(sa));
88 sa.sa_sigaction = &watchdog;
89 sa.sa_flags = SA_SIGINFO;
90 if (sigaction(SIGURG, &sa, 0) < 0)
95 sigaddset(&mask, SIGURG);
96 if (sigprocmask(SIG_UNBLOCK, &mask, 0) < 0)
99 tasks_.push_back(highPriorityEnd_);
100 tasks_.push_back(normalPriorityEnd_);
102 #ifndef SENF_DISABLE_CONSOLE 103 namespace fty = console::factory;
106 .doc(
"Get current watchdog abort on event status.") );
109 .doc(
"Enable/disable abort on watchdog event.") );
112 .doc(
"Get current watchdog timeout in milliseconds") );
115 .doc(
"Set watchdog timeout to in milliseconds\n" 116 "Setting the watchdog timeout to 0 will disable the watchdog.") );
118 .doc(
"Get number of occurred watchdog events.\n" 119 "Calling this method will reset the counter to 0") );
123 prefix_ senf::scheduler::detail::FIFORunner::~FIFORunner()
125 timer_delete(watchdogId_);
128 #ifndef SENF_DISABLE_CONSOLE 137 if (watchdogMs_ > 0) {
138 struct itimerspec timer;
139 ::memset(&timer, 0,
sizeof(timer));
141 timer.it_interval.tv_sec = watchdogMs_ / 1000;
142 timer.it_interval.tv_nsec = (watchdogMs_ % 1000) * 1000000ul;
143 timer.it_value.tv_sec = timer.it_interval.tv_sec;
144 timer.it_value.tv_nsec = timer.it_interval.tv_nsec;
146 if (timer_settime(watchdogId_, 0, &timer, 0) < 0)
149 watchdogRunning_ =
true;
157 struct itimerspec timer;
158 ::memset(&timer, 0,
sizeof(timer));
160 if (timer_settime(watchdogId_, 0, &timer, 0) < 0)
163 watchdogRunning_ =
false;
190 TaskList::iterator i (TaskList::s_iterator_to(*task));
193 if (runningTask_ == task) {
194 runningTask_ =
nullptr;
195 runningName_ = task->
name();
196 #ifdef SENF_BACKTRACE 197 runningBacktrace_ = task->backtrace_;
206 TaskList::iterator f (tasks_.begin());
207 TaskList::iterator l (TaskList::s_iterator_to(highPriorityEnd_));
215 l = TaskList::s_iterator_to(normalPriorityEnd_);
249 TaskList::iterator
end (tasks_.insert(l, queueEnd_));
257 runningTask_ = &(*next_);
258 if (runningTask_->runnable_) {
259 runningTask_->runnable_ =
false;
260 TaskList::iterator i (next_);
262 tasks_.splice(l, tasks_, i);
286 prefix_ senf::scheduler::detail::FIFORunner::TaskList::iterator
293 return TaskList::s_iterator_to(normalPriorityEnd_);
295 return TaskList::s_iterator_to(highPriorityEnd_);
297 return tasks_.begin();
300 prefix_ void senf::scheduler::detail::FIFORunner::watchdog(
int, siginfo_t * si,
void *)
302 FIFORunner & runner (*static_cast<FIFORunner *>(si->si_value.sival_ptr));
303 if (runner.watchdogCount_ > 0) {
304 ++ runner.watchdogCount_;
305 if (runner.watchdogCount_ > 2) {
306 ++ runner.hangCount_;
307 runner.watchdogError();
312 prefix_ void senf::scheduler::detail::FIFORunner::watchdogError()
314 std::string taskName (runningTask_ ? runningTask_->
name() : runningName_);
315 std::string checkpointName (watchdogCheckpoint_ ? std::string(watchdogCheckpoint_) : std::string(
""));
316 #ifdef SENF_BACKTRACE 317 std::string backTrace (runningTask_ ? runningTask_->backtrace_ : runningBacktrace_);
319 std::string backTrace (
"");
322 watchdogCallback_(taskName, checkpointName, backTrace, watchdogMs_, watchdogCount_ -1);
#define SENF_MEMBINDFNP(ret, cls, fn, args)
#define SENF_THROW_SYSTEM_EXCEPTION(desc)
FIFORunner public header.
boost::function< R(Args)> membind(R(T::*fn)(Args), T *ob)
StatsDataCollectorKernel signal
GenericNode::ptr remove(std::string const &name)
console::ScopedDirectory & consoleDir()
std::string const & name() const
Get event name.
Scheduler ConsoleDir public header.
void dequeue(TaskInfo *task)
NodeType & add(std::string const &name, boost::shared_ptr< NodeType > node)