Commit 4e8b623e authored by luz's avatar luz

p44utils: Application: now handles HUP, INT and TERM signals by terminating mainloop cleanly.

parent 9515cfd6
......@@ -23,6 +23,7 @@
#include "mainloop.hpp"
#include <sys/stat.h> // for umask
#include <sys/signal.h>
using namespace p44;
......@@ -44,10 +45,22 @@ Application::Application(MainLoop &aMainLoop) :
}
void Application::signal_handler(int aSignal)
{
if (sharedApplicationP) {
sharedApplicationP->signalOccurred(SIGHUP);
}
}
Application::Application() :
mainLoop(MainLoop::currentMainLoop())
{
sharedApplicationP = this;
// register signal handlers
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
}
Application::~Application()
......@@ -64,7 +77,21 @@ int Application::main(int argc, char **argv)
void Application::initialize()
{
// NOP
// NOP in base class
}
void Application::cleanup(int aExitCode)
{
// NOP in base class
}
void Application::signalOccurred(int aSignal)
{
// default action is terminating the program
LOG(LOG_ERR, "Terminating because signal %d occurred\n", aSignal);
mainLoop.terminate(EXIT_FAILURE);
}
......@@ -73,7 +100,11 @@ int Application::run()
// schedule the initialize() method as first mainloop method
mainLoop.executeOnce(boost::bind(&Application::initialize, this));
// run the mainloop
return mainLoop.run();
int exitCode = mainLoop.run();
// clean up
cleanup(exitCode);
// done
return exitCode;
}
......@@ -85,6 +116,19 @@ void Application::terminateApp(int aExitCode)
void Application::terminateApp(ErrorPtr aError)
{
if (Error::isOK(aError)) {
mainLoop.terminate(EXIT_SUCCESS);
}
else {
LOG(LOG_ERR, "Terminating because of error: %s\n", aError->description().c_str());
mainLoop.terminate(EXIT_FAILURE);
}
}
void Application::daemonize()
{
pid_t pid, sid;
......
......@@ -32,7 +32,10 @@ namespace p44 {
class Application : public P44Obj
{
typedef P44Obj inherited;
MainLoop &mainLoop;
public:
/// constructors
Application(MainLoop &aMainLoop);
......@@ -47,12 +50,17 @@ namespace p44 {
virtual int main(int argc, char **argv);
/// get shared instance (singleton)
Application *sharedApplication();
static Application *sharedApplication();
/// terminate app
/// @param aExitCode the exit code to return to the parent
void terminateApp(int aExitCode);
/// terminate app
/// @param aError if NULL or ErrorOK, app will terminate with EXIT_SUCCESS
/// otherwise, app will log aError's description at LOG_ERR level and then terminate with EXIT_FAILURE
void terminateApp(ErrorPtr aError);
protected:
/// daemonize
......@@ -63,6 +71,17 @@ namespace p44 {
/// scheduled to run when mainloop has started
virtual void initialize();
/// called when mainloop terminates
virtual void cleanup(int aExitCode);
/// called when a signal occurs
/// @note only SIGHUP,SIGINT,SIGKILL and SIGTERM are handled here
virtual void signalOccurred(int aSignal);
private:
static void signal_handler(int aSignal);
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment