From: Gunnar Beutner Date: Tue, 17 Jul 2012 18:41:06 +0000 (+0200) Subject: Cleaned up socket exception handling. X-Git-Tag: v0.0.1~211 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0ad6026f2926683978117949bc8507a65376f423;p=icinga2 Cleaned up socket exception handling. --- diff --git a/base/application.cpp b/base/application.cpp index fe17a1dda..e521460ad 100644 --- a/base/application.cpp +++ b/base/application.cpp @@ -39,7 +39,7 @@ Application::Application(void) #ifdef _WIN32 WSADATA wsaData; if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) - throw Win32Exception("WSAStartup failed", WSAGetLastError()); + throw_exception(Win32Exception("WSAStartup failed", WSAGetLastError())); #else /* _WIN32 */ lt_dlinit(); #endif /* _WIN32 */ @@ -133,12 +133,12 @@ Component::Ptr Application::LoadComponent(const string& path, HMODULE hModule = LoadLibrary(path.c_str()); if (hModule == NULL) - throw Win32Exception("LoadLibrary('" + path + "') failed", GetLastError()); + throw_exception(Win32Exception("LoadLibrary('" + path + "') failed", GetLastError())); #else /* _WIN32 */ lt_dlhandle hModule = lt_dlopen(path.c_str()); if (hModule == NULL) { - throw runtime_error("Could not load module '" + path + "': " + lt_dlerror()); + throw_exception(runtime_error("Could not load module '" + path + "': " + lt_dlerror())); } #endif /* _WIN32 */ @@ -155,8 +155,8 @@ Component::Ptr Application::LoadComponent(const string& path, #endif /* _WIN32 */ if (pCreateComponent == NULL) - throw runtime_error("Loadable module does not contain " - "CreateComponent function"); + throw_exception(runtime_error("Loadable module does not contain " + "CreateComponent function")); component = Component::Ptr(pCreateComponent()); component->SetConfig(componentConfig); @@ -228,7 +228,7 @@ string Application::GetExePath(void) const char buffer[MAXPATHLEN]; if (getcwd(buffer, sizeof(buffer)) == NULL) - throw PosixException("getcwd failed", errno); + throw_exception(PosixException("getcwd failed", errno)); string workingDirectory = buffer; if (argv0[0] != '/') @@ -255,20 +255,20 @@ string Application::GetExePath(void) const if (!foundPath) { executablePath.clear(); - throw runtime_error("Could not determine executable path."); + throw_exception(runtime_error("Could not determine executable path.")); } } } if (realpath(executablePath.c_str(), buffer) == NULL) - throw PosixException("realpath failed", errno); + throw_exception(PosixException("realpath failed", errno)); result = buffer; #else /* _WIN32 */ char FullExePath[MAXPATHLEN]; if (!GetModuleFileName(NULL, FullExePath, sizeof(FullExePath))) - throw Win32Exception("GetModuleFileName() failed", GetLastError()); + throw_exception(Win32Exception("GetModuleFileName() failed", GetLastError())); result = FullExePath; #endif /* _WIN32 */ @@ -410,15 +410,15 @@ void Application::UpdatePidFile(const string& filename) m_PidFile = fopen(filename.c_str(), "w"); if (m_PidFile == NULL) - throw runtime_error("Could not open PID file '" + filename + "'"); + throw_exception(runtime_error("Could not open PID file '" + filename + "'")); #ifndef _WIN32 if (flock(fileno(m_PidFile), LOCK_EX | LOCK_NB) < 0) { ClosePidFile(); - throw runtime_error("Another instance of the application is " + throw_exception(runtime_error("Another instance of the application is " "already running. Remove the '" + filename + "' file if " - "you're certain that this is not the case."); + "you're certain that this is not the case.")); } #endif /* _WIN32 */ diff --git a/base/asynctask.h b/base/asynctask.h index 47b57dabf..aae361571 100644 --- a/base/asynctask.h +++ b/base/asynctask.h @@ -83,13 +83,13 @@ public: TResult GetResult(void) { if (!m_Finished) - throw runtime_error("GetResult called on an unfinished AsyncTask"); + throw_exception(runtime_error("GetResult called on an unfinished AsyncTask")); if (m_ResultRetrieved) - throw runtime_error("GetResult called on an AsyncTask whose result was already retrieved."); + throw_exception(runtime_error("GetResult called on an AsyncTask whose result was already retrieved.")); if (m_Exception) - boost::rethrow_exception(m_Exception); + rethrow_exception(m_Exception); m_ResultRetrieved = true; diff --git a/base/configobject.cpp b/base/configobject.cpp index ef8e3ef9e..5647db120 100644 --- a/base/configobject.cpp +++ b/base/configobject.cpp @@ -208,7 +208,7 @@ ScriptTask::Ptr ConfigObject::InvokeMethod(const string& method, ScriptFunction::Ptr func = ScriptFunction::GetByName(funcName); if (!func) - throw invalid_argument("Function '" + funcName + "' does not exist."); + throw_exception(invalid_argument("Function '" + funcName + "' does not exist.")); ScriptTask::Ptr task = boost::make_shared(func, arguments); task->Start(callback); diff --git a/base/fifo.cpp b/base/fifo.cpp index e71c2f4e1..5ea4dff9e 100644 --- a/base/fifo.cpp +++ b/base/fifo.cpp @@ -57,7 +57,7 @@ void FIFO::ResizeBuffer(size_t newSize) char *newBuffer = (char *)realloc(m_Buffer, newSize); if (newBuffer == NULL) - throw bad_alloc(); + throw_exception(bad_alloc()); m_Buffer = newBuffer; diff --git a/base/i2-base.h b/base/i2-base.h index 94db9f57a..99e3991ca 100644 --- a/base/i2-base.h +++ b/base/i2-base.h @@ -104,6 +104,7 @@ using std::ostream; using std::ofstream; using std::exception; +using std::bad_alloc; using std::bad_cast; using std::runtime_error; using std::logic_error; @@ -137,6 +138,9 @@ using boost::mutex; using boost::condition_variable; using boost::system_time; using boost::tie; +using boost::throw_exception; +using boost::rethrow_exception; +using boost::current_exception; namespace tuples = boost::tuples; diff --git a/base/logger.cpp b/base/logger.cpp index 7b177af5a..4e7f6b830 100644 --- a/base/logger.cpp +++ b/base/logger.cpp @@ -111,7 +111,7 @@ string Logger::SeverityToString(LogSeverity severity) case LogCritical: return "critical"; default: - throw invalid_argument("Invalid severity."); + throw_exception(invalid_argument("Invalid severity.")); } } @@ -126,5 +126,5 @@ LogSeverity Logger::StringToSeverity(const string& severity) else if (severity == "critical") return LogCritical; else - throw invalid_argument("Invalid severity: " + severity); + throw_exception(invalid_argument("Invalid severity: " + severity)); } diff --git a/base/process.cpp b/base/process.cpp index 38990a89f..d48b21bbb 100644 --- a/base/process.cpp +++ b/base/process.cpp @@ -150,7 +150,7 @@ void Process::InitTask(void) #endif /* _MSC_VER */ if (m_FP == NULL) - throw runtime_error("Could not create process."); + throw_exception(runtime_error("Could not create process.")); } bool Process::RunTask(void) diff --git a/base/socket.cpp b/base/socket.cpp index 7ca0f949b..7fa8d3d9e 100644 --- a/base/socket.cpp +++ b/base/socket.cpp @@ -62,10 +62,10 @@ void Socket::SetFD(SOCKET fd) int flags; flags = fcntl(fd, F_GETFL, 0); if (flags < 0) - throw PosixException("fcntl failed", errno); + throw_exception(PosixException("fcntl failed", errno)); if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) - throw PosixException("fcntl failed", errno); + throw_exception(PosixException("fcntl failed", errno)); #else /* F_GETFL */ unsigned long lTrue = 1; ioctlsocket(fd, FIONBIO, &lTrue); @@ -105,6 +105,8 @@ void Socket::CloseInternal(bool from_dtor) if (m_FD == INVALID_SOCKET) return; + SetConnected(false); + closesocket(m_FD); m_FD = INVALID_SOCKET; @@ -146,30 +148,12 @@ int Socket::GetLastSocketError(void) #endif /* _WIN32 */ } -/** - * Handles a socket error by calling the OnError event or throwing an exception - * when there are no observers for the OnError event. - * - * @param ex An exception. - */ -void Socket::HandleSocketError(const exception& ex) -{ - if (!OnError.empty()) { - Event::Post(boost::bind(boost::ref(OnError), GetSelf(), runtime_error(ex.what()))); - - CloseInternal(false); - } else { - throw ex; - } -} - /** * Processes errors that have occured for the socket. */ void Socket::HandleException(void) { - HandleSocketError(SocketException( - "select() returned fd in except fdset", GetError())); + throw_exception(SocketException("select() returned fd in except fdset", GetError())); } /** @@ -208,9 +192,10 @@ string Socket::GetAddressFromSockaddr(sockaddr *address, socklen_t len) char host[NI_MAXHOST]; char service[NI_MAXSERV]; - if (getnameinfo(address, len, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV) < 0) - throw SocketException("getnameinfo() failed", - GetLastSocketError()); + if (getnameinfo(address, len, host, sizeof(host), service, + sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV) < 0) + throw_exception(SocketException("getnameinfo() failed", + GetLastSocketError())); stringstream s; s << "[" << host << "]:" << service; @@ -229,12 +214,8 @@ string Socket::GetClientAddress(void) sockaddr_storage sin; socklen_t len = sizeof(sin); - if (getsockname(GetFD(), (sockaddr *)&sin, &len) < 0) { - HandleSocketError(SocketException( - "getsockname() failed", GetError())); - - return string(); - } + if (getsockname(GetFD(), (sockaddr *)&sin, &len) < 0) + throw_exception(SocketException("getsockname() failed", GetError())); return GetAddressFromSockaddr((sockaddr *)&sin, len); } @@ -251,12 +232,8 @@ string Socket::GetPeerAddress(void) sockaddr_storage sin; socklen_t len = sizeof(sin); - if (getpeername(GetFD(), (sockaddr *)&sin, &len) < 0) { - HandleSocketError(SocketException( - "getpeername() failed", GetError())); - - return string(); - } + if (getpeername(GetFD(), (sockaddr *)&sin, &len) < 0) + throw_exception(SocketException("getpeername() failed", GetError())); return GetAddressFromSockaddr((sockaddr *)&sin, len); } @@ -311,16 +288,22 @@ void Socket::ReadThreadProc(void) if (GetFD() == INVALID_SOCKET) return; - if (rc < 0) { - HandleSocketError(SocketException("select() failed", GetError())); - return; - } + try { + if (rc < 0) + throw_exception(SocketException("select() failed", GetError())); - if (FD_ISSET(fd, &readfds)) - HandleReadable(); + if (FD_ISSET(fd, &readfds)) + HandleReadable(); - if (FD_ISSET(fd, &exceptfds)) - HandleException(); + if (FD_ISSET(fd, &exceptfds)) + HandleException(); + } catch (const exception&) { + m_Exception = boost::current_exception(); + + CloseInternal(false); + + break; + } if (WantsToWrite()) m_WriteCV.notify_all(); /* notify Write thread */ @@ -359,13 +342,19 @@ void Socket::WriteThreadProc(void) if (GetFD() == INVALID_SOCKET) return; - if (rc < 0) { - HandleSocketError(SocketException("select() failed", GetError())); - return; - } + try { + if (rc < 0) + throw_exception(SocketException("select() failed", GetError())); - if (FD_ISSET(fd, &writefds)) - HandleWritable(); + if (FD_ISSET(fd, &writefds)) + HandleWritable(); + } catch (const exception&) { + m_Exception = boost::current_exception(); + + CloseInternal(false); + + break; + } } } @@ -383,3 +372,9 @@ bool Socket::IsConnected(void) const { return m_Connected; } + +void Socket::CheckException(void) +{ + if (m_Exception) + rethrow_exception(m_Exception); +} diff --git a/base/socket.h b/base/socket.h index 5eeb0fe5b..f2e6adf01 100644 --- a/base/socket.h +++ b/base/socket.h @@ -35,7 +35,6 @@ public: ~Socket(void); - boost::signal OnError; boost::signal OnClosed; virtual void Start(void); @@ -47,6 +46,10 @@ public: mutex& GetMutex(void) const; + bool IsConnected(void) const; + + void CheckException(void); + protected: Socket(void); @@ -54,11 +57,9 @@ protected: SOCKET GetFD(void) const; void SetConnected(bool connected); - bool IsConnected(void) const; int GetError(void) const; static int GetLastSocketError(void); - void HandleSocketError(const exception& ex); virtual bool WantsToRead(void) const; virtual bool WantsToWrite(void) const; @@ -69,8 +70,6 @@ protected: virtual void CloseInternal(bool from_dtor); - mutable mutex m_Mutex; - private: SOCKET m_FD; /**< The socket descriptor. */ bool m_Connected; @@ -80,6 +79,9 @@ private: condition_variable m_WriteCV; + mutable mutex m_Mutex; + boost::exception_ptr m_Exception; + void ReadThreadProc(void); void WriteThreadProc(void); diff --git a/base/streamlogger.cpp b/base/streamlogger.cpp index 7126cc5cd..957f10c04 100644 --- a/base/streamlogger.cpp +++ b/base/streamlogger.cpp @@ -38,7 +38,7 @@ void StreamLogger::OpenFile(const string& filename) stream->open(filename.c_str(), ofstream::out | ofstream::trunc); if (!stream->good()) - throw runtime_error("Could not open logfile '" + filename + "'"); + throw_exception(runtime_error("Could not open logfile '" + filename + "'")); } catch (const exception&) { delete stream; throw; diff --git a/base/tcpclient.cpp b/base/tcpclient.cpp index c797f3bcd..0ee71e2a0 100644 --- a/base/tcpclient.cpp +++ b/base/tcpclient.cpp @@ -61,11 +61,8 @@ void TcpClient::Connect(const string& node, const string& service) int rc = getaddrinfo(node.c_str(), service.c_str(), &hints, &result); - if (rc < 0) { - HandleSocketError(SocketException( - "getaddrinfo() failed", GetLastSocketError())); - return; - } + if (rc < 0) + throw_exception(SocketException("getaddrinfo() failed", GetLastSocketError())); int fd = INVALID_SOCKET; @@ -96,8 +93,7 @@ void TcpClient::Connect(const string& node, const string& service) freeaddrinfo(result); if (fd == INVALID_SOCKET) - HandleSocketError(runtime_error( - "Could not create a suitable socket.")); + throw_exception(runtime_error("Could not create a suitable socket.")); } void TcpClient::HandleWritable(void) @@ -122,8 +118,7 @@ void TcpClient::HandleWritable(void) if (rc <= 0) { SetConnected(false); - HandleSocketError(SocketException("send() failed", GetError())); - return; + throw_exception(SocketException("send() failed", GetError())); } SetConnected(true); @@ -188,8 +183,7 @@ void TcpClient::HandleReadable(void) if (rc <= 0) { SetConnected(false); - HandleSocketError(SocketException("recv() failed", GetError())); - return; + throw_exception(SocketException("recv() failed", GetError())); } SetConnected(true); diff --git a/base/tcpserver.cpp b/base/tcpserver.cpp index 2da1a73f0..866530084 100644 --- a/base/tcpserver.cpp +++ b/base/tcpserver.cpp @@ -54,11 +54,8 @@ function TcpServer::GetFactoryFunction(void) const */ void TcpServer::Listen(void) { - if (listen(GetFD(), SOMAXCONN) < 0) { - HandleSocketError(SocketException( - "listen() failed", GetError())); - return; - } + if (listen(GetFD(), SOMAXCONN) < 0) + throw_exception(SocketException("listen() failed", GetError())); } /** @@ -83,11 +80,8 @@ void TcpServer::HandleReadable(void) fd = accept(GetFD(), (sockaddr *)&addr, &addrlen); - if (fd < 0) { - HandleSocketError(SocketException( - "accept() failed", GetError())); - return; - } + if (fd < 0) + throw_exception(SocketException("accept() failed", GetError())); TcpClient::Ptr client = m_ClientFactory(fd); diff --git a/base/tcpsocket.cpp b/base/tcpsocket.cpp index 201328e7e..ecdddef2c 100644 --- a/base/tcpsocket.cpp +++ b/base/tcpsocket.cpp @@ -32,12 +32,8 @@ void TcpSocket::MakeSocket(int family) int fd = socket(family, SOCK_STREAM, 0); - if (fd == INVALID_SOCKET) { - HandleSocketError(SocketException( - "socket() failed", GetLastSocketError())); - - return; - } + if (fd == INVALID_SOCKET) + throw_exception(SocketException("socket() failed", GetLastSocketError())); SetFD(fd); } @@ -72,12 +68,8 @@ void TcpSocket::Bind(string node, string service, int family) hints.ai_flags = AI_PASSIVE; if (getaddrinfo(node.empty() ? NULL : node.c_str(), - service.c_str(), &hints, &result) < 0) { - HandleSocketError(SocketException( - "getaddrinfo() failed", GetLastSocketError())); - - return; - } + service.c_str(), &hints, &result) < 0) + throw_exception(SocketException("getaddrinfo() failed", GetLastSocketError())); int fd = INVALID_SOCKET; @@ -116,6 +108,5 @@ void TcpSocket::Bind(string node, string service, int family) freeaddrinfo(result); if (fd == INVALID_SOCKET) - HandleSocketError(runtime_error( - "Could not create a suitable socket.")); + throw_exception(runtime_error("Could not create a suitable socket.")); } diff --git a/base/timer.cpp b/base/timer.cpp index 8bf42cfad..a1ea75230 100644 --- a/base/timer.cpp +++ b/base/timer.cpp @@ -113,11 +113,8 @@ void Timer::Call(void) * * @param interval The new interval. */ -void Timer::SetInterval(long interval) +void Timer::SetInterval(unsigned long interval) { - if (interval <= 0) - throw invalid_argument("interval"); - m_Interval = interval; } @@ -126,7 +123,7 @@ void Timer::SetInterval(long interval) * * @returns The interval. */ -long Timer::GetInterval(void) const +unsigned long Timer::GetInterval(void) const { return m_Interval; } diff --git a/base/timer.h b/base/timer.h index f644863f5..37c029352 100644 --- a/base/timer.h +++ b/base/timer.h @@ -39,8 +39,8 @@ public: Timer(void); - void SetInterval(long interval); - long GetInterval(void) const; + void SetInterval(unsigned long interval); + unsigned long GetInterval(void) const; static long ProcessTimers(void); @@ -52,7 +52,7 @@ public: boost::signal OnTimerExpired; private: - long m_Interval; /**< The interval of the timer. */ + unsigned long m_Interval; /**< The interval of the timer. */ time_t m_Next; /**< When the next event should happen. */ static Timer::CollectionType m_Timers; diff --git a/base/tlsclient.cpp b/base/tlsclient.cpp index c948e8903..0b1132c70 100644 --- a/base/tlsclient.cpp +++ b/base/tlsclient.cpp @@ -42,10 +42,10 @@ void TlsClient::Start(void) m_SSL = shared_ptr(SSL_new(m_SSLContext.get()), SSL_free); if (!m_SSL) - throw OpenSSLException("SSL_new failed", ERR_get_error()); + throw_exception(OpenSSLException("SSL_new failed", ERR_get_error())); if (!GetClientCertificate()) - throw logic_error("No X509 client certificate was specified."); + throw_exception(logic_error("No X509 client certificate was specified.")); if (!m_SSLIndexInitialized) { m_SSLIndex = SSL_get_ex_new_index(0, (void *)"TlsClient", NULL, NULL, NULL); @@ -137,9 +137,7 @@ void TlsClient::HandleReadable(void) CloseInternal(false); goto post_event; default: - HandleSocketError(OpenSSLException( - "SSL_read failed", ERR_get_error())); - goto post_event; + throw_exception(OpenSSLException("SSL_read failed", ERR_get_error())); } } @@ -194,9 +192,7 @@ void TlsClient::HandleWritable(void) CloseInternal(false); return; default: - HandleSocketError(OpenSSLException( - "SSL_write failed", ERR_get_error())); - return; + throw_exception(OpenSSLException("SSL_write failed", ERR_get_error())); } } diff --git a/base/utility.cpp b/base/utility.cpp index 4c63066ee..6a558e97e 100644 --- a/base/utility.cpp +++ b/base/utility.cpp @@ -58,7 +58,7 @@ void Utility::Daemonize(void) { pid = fork(); if (pid < 0) - throw PosixException("fork() failed", errno); + throw_exception PosixException("fork() failed", errno); if (pid) exit(0); @@ -66,7 +66,7 @@ void Utility::Daemonize(void) { fd = open("/dev/null", O_RDWR); if (fd < 0) - throw PosixException("open() failed", errno); + throw_exception PosixException("open() failed", errno); if (fd != STDIN_FILENO) dup2(fd, STDIN_FILENO); @@ -81,7 +81,7 @@ void Utility::Daemonize(void) { close(fd); if (setsid() < 0) - throw PosixException("setsid() failed", errno); + throw_exception PosixException("setsid() failed", errno); #endif } @@ -116,19 +116,19 @@ shared_ptr Utility::MakeSSLContext(string pubkey, string privkey, strin SSL_CTX_set_mode(sslContext.get(), SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); if (!SSL_CTX_use_certificate_chain_file(sslContext.get(), pubkey.c_str())) - throw OpenSSLException("Could not load public X509 key file", ERR_get_error()); + throw_exception(OpenSSLException("Could not load public X509 key file", ERR_get_error())); if (!SSL_CTX_use_PrivateKey_file(sslContext.get(), privkey.c_str(), SSL_FILETYPE_PEM)) - throw OpenSSLException("Could not load private X509 key file", ERR_get_error()); + throw_exception(OpenSSLException("Could not load private X509 key file", ERR_get_error())); if (!SSL_CTX_load_verify_locations(sslContext.get(), cakey.c_str(), NULL)) - throw OpenSSLException("Could not load public CA key file", ERR_get_error()); + throw_exception(OpenSSLException("Could not load public CA key file", ERR_get_error())); STACK_OF(X509_NAME) *cert_names; cert_names = SSL_load_client_CA_file(cakey.c_str()); if (cert_names == NULL) - throw OpenSSLException("SSL_load_client_CA_file() failed", ERR_get_error()); + throw_exception(OpenSSLException("SSL_load_client_CA_file() failed", ERR_get_error())); SSL_CTX_set_client_CA_list(sslContext.get(), cert_names); @@ -148,7 +148,7 @@ string Utility::GetCertificateCN(const shared_ptr& certificate) int rc = X509_NAME_get_text_by_NID(X509_get_subject_name(certificate.get()), NID_commonName, buffer, sizeof(buffer)); if (rc == -1) - throw OpenSSLException("X509 certificate has no CN attribute", ERR_get_error()); + throw_exception(OpenSSLException("X509 certificate has no CN attribute", ERR_get_error())); return buffer; } @@ -165,14 +165,14 @@ shared_ptr Utility::GetX509Certificate(string pemfile) BIO *fpcert = BIO_new(BIO_s_file()); if (fpcert == NULL) - throw OpenSSLException("BIO_new failed", ERR_get_error()); + throw_exception(OpenSSLException("BIO_new failed", ERR_get_error())); if (BIO_read_filename(fpcert, pemfile.c_str()) < 0) - throw OpenSSLException("BIO_read_filename failed", ERR_get_error()); + throw_exception(OpenSSLException("BIO_read_filename failed", ERR_get_error())); cert = PEM_read_bio_X509_AUX(fpcert, NULL, NULL, NULL); if (cert == NULL) - throw OpenSSLException("PEM_read_bio_X509_AUX failed", ERR_get_error()); + throw_exception(OpenSSLException("PEM_read_bio_X509_AUX failed", ERR_get_error())); BIO_free(fpcert); @@ -203,14 +203,14 @@ string Utility::DirName(const string& path) string result; if (dir == NULL) - throw std::bad_alloc(); + throw_exception(bad_alloc()); #ifndef _WIN32 result = dirname(dir); #else /* _WIN32 */ if (!PathRemoveFileSpec(dir)) { free(dir); - throw Win32Exception("PathRemoveFileSpec() failed", GetLastError()); + throw_exception(Win32Exception("PathRemoveFileSpec() failed", GetLastError())); } result = dir; @@ -233,7 +233,7 @@ string Utility::BaseName(const string& path) string result; if (dir == NULL) - throw std::bad_alloc(); + throw_exception(bad_alloc()); #ifndef _WIN32 result = basename(dir); diff --git a/base/variant.h b/base/variant.h index 7fe047a22..4f1c996cd 100644 --- a/base/variant.h +++ b/base/variant.h @@ -65,7 +65,7 @@ public: Object::Ptr object = dynamic_pointer_cast(value); if (!object) - throw invalid_argument("shared_ptr value type must inherit from Object class."); + throw_exception(invalid_argument("shared_ptr value type must inherit from Object class.")); m_Value = object; } @@ -110,7 +110,7 @@ public: shared_ptr object = dynamic_pointer_cast(boost::get(m_Value)); if (!object) - throw bad_cast(); + throw_exception(bad_cast()); return object; } diff --git a/cib/host.cpp b/cib/host.cpp index 90cfdcb39..5832dba51 100644 --- a/cib/host.cpp +++ b/cib/host.cpp @@ -48,7 +48,7 @@ Host Host::GetByName(const string& name) ConfigObject::Ptr configObject = ConfigObject::GetObject("host", name); if (!configObject) - throw invalid_argument("Host '" + name + "' does not exist."); + throw_exception(invalid_argument("Host '" + name + "' does not exist.")); return Host(configObject); } diff --git a/cib/hostgroup.cpp b/cib/hostgroup.cpp index 840aefcf9..12adce953 100644 --- a/cib/hostgroup.cpp +++ b/cib/hostgroup.cpp @@ -61,7 +61,7 @@ HostGroup HostGroup::GetByName(const string& name) ConfigObject::Ptr configObject = ConfigObject::GetObject("hostgroup", name); if (!configObject) - throw invalid_argument("HostGroup '" + name + "' does not exist."); + throw_exception(invalid_argument("HostGroup '" + name + "' does not exist.")); return HostGroup(configObject); } diff --git a/cib/macroprocessor.cpp b/cib/macroprocessor.cpp index 4bd4aeb2f..b2ff0eac7 100644 --- a/cib/macroprocessor.cpp +++ b/cib/macroprocessor.cpp @@ -32,7 +32,7 @@ string MacroProcessor::ResolveMacros(const string& str, const vector& arguments) { if (arguments.size() < 1) - throw invalid_argument("Missing argument: Service must be specified."); + throw_exception(invalid_argument("Missing argument: Service must be specified.")); Variant vservice = arguments[0]; if (!vservice.IsObjectType()) - throw invalid_argument("Argument must be a config object."); + throw_exception(invalid_argument("Argument must be a config object.")); Service service = static_cast(vservice); diff --git a/cib/nullchecktask.cpp b/cib/nullchecktask.cpp index 479bbc95e..20553d340 100644 --- a/cib/nullchecktask.cpp +++ b/cib/nullchecktask.cpp @@ -24,7 +24,7 @@ using namespace icinga; void NullCheckTask::ScriptFunc(const ScriptTask::Ptr& task, const vector& arguments) { if (arguments.size() < 1) - throw invalid_argument("Missing argument: Service must be specified."); + throw_exception(invalid_argument("Missing argument: Service must be specified.")); time_t now; time(&now); diff --git a/cib/service.cpp b/cib/service.cpp index 3a16334a6..75ec64a35 100644 --- a/cib/service.cpp +++ b/cib/service.cpp @@ -47,7 +47,7 @@ Service Service::GetByName(const string& name) ConfigObject::Ptr configObject = ConfigObject::GetObject("service", name); if (!configObject) - throw invalid_argument("Service '" + name + "' does not exist."); + throw_exception(invalid_argument("Service '" + name + "' does not exist.")); return configObject; } @@ -56,7 +56,7 @@ Host Service::GetHost(void) const { string hostname; if (!GetProperty("host_name", &hostname)) - throw runtime_error("Service object is missing the 'host_name' property."); + throw_exception(runtime_error("Service object is missing the 'host_name' property.")); return Host::GetByName(hostname); } @@ -269,7 +269,7 @@ CheckResult Service::GetLastCheckResult(void) const { Dictionary::Ptr value; if (!GetTag("last_result", &value)) - throw invalid_argument("Service has no last check result."); + throw_exception(invalid_argument("Service has no last check result.")); return CheckResult(value); } diff --git a/cib/servicegroup.cpp b/cib/servicegroup.cpp index 8e4209dbd..57d80ace5 100644 --- a/cib/servicegroup.cpp +++ b/cib/servicegroup.cpp @@ -62,7 +62,7 @@ ServiceGroup ServiceGroup::GetByName(const string& name) ConfigObject::Ptr configObject = ConfigObject::GetObject("hostgroup", name); if (!configObject) - throw invalid_argument("ServiceGroup '" + name + "' does not exist."); + throw_exception(invalid_argument("ServiceGroup '" + name + "' does not exist.")); return ServiceGroup(configObject); } diff --git a/components/cibsync/cibsynccomponent.cpp b/components/cibsync/cibsynccomponent.cpp index 9ff939603..b4badb2c2 100644 --- a/components/cibsync/cibsynccomponent.cpp +++ b/components/cibsync/cibsynccomponent.cpp @@ -249,7 +249,7 @@ void CIBSyncComponent::RemoteObjectCommittedHandler(const Endpoint::Ptr& sender, } if (object->IsLocal()) - throw invalid_argument("Replicated remote object is marked as local."); + throw_exception(invalid_argument("Replicated remote object is marked as local.")); if (object->GetSource().empty()) object->SetSource(sender->GetIdentity()); diff --git a/components/configfile/configfilecomponent.cpp b/components/configfile/configfilecomponent.cpp index 6f9a2f718..8c935cf80 100644 --- a/components/configfile/configfilecomponent.cpp +++ b/components/configfile/configfilecomponent.cpp @@ -34,7 +34,7 @@ void ConfigFileComponent::Start(void) string filename; if (!GetConfig()->GetProperty("configFilename", &filename)) - throw logic_error("Missing 'configFilename' property"); + throw_exception(logic_error("Missing 'configFilename' property")); vector configItems = ConfigCompiler::CompileFile(filename); diff --git a/components/convenience/conveniencecomponent.cpp b/components/convenience/conveniencecomponent.cpp index afcfcea92..129d61f4c 100644 --- a/components/convenience/conveniencecomponent.cpp +++ b/components/convenience/conveniencecomponent.cpp @@ -139,7 +139,7 @@ void ConvenienceComponent::HostCommittedHandler(const ConfigItem::Ptr& item) CopyServiceAttributes(host, service, builder); } else { - throw invalid_argument("Service description must be either a string or a dictionary."); + throw_exception(invalid_argument("Service description must be either a string or a dictionary.")); } ConfigItem::Ptr serviceItem = builder->Compile(); diff --git a/dyn/config_lexer.cc b/dyn/config_lexer.cc index 66a306750..6c3894c97 100644 --- a/dyn/config_lexer.cc +++ b/dyn/config_lexer.cc @@ -1801,7 +1801,7 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yysc if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); - /* It's okay to grow etc. this buffer, and we should throw it + /* It's okay to grow etc. this buffer, and we should throw_exception it * away when we're done. */ b->yy_is_our_buffer = 1; diff --git a/dyn/config_parser.cc b/dyn/config_parser.cc index 6f6855750..8748a0a8c 100644 --- a/dyn/config_parser.cc +++ b/dyn/config_parser.cc @@ -212,7 +212,7 @@ void yyerror(YYLTYPE *locp, ConfigCompiler *context, const char *err) { stringstream message; message << *locp << ": " << err; - throw runtime_error(message.str()); + throw_exception(runtime_error(message.str())); } int yyparse(ConfigCompiler *context); diff --git a/dyn/config_parser.yy b/dyn/config_parser.yy index 9255237a5..ec1d78964 100644 --- a/dyn/config_parser.yy +++ b/dyn/config_parser.yy @@ -70,7 +70,7 @@ void yyerror(YYLTYPE *locp, ConfigCompiler *context, const char *err) { stringstream message; message << *locp << ": " << err; - throw runtime_error(message.str()); + throw_exception(runtime_error(message.str())); } int yyparse(ConfigCompiler *context); diff --git a/dyn/configcompiler.cpp b/dyn/configcompiler.cpp index ec1013676..85aa98a2a 100644 --- a/dyn/configcompiler.cpp +++ b/dyn/configcompiler.cpp @@ -72,11 +72,10 @@ vector ConfigCompiler::CompileStream(const string& path, istrea vector ConfigCompiler::CompileFile(const string& path) { ifstream stream; - stream.exceptions(ifstream::badbit); stream.open(path.c_str(), ifstream::in); if (!stream.good()) - throw invalid_argument("Could not open config file: " + path); + throw_exception(invalid_argument("Could not open config file: " + path)); Logger::Write(LogInformation, "dyn", "Compiling config file: " + path); diff --git a/dyn/configitem.cpp b/dyn/configitem.cpp index 3d7295e4d..61f9aefb4 100644 --- a/dyn/configitem.cpp +++ b/dyn/configitem.cpp @@ -62,7 +62,7 @@ void ConfigItem::CalculateProperties(Dictionary::Ptr dictionary) const if (!parent) { stringstream message; message << "Parent object '" << name << "' does not exist (" << m_DebugInfo << ")"; - throw domain_error(message.str()); + throw_exception(domain_error(message.str())); } parent->CalculateProperties(dictionary); diff --git a/dyn/expression.cpp b/dyn/expression.cpp index 3f720133d..b9f2b5c43 100644 --- a/dyn/expression.cpp +++ b/dyn/expression.cpp @@ -45,7 +45,7 @@ void Expression::Execute(const Dictionary::Ptr& dictionary) const switch (m_Operator) { case OperatorExecute: if (!valueExprl) - throw invalid_argument("Operand for OperatorExecute must be an ExpressionList."); + throw_exception(invalid_argument("Operand for OperatorExecute must be an ExpressionList.")); valueExprl->Execute(dictionary); @@ -70,7 +70,7 @@ void Expression::Execute(const Dictionary::Ptr& dictionary) const if (!oldValue.IsEmpty()) { stringstream message; message << "Wrong argument types for += (non-dictionary and dictionary) (" << m_DebugInfo << ")"; - throw domain_error(message.str()); + throw_exception(domain_error(message.str())); } dict = boost::make_shared(); @@ -89,13 +89,13 @@ void Expression::Execute(const Dictionary::Ptr& dictionary) const } else { stringstream message; message << "+= only works for dictionaries (" << m_DebugInfo << ")"; - throw domain_error(message.str()); + throw_exception(domain_error(message.str())); } break; default: - throw runtime_error("Not yet implemented."); + throw_exception(runtime_error("Not yet implemented.")); } dictionary->Set(m_Key, newValue); diff --git a/icinga/endpointmanager.cpp b/icinga/endpointmanager.cpp index 272819e35..9159d2f01 100644 --- a/icinga/endpointmanager.cpp +++ b/icinga/endpointmanager.cpp @@ -82,7 +82,7 @@ shared_ptr EndpointManager::GetSSLContext(void) const void EndpointManager::AddListener(string service) { if (!GetSSLContext()) - throw logic_error("SSL context is required for AddListener()"); + throw_exception(logic_error("SSL context is required for AddListener()")); stringstream s; s << "Adding new listener: port " << service; @@ -237,7 +237,7 @@ void EndpointManager::SendAnycastMessage(Endpoint::Ptr sender, { string method; if (!message.GetMethod(&method)) - throw invalid_argument("Message is missing the 'method' property."); + throw_exception(invalid_argument("Message is missing the 'method' property.")); vector candidates; Endpoint::Ptr endpoint; @@ -269,11 +269,11 @@ void EndpointManager::SendMulticastMessage(Endpoint::Ptr sender, { string id; if (message.GetID(&id)) - throw invalid_argument("Multicast requests must not have an ID."); + throw_exception(invalid_argument("Multicast requests must not have an ID.")); string method; if (!message.GetMethod(&method)) - throw invalid_argument("Message is missing the 'method' property."); + throw_exception(invalid_argument("Message is missing the 'method' property.")); Endpoint::Ptr recipient; BOOST_FOREACH(tie(tuples::ignore, recipient), m_Endpoints) { @@ -366,7 +366,7 @@ void EndpointManager::ProcessResponseMessage(const Endpoint::Ptr& sender, const { string id; if (!message.GetID(&id)) - throw invalid_argument("Response message must have a message ID."); + throw_exception(invalid_argument("Response message must have a message ID.")); map::iterator it; it = m_Requests.find(id); diff --git a/icinga/icingaapplication.cpp b/icinga/icingaapplication.cpp index 3ca027a84..7ba9ca121 100644 --- a/icinga/icingaapplication.cpp +++ b/icinga/icingaapplication.cpp @@ -97,7 +97,7 @@ int IcingaApplication::Main(const vector& args) continue; } else if (arg == "-L") { if (it + 1 == args.end()) - throw invalid_argument("Option -L requires a parameter"); + throw_exception(invalid_argument("Option -L requires a parameter")); StreamLogger::Ptr fileLogger = boost::make_shared(LogInformation); fileLogger->OpenFile(*(it + 1)); @@ -110,25 +110,25 @@ int IcingaApplication::Main(const vector& args) daemonize = true; continue; } else { - throw invalid_argument("Unknown option: " + arg); + throw_exception(invalid_argument("Unknown option: " + arg)); } } configFile = arg; if (it + 1 != args.end()) - throw invalid_argument("Trailing command line arguments after config filename."); + throw_exception(invalid_argument("Trailing command line arguments after config filename.")); } if (configFile.empty()) - throw invalid_argument("No config file was specified on the command line."); + throw_exception(invalid_argument("No config file was specified on the command line.")); if (enableSyslog) { #ifndef _WIN32 SyslogLogger::Ptr syslogLogger = boost::make_shared(LogInformation); Logger::RegisterLogger(syslogLogger); #else /* _WIN32 */ - throw invalid_argument("Syslog is not supported on Windows."); + throw_exception(invalid_argument("Syslog is not supported on Windows.")); #endif /* _WIN32 */ } @@ -160,10 +160,10 @@ int IcingaApplication::Main(const vector& args) ConfigObject::Ptr icingaConfig = ConfigObject::GetObject("application", "icinga"); if (!icingaConfig) - throw runtime_error("Configuration must contain an 'application' object named 'icinga'."); + throw_exception(runtime_error("Configuration must contain an 'application' object named 'icinga'.")); if (!icingaConfig->IsLocal()) - throw runtime_error("'icinga' application object must be 'local'."); + throw_exception(runtime_error("'icinga' application object must be 'local'.")); icingaConfig->GetProperty("cert", &m_CertificateFile); icingaConfig->GetProperty("ca", &m_CAFile); @@ -217,7 +217,7 @@ void IcingaApplication::NewComponentHandler(const ConfigObject::Ptr& object) { /* don't allow replicated config objects */ if (!object->IsLocal()) - throw runtime_error("'component' objects must be 'local'"); + throw_exception(runtime_error("'component' objects must be 'local'")); string path; if (!object->GetProperty("path", &path)) { @@ -235,7 +235,7 @@ void IcingaApplication::NewLogHandler(const ConfigObject::Ptr& object) { /* don't allow replicated config objects */ if (!object->IsLocal()) - throw runtime_error("'log' objects must be 'local'"); + throw_exception(runtime_error("'log' objects must be 'local'")); Logger::Ptr logger; if (object->GetTag("logger", &logger)) @@ -243,7 +243,7 @@ void IcingaApplication::NewLogHandler(const ConfigObject::Ptr& object) string type; if (!object->GetProperty("type", &type)) - throw invalid_argument("'log' object must have a 'type' property"); + throw_exception(invalid_argument("'log' object must have a 'type' property")); string strSeverity; LogSeverity severity = LogInformation; @@ -254,12 +254,12 @@ void IcingaApplication::NewLogHandler(const ConfigObject::Ptr& object) #ifndef _WIN32 logger = boost::make_shared(severity); #else /* _WIN32 */ - throw invalid_argument("Syslog is not supported on Windows."); + throw_exception(invalid_argument("Syslog is not supported on Windows.")); #endif /* _WIN32 */ } else if (type == "file") { string path; if (!object->GetProperty("path", &path)) - throw invalid_argument("'log' object of type 'file' must have a 'path' property"); + throw_exception(invalid_argument("'log' object of type 'file' must have a 'path' property")); StreamLogger::Ptr slogger = boost::make_shared(severity); slogger->OpenFile(path); @@ -268,7 +268,7 @@ void IcingaApplication::NewLogHandler(const ConfigObject::Ptr& object) } else if (type == "console") { logger = boost::make_shared(&std::cout, severity); } else { - throw runtime_error("Unknown log type: " + type); + throw_exception(runtime_error("Unknown log type: " + type)); } object->SetTag("logger", logger); diff --git a/icinga/jsonrpcendpoint.cpp b/icinga/jsonrpcendpoint.cpp index a1acc3c7b..e5ad3c10b 100644 --- a/icinga/jsonrpcendpoint.cpp +++ b/icinga/jsonrpcendpoint.cpp @@ -52,7 +52,6 @@ void JsonRpcEndpoint::SetClient(JsonRpcClient::Ptr client) m_Client = client; client->OnNewMessage.connect(boost::bind(&JsonRpcEndpoint::NewMessageHandler, this, _2)); client->OnClosed.connect(boost::bind(&JsonRpcEndpoint::ClientClosedHandler, this)); - client->OnError.connect(boost::bind(&JsonRpcEndpoint::ClientErrorHandler, this, _2)); client->OnCertificateValidated.connect(boost::bind(&JsonRpcEndpoint::CertificateValidatedHandler, this)); } @@ -63,7 +62,7 @@ bool JsonRpcEndpoint::IsLocal(void) const bool JsonRpcEndpoint::IsConnected(void) const { - return (bool)m_Client; + return (m_Client && m_Client->IsConnected()); } void JsonRpcEndpoint::ProcessRequest(Endpoint::Ptr sender, const RequestMessage& message) @@ -109,6 +108,15 @@ void JsonRpcEndpoint::NewMessageHandler(const MessagePart& message) void JsonRpcEndpoint::ClientClosedHandler(void) { + try { + m_Client->CheckException(); + } catch (const exception& ex) { + stringstream message; + message << "Error occured for JSON-RPC socket: Message=" << ex.what(); + + Logger::Write(LogWarning, "jsonrpc", message.str()); + } + Logger::Write(LogWarning, "jsonrpc", "Lost connection to endpoint: identity=" + GetIdentity()); // TODO: _only_ clear non-persistent publications/subscriptions @@ -129,10 +137,6 @@ void JsonRpcEndpoint::ClientClosedHandler(void) void JsonRpcEndpoint::ClientErrorHandler(const exception& ex) { - stringstream message; - message << "Error occured for JSON-RPC socket: Message=" << ex.what(); - - Logger::Write(LogWarning, "jsonrpc", message.str()); } void JsonRpcEndpoint::CertificateValidatedHandler(void) diff --git a/icinga/virtualendpoint.cpp b/icinga/virtualendpoint.cpp index 28f2266b5..8dfe7bf49 100644 --- a/icinga/virtualendpoint.cpp +++ b/icinga/virtualendpoint.cpp @@ -68,7 +68,7 @@ void VirtualEndpoint::UnregisterTopicHandler(string topic, function 0) + throw_exception(bad_alloc()); + queue->Peek(buffer, buffer_length); /* no leading zeros allowed */ if (buffer[0] == '0' && isdigit(buffer[1])) { free(buffer); - throw invalid_argument("Invalid netstring (leading zero)"); + throw_exception(invalid_argument("Invalid netstring (leading zero)")); } size_t len, i; @@ -58,7 +62,7 @@ bool Netstring::ReadStringFromIOQueue(IOQueue *queue, string *str) /* length specifier must have at most 9 characters */ if (i >= 9) { free(buffer); - throw invalid_argument("Length specifier must not exceed 9 characters"); + throw_exception(invalid_argument("Length specifier must not exceed 9 characters")); } len = len * 10 + (buffer[i] - '0'); @@ -77,7 +81,7 @@ bool Netstring::ReadStringFromIOQueue(IOQueue *queue, string *str) if (new_buffer == NULL) { free(buffer); - throw std::bad_alloc(); + throw_exception(bad_alloc()); } buffer = new_buffer; @@ -87,13 +91,13 @@ bool Netstring::ReadStringFromIOQueue(IOQueue *queue, string *str) /* check for the colon delimiter */ if (buffer[i] != ':') { free(buffer); - throw invalid_argument("Invalid Netstring (missing :)"); + throw_exception(invalid_argument("Invalid Netstring (missing :)")); } /* check for the comma delimiter after the string */ if (buffer[i + 1 + len] != ',') { free(buffer); - throw invalid_argument("Invalid Netstring (missing ,)"); + throw_exception(invalid_argument("Invalid Netstring (missing ,)")); } *str = string(&buffer[i + 1], &buffer[i + 1 + len]);