diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp index 6efdc1573..3ca2ce933 100644 --- a/icinga-app/icinga.cpp +++ b/icinga-app/icinga.cpp @@ -653,7 +653,7 @@ int main(int argc, char **argv) }; StartServiceCtrlDispatcher(dispatchTable); - Application::Exit(1); + Application::Exit(EXIT_FAILURE); } #endif /* _WIN32 */ diff --git a/lib/base/application.cpp b/lib/base/application.cpp index 205f175a4..b979924ea 100644 --- a/lib/base/application.cpp +++ b/lib/base/application.cpp @@ -54,6 +54,7 @@ static bool l_InExceptionHandler = false; int Application::m_ArgC; char **Application::m_ArgV; double Application::m_StartTime; +int Application::m_ExitStatus = 0; /** * Constructor for the Application class. @@ -110,7 +111,6 @@ void Application::Exit(int rc) } UninitializeBase(); - #ifdef I2_DEBUG exit(rc); #else /* I2_DEBUG */ @@ -308,7 +308,11 @@ mainloop: goto mainloop; } - Log(LogInformation, "Application", "Shutting down Icinga..."); + if (m_ExitStatus) + Log(LogInformation, "Application", "Shutting down Icinga after a fatal error."); + else + Log(LogInformation, "Application", "Shutting down Icinga..."); + DynamicObject::StopObjects(); Application::GetInstance()->OnShutdown(); @@ -355,8 +359,9 @@ pid_t Application::StartReloadProcess(void) * Signals the application to shut down during the next * execution of the event loop. */ -void Application::RequestShutdown(void) +void Application::RequestShutdown(int rc) { + m_ExitStatus = rc > m_ExitStatus ? rc : m_ExitStatus; m_ShuttingDown = true; } diff --git a/lib/base/application.hpp b/lib/base/application.hpp index f00831b58..6ed9c648f 100644 --- a/lib/base/application.hpp +++ b/lib/base/application.hpp @@ -69,7 +69,7 @@ public: static void InstallExceptionHandlers(void); - static void RequestShutdown(void); + static void RequestShutdown(int rc = 0); static void RequestRestart(void); static void RequestReopenLogs(void); @@ -162,6 +162,7 @@ private: static bool m_Debugging; /**< Whether debugging is enabled. */ static LogSeverity m_DebuggingSeverity; /**< Whether debugging severity is set. */ static double m_StartTime; + static int m_ExitStatus; #ifndef _WIN32 static void SigIntTermHandler(int signum); diff --git a/lib/cli/daemoncommand.cpp b/lib/cli/daemoncommand.cpp index bfd860dee..4d564b94a 100644 --- a/lib/cli/daemoncommand.cpp +++ b/lib/cli/daemoncommand.cpp @@ -93,14 +93,14 @@ static bool Daemonize(void) if (ret == pid) { Log(LogCritical, "cli", "The daemon could not be started. See log output for details."); - Application::Exit(EXIT_FAILURE); + _exit(EXIT_FAILURE); } else if (ret == -1) { Log(LogCritical, "cli") << "waitpid() failed with error code " << errno << ", \"" << Utility::FormatErrorNumber(errno) << "\""; - Application::Exit(EXIT_FAILURE); + _exit(EXIT_FAILURE); } - Application::Exit(0); + _exit(EXIT_SUCCESS); } Application::GetTP().Start(); diff --git a/lib/db_ido_mysql/idomysqlconnection.cpp b/lib/db_ido_mysql/idomysqlconnection.cpp index 560f8f8a0..aa7a7bb8c 100644 --- a/lib/db_ido_mysql/idomysqlconnection.cpp +++ b/lib/db_ido_mysql/idomysqlconnection.cpp @@ -225,7 +225,7 @@ void IdoMysqlConnection::Reconnect(void) if (!row) { Log(LogCritical, "IdoMysqlConnection", "Schema does not provide any valid version! Verify your schema installation."); - Application::Exit(EXIT_FAILURE); + Application::RequestShutdown(EXIT_FAILURE); } DiscardRows(result); @@ -237,7 +237,7 @@ void IdoMysqlConnection::Reconnect(void) << "Schema version '" << version << "' does not match the required version '" << SCHEMA_VERSION << "'! Please check the upgrade documentation."; - Application::Exit(EXIT_FAILURE); + Application::RequestShutdown(EXIT_FAILURE); } String instanceName = GetInstanceName(); diff --git a/lib/db_ido_pgsql/idopgsqlconnection.cpp b/lib/db_ido_pgsql/idopgsqlconnection.cpp index e401b75cd..a8debf876 100644 --- a/lib/db_ido_pgsql/idopgsqlconnection.cpp +++ b/lib/db_ido_pgsql/idopgsqlconnection.cpp @@ -225,7 +225,7 @@ void IdoPgsqlConnection::Reconnect(void) if (!row) { Log(LogCritical, "IdoPgsqlConnection", "Schema does not provide any valid version! Verify your schema installation."); - Application::Exit(EXIT_FAILURE); + Application::RequestShutdown(EXIT_FAILURE); } String version = row->Get("version"); @@ -235,7 +235,7 @@ void IdoPgsqlConnection::Reconnect(void) << "Schema version '" << version << "' does not match the required version '" << SCHEMA_VERSION << "'! Please check the upgrade documentation."; - Application::Exit(EXIT_FAILURE); + Application::RequestShutdown(EXIT_FAILURE); } String instanceName = GetInstanceName(); diff --git a/lib/remote/apilistener.cpp b/lib/remote/apilistener.cpp index d4c728497..04874b831 100644 --- a/lib/remote/apilistener.cpp +++ b/lib/remote/apilistener.cpp @@ -49,17 +49,13 @@ void ApiListener::OnConfigLoaded(void) try { cert = GetX509Certificate(GetCertPath()); } catch (const std::exception&) { - Log(LogCritical, "ApiListener") - << "Cannot get certificate from cert path: '" << GetCertPath() << "'."; - Application::Exit(EXIT_FAILURE); + BOOST_THROW_EXCEPTION(ScriptError("Cannot get certificate from cert path: '" + GetCertPath() + "'.", GetDebugInfo())); } try { SetIdentity(GetCertificateCN(cert)); } catch (const std::exception&) { - Log(LogCritical, "ApiListener") - << "Cannot get certificate common name from cert path: '" << GetCertPath() << "'."; - Application::Exit(EXIT_FAILURE); + BOOST_THROW_EXCEPTION(ScriptError("Cannot get certificate common name from cert path: '" + GetCertPath() + "'.", GetDebugInfo())); } Log(LogInformation, "ApiListener") @@ -68,29 +64,22 @@ void ApiListener::OnConfigLoaded(void) try { m_SSLContext = MakeSSLContext(GetCertPath(), GetKeyPath(), GetCaPath()); } catch (const std::exception&) { - Log(LogCritical, "ApiListener") - << "Cannot make SSL context for cert path: '" << GetCertPath() << "' key path: '" << GetKeyPath() << "' ca path: '" << GetCaPath() << "'."; - Application::Exit(EXIT_FAILURE); + BOOST_THROW_EXCEPTION(ScriptError("Cannot make SSL context for cert path: '" + GetCertPath() + "' key path: '" + GetKeyPath() + "' ca path: '" + GetCaPath() + "'.", GetDebugInfo())); } if (!GetCrlPath().IsEmpty()) { try { AddCRLToSSLContext(m_SSLContext, GetCrlPath()); } catch (const std::exception&) { - Log(LogCritical, "ApiListener") - << "Cannot add certificate revocation list to SSL context for crl path: '" << GetCrlPath() << "'."; - Application::Exit(EXIT_FAILURE); + BOOST_THROW_EXCEPTION(ScriptError("Cannot add certificate revocation list to SSL context for crl path: '" + GetCrlPath() + "'.", GetDebugInfo())); } } } void ApiListener::OnAllConfigLoaded(void) { - if (!Endpoint::GetByName(GetIdentity())) { - Log(LogCritical, "ApiListener") - << "Endpoint object for '" << GetIdentity() << "' is missing."; - Application::Exit(EXIT_FAILURE); - } + if (!Endpoint::GetByName(GetIdentity())) + BOOST_THROW_EXCEPTION(ScriptError("Endpoint object for '" + GetIdentity() + "' is missing.", GetDebugInfo())); } /** @@ -117,7 +106,7 @@ void ApiListener::Start(void) if (!AddListener(GetBindHost(), GetBindPort())) { Log(LogCritical, "ApiListener") << "Cannot add listener on host '" << GetBindHost() << "' for port '" << GetBindPort() << "'."; - Application::Exit(EXIT_FAILURE); + Application::RequestShutdown(EXIT_FAILURE); } m_Timer = new Timer();