+/**
+ * @file main/CLI/exithandler.cpp
+ * @brief Exit handlers for the eVaf main executable
+ * @author Enar Vaikene
+ *
+ * Copyright (c) 2011 Enar Vaikene
+ *
+ * This file is part of the eVaf C++ cross-platform application development framework.
+ *
+ * This file can be used under the terms of the GNU General Public License
+ * version 3.0 as published by the Free Software Foundation and appearing in
+ * the file LICENSE included in the packaging of this file. Please review the
+ * the following information to ensure the GNU General Public License version
+ * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
+ *
+ * Alternatively, this file may be used in accordance with the Commercial License
+ * Agreement provided with the Software.
+ */
+
+#include "exithandler.h"
+
+#include <Common/iLogger>
+#include <Common/iApp>
+
+#include <QtCore>
+
+#ifdef Q_OS_LINUX
+# include <signal.h>
+#endif
+
+#ifdef Q_OS_WIN32
+# include <windows.h>
+#endif
+
+namespace eVaf {
+namespace CLI {
+namespace Internal {
+
+#ifdef Q_OS_LINUX
+
+/**
+ * Signal handler on Linux
+ *
+ * Handles TERM and HUP signals and either quits or restarts the application.
+ *
+ * @TODO According to the signal(7) documentation, only "safe" functions can be called from the
+ * signal handler. We don't know how safe it is to call iApp::quit() and iApp::restart() and
+ * probably have to implement "safe" versions of these functions.
+ */
+static void signalHandler(int sig)
+{
+ eVaf::Common::iApp * app = eVaf::Common::iApp::instance();
+
+ switch (sig) {
+ case SIGTERM:
+ if (app)
+ app->quit();
+ else
+ exit(0);
+ break;
+ case SIGHUP:
+ if (app)
+ app->restart();
+ break;
+ }
+}
+
+#endif
+
+#ifdef Q_OS_WIN32
+
+/**
+ * Signal handler on Windows
+ *
+ * Either quits or restarts the application.
+ *
+ * @TODO Is there a similar concept of "safe" functions for Windows signal handlers?
+ */
+static BOOL WINAPI signalHandler(DWORD sig)
+{
+ eVaf::Common::iApp * app = eVaf::Common::iApp::instance();
+
+ switch (sig) {
+ case CTRL_C_EVENT:
+ case CTRL_CLOSE_EVENT:
+ case CTRL_LOGOFF_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
+ if (app)
+ app->quit();
+ else
+ exit(0);
+ return true;
+ break;
+ case CTRL_BREAK_EVENT:
+ if (app)
+ app->restart();
+ return true;
+ break;
+ }
+
+ return false;
+}
+
+#endif
+
+} // namespace eVaf::GUI::Internal
+} // namespace eVaf::GUI
+} // namespace eVaf
+
+
+bool eVaf::CLI::Internal::installExitHandler()
+{
+
+#ifdef Q_OS_LINUX
+ struct sigaction sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = signalHandler;
+ if (sigaction(SIGTERM, &sa, NULL) != 0) {
+ EVAF_FATAL_ERROR("sigaction() failed: %m");
+ return false;
+ }
+ if (sigaction(SIGHUP, &sa, NULL) != 0) {
+ EVAF_FATAL_ERROR("sigaction() failed: %m");
+ return false;
+ }
+#endif
+
+#ifdef Q_OS_WIN32
+ if (SetConsoleCtrlHandler(signalHandler, true) == 0) {
+ EVAF_FATAL_ERROR("SetConsoleCtrlHandler() failed");
+ return false;
+ }
+#endif
+
+ return true;
+}