From 09c41819d83be23387a7c6b1447e5c3ee493edce Mon Sep 17 00:00:00 2001 From: randomdan Date: Fri, 20 Dec 2013 21:30:44 +0000 Subject: Improved signal handler Basic scheduler that fires periodic component handlers --- project2/daemon/p2daemonAppEngine.cpp | 82 ++++++++++++++++++++++++++++++----- project2/daemon/p2daemonAppEngine.h | 20 +++++++-- project2/daemon/p2daemonMain.cpp | 1 - 3 files changed, 86 insertions(+), 17 deletions(-) diff --git a/project2/daemon/p2daemonAppEngine.cpp b/project2/daemon/p2daemonAppEngine.cpp index 942ab9f..e5a1b3c 100644 --- a/project2/daemon/p2daemonAppEngine.cpp +++ b/project2/daemon/p2daemonAppEngine.cpp @@ -7,18 +7,23 @@ std::string DaemonAppEngine::daemonType; Glib::ustring DaemonAppEngine::reqPlatform; -DaemonPtr DaemonAppEngine::daemon; +int DaemonAppEngine::periodicTimeout; +DaemonAppEngine::SignalMap DaemonAppEngine::signalMap; DECLARE_OPTIONS(DaemonAppEngine, "Project2 Daemon options") ("help", new OptionFlagSet(&ShowHelpComponent::showHelp), "Print usage and exit")("h") ("daemon.type", Options::value(&daemonType), "The core daemon module to run") ("daemon.platform", Options::value(&reqPlatform), "Platform") +("daemon.periodicTimeout", Options::value(&periodicTimeout, 60), + "Delay between occurrences of component periodic calls (default 60s)") END_OPTIONS(DaemonAppEngine); -DaemonAppEngine::DaemonAppEngine(int argc, char ** argv) +DaemonAppEngine::DaemonAppEngine(int argc, char ** argv) : + main_loop(Glib::MainLoop::create()) { daemon = DaemonLoader::createNew(daemonType, argc, argv); + Glib::signal_timeout().connect_seconds(sigc::mem_fun(this, &DaemonAppEngine::periodicCallback), periodicTimeout); } DaemonAppEngine::~DaemonAppEngine() @@ -27,7 +32,7 @@ DaemonAppEngine::~DaemonAppEngine() } void -DaemonAppEngine::shutdown(int) +DaemonAppEngine::shutdown() { DefaultSignalHandler(SIGINT); DefaultSignalHandler(SIGUSR1); @@ -35,28 +40,56 @@ DaemonAppEngine::shutdown(int) DefaultSignalHandler(SIGQUIT); DefaultSignalHandler(SIGTERM); - Logger()->message(LOG_INFO, "Shutting down daemon."); + Logger()->messagebf(LOG_DEBUG, "%s: Shutting down events.", __PRETTY_FUNCTION__); + main_loop->quit(); + Logger()->messagebf(LOG_DEBUG, "%s: Waiting for events to terminate.", __PRETTY_FUNCTION__); + evThread->join(); + delete evThread; + Logger()->messagebf(LOG_INFO, "%s: Shutting down daemon.", __PRETTY_FUNCTION__); daemon->shutdown(); - Logger()->message(LOG_INFO, "Daemon shut down."); + Logger()->messagebf(LOG_INFO, "%s: Daemon shut down.", __PRETTY_FUNCTION__); } void -DaemonAppEngine::process() const +DaemonAppEngine::process() { IgnoreSignal(SIGINT); IgnoreSignal(SIGUSR1); IgnoreSignal(SIGUSR2); - AddSignalHandler(SIGQUIT, &shutdown); - AddSignalHandler(SIGTERM, &shutdown); + AddSignalHandler(SIGQUIT, boost::bind(&DaemonAppEngine::shutdown, this)); + AddSignalHandler(SIGTERM, boost::bind(&DaemonAppEngine::shutdown, this)); - Logger()->message(LOG_INFO, "Starting daemon."); + Logger()->messagebf(LOG_DEBUG, "%s: Starting events.", __PRETTY_FUNCTION__); + evThread = new std::thread(&Glib::MainLoop::run, main_loop.operator->()); + Logger()->messagebf(LOG_INFO, "%s: Starting daemon.", __PRETTY_FUNCTION__); daemon->run(); - Logger()->message(LOG_INFO, "Daemon exitted."); + Logger()->messagebf(LOG_INFO, "%s: Daemon exitted.", __PRETTY_FUNCTION__); +} + +void +DaemonAppEngine::signalHandler(int signum) +{ + SignalMap::const_iterator shi = signalMap.find(signum); + if (shi != signalMap.end()) { + shi->second(signum); + } + else { + Logger()->messagebf(LOG_WARNING, "%s: Failed to find signal handler for sig %d", __PRETTY_FUNCTION__, signum); + } +} + +bool +DaemonAppEngine::periodicCallback() +{ + Logger()->messagebf(LOG_DEBUG, "%s: firing component periodics.", __PRETTY_FUNCTION__); + Plugable::onAllComponents(boost::bind(&ComponentLoader::onPeriodic, _1)); + return true; } void DaemonAppEngine::IgnoreSignal(int signum) { + signalMap.erase(signum); if (signal(signum, SIG_IGN) == SIG_ERR) { Logger()->messagef(LOG_WARNING, "%s: Failed to ignore signal %d", __PRETTY_FUNCTION__, signum); } @@ -65,16 +98,41 @@ DaemonAppEngine::IgnoreSignal(int signum) void DaemonAppEngine::DefaultSignalHandler(int signum) { + signalMap.erase(signum); if (signal(signum, SIG_DFL) == SIG_ERR) { Logger()->messagef(LOG_WARNING, "%s: Failed to restore default signal %d handler", __PRETTY_FUNCTION__, signum); } } void -DaemonAppEngine::AddSignalHandler(int signum, sighandler_t handler) +DaemonAppEngine::AddSignalHandler(int signum, const SignalFunc & handler) { - if (signal(signum, handler) == SIG_ERR) { + if (signal(signum, signalHandler) == SIG_ERR) { Logger()->messagef(LOG_WARNING, "%s: Failed to add signal %d handler", __PRETTY_FUNCTION__, signum); } + signalMap.insert({signum, handler}); } +#ifndef NDEBUG +class DummyDaemon : public Daemon { + public: + DummyDaemon(int, char * []) : stop(false) { } + void run() const + { + Logger()->messagef(LOG_INFO, "%s: Running", __PRETTY_FUNCTION__); + while (!stop) { + sleep(1); + } + Logger()->messagef(LOG_INFO, "%s: Exiting", __PRETTY_FUNCTION__); + } + void shutdown() const + { + Logger()->messagef(LOG_INFO, "%s: Setting stop flag", __PRETTY_FUNCTION__); + stop = true; + } + private: + mutable bool stop; +}; +DECLARE_GENERIC_LOADER("dummydaemon", DaemonLoader, DummyDaemon); +#endif + diff --git a/project2/daemon/p2daemonAppEngine.h b/project2/daemon/p2daemonAppEngine.h index 42eddc7..0b16f70 100644 --- a/project2/daemon/p2daemonAppEngine.h +++ b/project2/daemon/p2daemonAppEngine.h @@ -4,27 +4,39 @@ #include #include #include "lib/daemon.h" +#include +#include class DaemonAppEngine { public: DaemonAppEngine(int, char **); ~DaemonAppEngine(); - void process() const; + void process(); INITOPTIONS; static Glib::ustring reqPlatform; static std::string daemonType; + static int periodicTimeout; protected: + typedef boost::function SignalFunc; + typedef std::map SignalMap; + static void IgnoreSignal(int signum); static void DefaultSignalHandler(int signum); - static void AddSignalHandler(int signum, sighandler_t handler); + static void AddSignalHandler(int signum, const SignalFunc & handler); + + static SignalMap signalMap; + static void signalHandler(int); private: - static void shutdown(int); - static DaemonPtr daemon; + Glib::RefPtr main_loop; + std::thread * evThread; + bool periodicCallback(); + void shutdown(); + DaemonPtr daemon; }; #endif diff --git a/project2/daemon/p2daemonMain.cpp b/project2/daemon/p2daemonMain.cpp index 6dfb3ac..20c4eb7 100644 --- a/project2/daemon/p2daemonMain.cpp +++ b/project2/daemon/p2daemonMain.cpp @@ -20,7 +20,6 @@ main(int argc, char ** argv) dae.process(); //Plugable::onAllComponents(boost::bind(&ComponentLoader::onIteration, _1)); - //Plugable::onAllComponents(boost::bind(&ComponentLoader::onPeriodic, _1)); Plugable::onAllComponents(boost::bind(&ComponentLoader::onIdle, _1)); } -- cgit v1.2.3