]> granicus.if.org Git - icinga2/commitdiff
Add more information to exceptions.
authorGunnar Beutner <gunnar.beutner@netways.de>
Mon, 11 Mar 2013 12:45:08 +0000 (13:45 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Mon, 11 Mar 2013 12:47:17 +0000 (13:47 +0100)
15 files changed:
components/compat/compatcomponent.cpp
components/livestatus/component.cpp
lib/base/application.cpp
lib/base/dynamicobject.cpp
lib/base/exception.cpp
lib/base/exception.h
lib/base/i2-base.h
lib/base/process-unix.cpp
lib/base/socket.cpp
lib/base/socket.h
lib/base/tcpsocket.cpp
lib/base/tlsstream.cpp
lib/base/unixsocket.cpp
lib/base/utility.cpp
lib/remoting/endpoint.cpp

index 1978f72b867be4927a75fc21eef5071c3adeb79e..c5e3f24f61407dbdd38312d9c5639772465c9568 100644 (file)
@@ -127,13 +127,21 @@ void CompatComponent::CommandPipeThread(const String& commandPath)
                if (S_ISFIFO(statbuf.st_mode) && access(commandPath.CStr(), R_OK) >= 0) {
                        fifo_ok = true;
                } else {
-                       if (unlink(commandPath.CStr()) < 0)
-                               BOOST_THROW_EXCEPTION(PosixException("unlink() failed", errno));
+                       if (unlink(commandPath.CStr()) < 0) {
+                               BOOST_THROW_EXCEPTION(posix_error()
+                                   << errinfo_api_function("unlink")
+                                   << errinfo_errno(errno)
+                                   << errinfo_file_name(commandPath));
+                       }
                }
        }
 
-       if (!fifo_ok && mkfifo(commandPath.CStr(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) < 0)
-               BOOST_THROW_EXCEPTION(PosixException("mkfifo() failed", errno));
+       if (!fifo_ok && mkfifo(commandPath.CStr(), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("mkfifo")
+                   << errinfo_errno(errno)
+                   << errinfo_file_name(commandPath));
+       }
 
        for (;;) {
                int fd;
@@ -142,14 +150,20 @@ void CompatComponent::CommandPipeThread(const String& commandPath)
                        fd = open(commandPath.CStr(), O_RDONLY);
                } while (fd < 0 && errno == EINTR);
 
-               if (fd < 0)
-                       BOOST_THROW_EXCEPTION(PosixException("open() failed", errno));
+               if (fd < 0) {
+                       BOOST_THROW_EXCEPTION(posix_error()
+                           << errinfo_api_function("open")
+                           << errinfo_errno(errno)
+                           << errinfo_file_name(commandPath));
+               }
 
                FILE *fp = fdopen(fd, "r");
 
                if (fp == NULL) {
-                       close(fd);
-                       BOOST_THROW_EXCEPTION(PosixException("fdopen() failed", errno));
+                       (void) close(fd);
+                       BOOST_THROW_EXCEPTION(posix_error()
+                           << errinfo_api_function("fdopen")
+                           << errinfo_errno(errno));
                }
 
                char line[2048];
@@ -640,10 +654,18 @@ void CompatComponent::StatusTimerHandler(void)
 #endif /* _WIN32 */
 
        statusfp.close();
-       if (rename(statuspathtmp.CStr(), statuspath.CStr()) < 0)
-               BOOST_THROW_EXCEPTION(PosixException("rename() failed", errno));
+       if (rename(statuspathtmp.CStr(), statuspath.CStr()) < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("rename")
+                   << errinfo_errno(errno)
+                   << errinfo_file_name(statuspathtmp));
+       }
 
        objectfp.close();
-       if (rename(objectspathtmp.CStr(), objectspath.CStr()) < 0)
-               BOOST_THROW_EXCEPTION(PosixException("rename() failed", errno));
+       if (rename(objectspathtmp.CStr(), objectspath.CStr()) < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("rename")
+                   << errinfo_errno(errno)
+                   << errinfo_file_name(objectspathtmp));
+       }
 }
index 892c32a404787b572c0b582817ce3fabc5307cd1..83c164833e583f316f0244b17b7e0c7d2680444c 100644 (file)
@@ -29,13 +29,13 @@ REGISTER_COMPONENT("livestatus", LivestatusComponent);
  */
 void LivestatusComponent::Start(void)
 {
-#ifndef _WIN32
-       UnixSocket::Ptr socket = boost::make_shared<UnixSocket>();
-       socket->Bind(GetSocketPath());
-#else /* _WIN32 */
+//#ifndef _WIN32
+//     UnixSocket::Ptr socket = boost::make_shared<UnixSocket>();
+//     socket->Bind(GetSocketPath());
+//#else /* _WIN32 */
        TcpSocket::Ptr socket = boost::make_shared<TcpSocket>();
-       socket->Bind("6557", AF_INET);
-#endif /* _WIN32 */
+       socket->Bind("6558", AF_INET);
+//#endif /* _WIN32 */
 
        socket->OnNewClient.connect(boost::bind(&LivestatusComponent::NewClientHandler, this, _2));
        socket->Listen();
index 1427025544a3b665e262aef9275180a422c0c289..d8e040ce8f428ca81aa9691413980947904e1722 100644 (file)
@@ -188,8 +188,12 @@ String Application::GetExePath(const String& argv0)
 
 #ifndef _WIN32
        char buffer[MAXPATHLEN];
-       if (getcwd(buffer, sizeof(buffer)) == NULL)
-               BOOST_THROW_EXCEPTION(PosixException("getcwd failed", errno));
+       if (getcwd(buffer, sizeof(buffer)) == NULL) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("getcwd")
+                   << errinfo_errno(errno));
+       }
+
        String workingDirectory = buffer;
 
        if (argv0[0] != '/')
@@ -229,8 +233,12 @@ String Application::GetExePath(const String& argv0)
                }
        }
 
-       if (realpath(executablePath.CStr(), buffer) == NULL)
-               BOOST_THROW_EXCEPTION(PosixException("realpath failed", errno));
+       if (realpath(executablePath.CStr(), buffer) == NULL) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("realpath")
+                   << errinfo_errno(errno)
+                   << errinfo_file_name(executablePath));
+       }
 
        return buffer;
 #else /* _WIN32 */
index d45edf775823430c75351f8b30c612f33fd75d55..bbe94a62f932f03170a245ec3e6638ac5edbad1e 100644 (file)
@@ -495,8 +495,12 @@ void DynamicObject::DumpObjects(const String& filename)
        _unlink(filename.CStr());
 #endif /* _WIN32 */
 
-       if (rename(tempFilename.CStr(), filename.CStr()) < 0)
-               BOOST_THROW_EXCEPTION(PosixException("rename() failed", errno));
+       if (rename(tempFilename.CStr(), filename.CStr()) < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("rename")
+                   << errinfo_errno(errno)
+                   << errinfo_file_name(tempFilename));
+       }
 }
 
 /*
index f533d1636ab4a0cc5ee1fae5f4f358f873801cce..11233b63e4aed91716ea9fa5914cfa90463de2de 100644 (file)
@@ -23,111 +23,6 @@ using namespace icinga;
 
 boost::thread_specific_ptr<StackTrace> Exception::m_LastStackTrace;
 
-/**
- * Retrieves the error code for the exception.
- *
- * @returns The error code.
- */
-int Exception::GetCode(void) const
-{
-       return m_Code;
-}
-
-/**
- * Sets the error code for the exception.
- *
- * @param code The error code.
- */
-void Exception::SetCode(int code)
-{
-       m_Code = code;
-}
-
-/**
- * Retrieves the description for the exception.
- *
- * @returns The description.
- */
-String Exception::GetMessage(void) const
-{
-       return m_Message;
-}
-
-/**
- * Retrieves the description for the exception.
- *
- * @returns The description.
- */
-const char *Exception::what(void) const throw()
-{
-       return m_Message.CStr();
-}
-
-/**
- * Sets the description for the exception.
- *
- * @param message The description.
- */
-void Exception::SetMessage(String message)
-{
-       m_Message = message;
-}
-
-#ifdef _WIN32
-/**
- * Formats an Win32 error code.
- *
- * @param code The error code.
- * @returns A String describing the error.
- */
-String Win32Exception::FormatErrorCode(int code)
-{
-       char *message;
-       String result = "Unknown error.";
-
-       DWORD rc = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-               FORMAT_MESSAGE_FROM_SYSTEM, NULL, code, 0, (char *)&message,
-               0, NULL);
-
-       if (rc != 0) {
-               result = String(message);
-               LocalFree(message);
-
-               /* remove trailing new-line characters */
-               boost::algorithm::trim_right(result);
-       }
-
-       return result;
-}
-#endif /* _WIN32 */
-
-/**
- * Formats a Posix error code.
- *
- * @param code The error code.
- * @returns A String describing the error.
- */
-String PosixException::FormatErrorCode(int code)
-{
-       return strerror(code);
-}
-
-/**
- * Formats an OpenSSL error code.
- *
- * @param code The error code.
- * @returns A String describing the error.
- */
-String OpenSSLException::FormatErrorCode(int code)
-{
-       const char *message = ERR_error_string(code, NULL);
-
-       if (message == NULL)
-               message = "Unknown error.";
-
-       return message;
-}
-
 #ifndef _WIN32
 extern "C"
 void __cxa_throw(void *obj, void *pvtinfo, void (*dest)(void *))
index 8af7e83ca9cd8b9a644ae6095c4d6b5e5bbf1b24..12f75c6a5d4e55b9b99302b34160e9953b4ca210 100644 (file)
@@ -28,150 +28,65 @@ namespace icinga
  *
  * @ingroup base
  */
-class I2_BASE_API Exception : public virtual exception
+class I2_BASE_API Exception //: public virtual exception
 {
 public:
-       Exception(void)
-           : m_Message(), m_Code(0)
-       { }
-
-       Exception(String message)
-           : m_Message(message), m_Code(0)
-       { }
-
-       Exception(String message, int code)
-           : m_Message(message), m_Code(code)
-       { }
-
-       /**
-        * Destructor for the Exception class. Must be virtual for RTTI to work.
-        */
-       virtual ~Exception(void) throw()
-       { }
-
-       int GetCode(void) const;
-       String GetMessage(void) const;
-
-       virtual const char *what(void) const throw();
-
        static StackTrace *GetLastStackTrace(void);
        static void SetLastStackTrace(const StackTrace& trace);
 
-protected:
-       void SetCode(int code);
-       void SetMessage(String message);
-
 private:
-       String m_Message;
-       int m_Code;
-
        static boost::thread_specific_ptr<StackTrace> m_LastStackTrace;
 };
 
 typedef boost::error_info<StackTrace, StackTrace> StackTraceErrorInfo;
 
-#define DEFINE_EXCEPTION_CLASS(klass)                                  \
-       class klass : public Exception                                  \
-       {                                                               \
-       public:                                                         \
-               inline klass(void) : Exception()                        \
-               { }                                                     \
-                                                                       \
-               inline klass(String message)                            \
-                   : Exception(message)                                \
-               { }                                                     \
-       }
-
-/**
- * An exception that is thrown when a certain feature
- * is not implemented.
- *
- * @ingroup base
- */
-DEFINE_EXCEPTION_CLASS(NotImplementedException);
+class I2_BASE_API posix_error : virtual public std::exception, virtual public boost::exception { };
 
 #ifdef _WIN32
-/**
- * A Win32 error encapsulated in an exception.
- *
- * @ingroup base
- */
-class I2_BASE_API Win32Exception : public Exception
+typedef boost::error_info<struct errinfo_win32_error_, int> errinfo_win32_error;
+
+inline std::string to_string(const errinfo_win32_error& e)
 {
-public:
-       /**
-        * Constructor for the Win32Exception class.
-        *
-        * @param message An error message.
-        * @param errorCode A Win32 error code.
-        */
-       inline Win32Exception(const String& message, int errorCode)
-           : Exception(message + ": " + FormatErrorCode(errorCode), errorCode)
-       { }
-
-       /**
-        * Returns a String that describes the Win32 error.
-        *
-        * @param code The Win32 error code.
-        * @returns A description of the error.
-        */
-       static String FormatErrorCode(int code);
-};
+       stringstream tmp;
+       int code = e.value();
+
+       char *message;
+       String result = "Unknown error.";
+
+       DWORD rc = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+               FORMAT_MESSAGE_FROM_SYSTEM, NULL, code, 0, (char *)&message,
+               0, NULL);
+
+       if (rc != 0) {
+               result = String(message);
+               LocalFree(message);
+
+               /* remove trailing new-line characters */
+               boost::algorithm::trim_right(result);
+       }
+
+       tmp << code << ", \"" << result << "\"";
+       return tmp.str();
+}
 #endif /* _WIN32 */
 
-/**
- * A Posix error encapsulated in an exception.
- *
- * @ingroup base
- */
-class I2_BASE_API PosixException : public Exception
-{
-public:
-       /**
-        * Constructor for the PosixException class.
-        *
-        * @param message An error message.
-        * @param errorCode A Posix (errno) error code.
-        */
-       inline PosixException(const String& message, int errorCode)
-           : Exception(message + ": " + FormatErrorCode(errorCode), errorCode)
-       { }
-
-       /**
-        * Returns a String that describes the Posix error.
-        *
-        * @param code The Posix error code.
-        * @returns A description of the error.
-        */
-       static String FormatErrorCode(int code);
-};
+class openssl_error : virtual public std::exception, virtual public boost::exception { };
 
-/**
- * An OpenSSL error encapsulated in an exception.
- *
- * @ingroup base
- */
-class I2_BASE_API OpenSSLException : public Exception
+typedef boost::error_info<struct errinfo_openssl_error_, int> errinfo_openssl_error;
+
+inline std::string to_string(const errinfo_openssl_error& e)
 {
-public:
-       /**
-        * Constructor for the OpenSSLException class.
-        *
-        * @param message An error message.
-        * @param errorCode An OpenSSL error code.
-        */
-       inline OpenSSLException(const String& message, int errorCode)
-           : Exception(message + ": " + FormatErrorCode(errorCode), errorCode)
-       { }
-
-       /**
-        * Returns a String that describes the OpenSSL error.
-        *
-        * @param code The OpenSSL error code.
-        * @returns A description of the error.
-        */
-       static String FormatErrorCode(int code);
-};
+       stringstream tmp;
+       int code = e.value();
+
+       const char *message = ERR_error_string(code, NULL);
+
+       if (message == NULL)
+               message = "Unknown error.";
+
+       tmp << code << ", \"" << message << "\"";
+       return tmp.str();
+}
 
 }
 
index 643c26c02f93b59a10e4b5763f19c1c7a4d7a9ed..041319c1522cdbbffbecc1228081c2c4f5ed49be 100644 (file)
@@ -142,6 +142,10 @@ using std::type_info;
 #include <boost/uuid/uuid_io.hpp>
 #include <boost/program_options.hpp>
 #include <boost/exception/diagnostic_information.hpp>
+#include <boost/exception/error_info.hpp>
+#include <boost/exception/errinfo_api_function.hpp>
+#include <boost/exception/errinfo_errno.hpp>
+#include <boost/exception/errinfo_file_name.hpp>
 #include <boost/multi_index_container.hpp>
 #include <boost/multi_index/ordered_index.hpp>
 #include <boost/multi_index/key_extractors.hpp>
@@ -163,6 +167,9 @@ using boost::tie;
 using boost::rethrow_exception;
 using boost::current_exception;
 using boost::diagnostic_information;
+using boost::errinfo_api_function;
+using boost::errinfo_errno;
+using boost::errinfo_file_name;
 using boost::multi_index_container;
 using boost::multi_index::indexed_by;
 using boost::multi_index::identity;
index 30944717fafa9d3990170eead153a9977700d924..fb43901114980dbc27a3138ba9f4373c221a6ab2 100644 (file)
@@ -34,11 +34,17 @@ void Process::Initialize(void)
        int fds[2];
 
 #if HAVE_PIPE2
-       if (pipe2(fds, O_CLOEXEC) < 0)
-               BOOST_THROW_EXCEPTION(PosixException("pipe2() failed.", errno));
+       if (pipe2(fds, O_CLOEXEC) < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("pipe2")
+                   << errinfo_errno(errno));
+       }
 #else /* HAVE_PIPE2 */
-       if (pipe(fds) < 0)
-               BOOST_THROW_EXCEPTION(PosixException("pipe() failed.", errno));
+       if (pipe(fds) < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("pipe")
+                   << errinfo_errno(errno));
+       }
 
        /* Don't bother setting fds[0] to clo-exec as we'll only
         * use it in the following dup() call. */
@@ -56,8 +62,11 @@ void Process::Initialize(void)
        for (unsigned int i = 0; i < threads; i++) {
                int childTaskFd = dup(fds[0]);
 
-               if (childTaskFd < 0)
-                       BOOST_THROW_EXCEPTION(PosixException("dup() failed.", errno));
+               if (childTaskFd < 0) {
+                       BOOST_THROW_EXCEPTION(posix_error()
+                           << errinfo_api_function("dup")
+                           << errinfo_errno(errno));
+               }
 
                Utility::SetNonBlocking(childTaskFd);
                Utility::SetCloExec(childTaskFd);
@@ -84,8 +93,11 @@ void Process::WorkerThreadProc(int taskFd)
 
                pfds = (pollfd *)realloc(pfds, (1 + tasks.size()) * sizeof(pollfd));
 
-               if (pfds == NULL)
-                       BOOST_THROW_EXCEPTION(PosixException("realloc() failed.", errno));
+               if (pfds == NULL) {
+                       BOOST_THROW_EXCEPTION(posix_error()
+                           << errinfo_api_function("realloc")
+                           << errinfo_errno(errno));
+               }
 
                int idx = 0;
 
@@ -104,8 +116,11 @@ void Process::WorkerThreadProc(int taskFd)
 
                int rc = poll(pfds, idx, -1);
 
-               if (rc < 0 && errno != EINTR)
-                       BOOST_THROW_EXCEPTION(PosixException("poll() failed.", errno));
+               if (rc < 0 && errno != EINTR) {
+                       BOOST_THROW_EXCEPTION(posix_error()
+                           << errinfo_api_function("poll")
+                           << errinfo_errno(errno));
+               }
 
                if (rc == 0)
                        continue;
@@ -133,7 +148,9 @@ void Process::WorkerThreadProc(int taskFd)
                                                if (errno == EAGAIN)
                                                        break; /* Someone else was faster and took our task. */
 
-                                               BOOST_THROW_EXCEPTION(PosixException("read() failed.", errno));
+                                               BOOST_THROW_EXCEPTION(posix_error()
+                                                   << errinfo_api_function("read")
+                                                   << errinfo_errno(errno));
                                        }
 
                                        while (have > 0) {
@@ -197,8 +214,11 @@ void Process::QueueTask(void)
                 * This little gem which is commonly known as the "self-pipe trick"
                 * takes care of waking up the select() call in the worker thread.
                 */
-               if (write(m_TaskFd, "T", 1) < 0)
-                       BOOST_THROW_EXCEPTION(PosixException("write() failed.", errno));
+               if (write(m_TaskFd, "T", 1) < 0) {
+                       BOOST_THROW_EXCEPTION(posix_error()
+                           << errinfo_api_function("write")
+                           << errinfo_errno(errno));
+               }
        }
 }
 
@@ -211,11 +231,17 @@ void Process::InitTask(void)
        int fds[2];
 
 #if HAVE_PIPE2
-       if (pipe2(fds, O_NONBLOCK | O_CLOEXEC) < 0)
-               BOOST_THROW_EXCEPTION(PosixException("pipe2() failed.", errno));
+       if (pipe2(fds, O_NONBLOCK | O_CLOEXEC) < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("pipe2")
+                   << errinfo_errno(errno));
+       }
 #else /* HAVE_PIPE2 */
-       if (pipe(fds) < 0)
-               BOOST_THROW_EXCEPTION(PosixException("pipe() failed.", errno));
+       if (pipe(fds) < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("pipe")
+                   << errinfo_errno(errno));
+       }
 
        Utility::SetNonBlocking(fds[0]);
        Utility::SetCloExec(fds[0]);
@@ -269,8 +295,11 @@ void Process::InitTask(void)
        m_Pid = fork();
 #endif /* HAVE_WORKING_VFORK */
 
-       if (m_Pid < 0)
-               BOOST_THROW_EXCEPTION(PosixException("fork() failed.", errno));
+       if (m_Pid < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("fork")
+                   << errinfo_errno(errno));
+       }
 
        if (m_Pid == 0) {
                // child process
@@ -331,8 +360,11 @@ bool Process::RunTask(void)
 
        (void) close(m_FD);
 
-       if (waitpid(m_Pid, &status, 0) != m_Pid)
-               BOOST_THROW_EXCEPTION(PosixException("waitpid() failed.", errno));
+       if (waitpid(m_Pid, &status, 0) != m_Pid) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("waitpid")
+                   << errinfo_errno(errno));
+       }
 
        if (WIFEXITED(status)) {
                exitcode = WEXITSTATUS(status);
index 53bd08ee8f5b0e4ca73ce45e57e0eba1efa70337..ba8a74828eb378d6ba92b2bd596a10caf2d95df1 100644 (file)
@@ -137,20 +137,6 @@ int Socket::GetError(void) const
        return 0;
 }
 
-/**
- * Retrieves the last socket error.
- *
- * @returns An error code.
- */
-int Socket::GetLastSocketError(void)
-{
-#ifdef _WIN32
-       return WSAGetLastError();
-#else /* _WIN32 */
-       return errno;
-#endif /* _WIN32 */
-}
-
 /**
  * Processes errors that have occured for the socket.
  */
@@ -158,7 +144,14 @@ void Socket::HandleException(void)
 {
        ObjectLock olock(this);
 
-       BOOST_THROW_EXCEPTION(SocketException("select() returned fd in except fdset", GetError()));
+       BOOST_THROW_EXCEPTION(socket_error()
+           << errinfo_api_function("select")
+#ifndef _WIN32
+           << errinfo_errno(GetError())
+#else /* _WIN32 */
+           << errinfo_win32_error(GetError())
+#endif /* _WIN32 */
+       );
 }
 
 /**
@@ -172,9 +165,16 @@ String Socket::GetAddressFromSockaddr(sockaddr *address, socklen_t len)
        char service[NI_MAXSERV];
 
        if (getnameinfo(address, len, host, sizeof(host), service,
-           sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
-               BOOST_THROW_EXCEPTION(SocketException("getnameinfo() failed",
-                   GetLastSocketError()));
+           sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV) < 0) {
+               BOOST_THROW_EXCEPTION(socket_error()
+                   << errinfo_api_function("getnameinfo")
+       #ifndef _WIN32
+                   << errinfo_errno(errno)
+       #else /* _WIN32 */
+                   << errinfo_win32_error(WSAGetLastError())
+       #endif /* _WIN32 */
+               );
+       }
 
        stringstream s;
        s << "[" << host << "]:" << service;
@@ -193,8 +193,16 @@ String Socket::GetClientAddress(void)
        sockaddr_storage sin;
        socklen_t len = sizeof(sin);
 
-       if (getsockname(GetFD(), (sockaddr *)&sin, &len) < 0)
-               BOOST_THROW_EXCEPTION(SocketException("getsockname() failed", GetError()));
+       if (getsockname(GetFD(), (sockaddr *)&sin, &len) < 0) {
+               BOOST_THROW_EXCEPTION(socket_error()
+                   << errinfo_api_function("getsockname")
+       #ifndef _WIN32
+                   << errinfo_errno(errno)
+       #else /* _WIN32 */
+                   << errinfo_win32_error(WSAGetLastError())
+       #endif /* _WIN32 */
+               );
+       }
 
        return GetAddressFromSockaddr((sockaddr *)&sin, len);
 }
@@ -211,30 +219,20 @@ String Socket::GetPeerAddress(void)
        sockaddr_storage sin;
        socklen_t len = sizeof(sin);
 
-       if (getpeername(GetFD(), (sockaddr *)&sin, &len) < 0)
-               BOOST_THROW_EXCEPTION(SocketException("getpeername() failed", GetError()));
+       if (getpeername(GetFD(), (sockaddr *)&sin, &len) < 0) {
+               BOOST_THROW_EXCEPTION(socket_error()
+                   << errinfo_api_function("getpeername")
+       #ifndef _WIN32
+                   << errinfo_errno(errno)
+       #else /* _WIN32 */
+                   << errinfo_win32_error(WSAGetLastError())
+       #endif /* _WIN32 */
+               );
+       }
 
        return GetAddressFromSockaddr((sockaddr *)&sin, len);
 }
 
-/**
- * Constructor for the SocketException class.
- *
- * @param message The error message.
- * @param errorCode The error code.
- */
-SocketException::SocketException(const String& message, int errorCode)
-{
-#ifdef _WIN32
-       String details = Win32Exception::FormatErrorCode(errorCode);
-#else /* _WIN32 */
-       String details = PosixException::FormatErrorCode(errorCode);
-#endif /* _WIN32 */
-
-       String msg = message + ": " + details;
-       SetMessage(msg.CStr());
-}
-
 /**
  * Read thread procedure for sockets. This function waits until the
  * socket is readable and processes inbound data.
@@ -272,8 +270,16 @@ void Socket::ReadThreadProc(void)
                        return;
 
                try {
-                       if (rc < 0)
-                               BOOST_THROW_EXCEPTION(SocketException("select() failed", GetError()));
+                       if (rc < 0) {
+                               BOOST_THROW_EXCEPTION(socket_error()
+                                   << errinfo_api_function("select")
+                       #ifndef _WIN32
+                                   << errinfo_errno(errno)
+                       #else /* _WIN32 */
+                                   << errinfo_win32_error(WSAGetLastError())
+                       #endif /* _WIN32 */
+                               );
+                       }
 
                        if (FD_ISSET(fd, &readfds))
                                HandleReadable();
@@ -330,8 +336,16 @@ void Socket::WriteThreadProc(void)
                        return;
 
                try {
-                       if (rc < 0)
-                               BOOST_THROW_EXCEPTION(SocketException("select() failed", GetError()));
+                       if (rc < 0) {
+                               BOOST_THROW_EXCEPTION(socket_error()
+                                   << errinfo_api_function("select")
+                       #ifndef _WIN32
+                                   << errinfo_errno(errno)
+                       #else /* _WIN32 */
+                                   << errinfo_win32_error(WSAGetLastError())
+                       #endif /* _WIN32 */
+                               );
+                       }
 
                        if (FD_ISSET(fd, &writefds))
                                HandleWritable();
@@ -451,8 +465,16 @@ void Socket::Write(const void *buffer, size_t size)
  */
 void Socket::Listen(void)
 {
-       if (listen(GetFD(), SOMAXCONN) < 0)
-               BOOST_THROW_EXCEPTION(SocketException("listen() failed", GetError()));
+       if (listen(GetFD(), SOMAXCONN) < 0) {
+               BOOST_THROW_EXCEPTION(socket_error()
+                   << errinfo_api_function("listen")
+       #ifndef _WIN32
+                   << errinfo_errno(errno)
+       #else /* _WIN32 */
+                   << errinfo_win32_error(WSAGetLastError())
+       #endif /* _WIN32 */
+               );
+       }
 
        {
                ObjectLock olock(this);
@@ -500,8 +522,16 @@ void Socket::HandleWritableClient(void)
 
                rc = send(GetFD(), data, count, 0);
 
-               if (rc <= 0)
-                       BOOST_THROW_EXCEPTION(SocketException("send() failed", GetError()));
+               if (rc <= 0) {
+                       BOOST_THROW_EXCEPTION(socket_error()
+                           << errinfo_api_function("send")
+               #ifndef _WIN32
+                           << errinfo_errno(errno)
+               #else /* _WIN32 */
+                           << errinfo_win32_error(WSAGetLastError())
+               #endif /* _WIN32 */
+                       );
+               }
 
                m_SendQueue->Read(NULL, rc);
        }
@@ -528,8 +558,16 @@ void Socket::HandleReadableClient(void)
 #endif /* _WIN32 */
                        break;
 
-               if (rc < 0)
-                       BOOST_THROW_EXCEPTION(SocketException("recv() failed", GetError()));
+               if (rc < 0) {
+                       BOOST_THROW_EXCEPTION(socket_error()
+                           << errinfo_api_function("recv")
+               #ifndef _WIN32
+                           << errinfo_errno(errno)
+               #else /* _WIN32 */
+                           << errinfo_win32_error(WSAGetLastError())
+               #endif /* _WIN32 */
+                       );
+               }
 
                new_data = true;
 
@@ -563,8 +601,16 @@ void Socket::HandleReadableServer(void)
 
        fd = accept(GetFD(), (sockaddr *)&addr, &addrlen);
 
-       if (fd < 0)
-               BOOST_THROW_EXCEPTION(SocketException("accept() failed", GetError()));
+       if (fd < 0) {
+               BOOST_THROW_EXCEPTION(socket_error()
+                   << errinfo_api_function("accept")
+       #ifndef _WIN32
+                   << errinfo_errno(errno)
+       #else /* _WIN32 */
+                   << errinfo_win32_error(WSAGetLastError())
+       #endif /* _WIN32 */
+               );
+       }
 
        Socket::Ptr client = boost::make_shared<Socket>();
        client->SetFD(fd);
index e979ad1f40bdb2a90295579ec7f60dbb66c7f60b..d0de45c3cfc41b7bbcd3ad585ef146405d33ec9c 100644 (file)
@@ -61,7 +61,6 @@ protected:
        void SetConnected(bool connected);
 
        int GetError(void) const;
-       static int GetLastSocketError(void);
 
        mutable boost::mutex m_SocketMutex;
 
@@ -107,14 +106,7 @@ private:
        bool WantsToRead(void) const;
 };
 
-/**
- * A socket exception.
- */
-class SocketException : public Exception
-{
-public:
-       SocketException(const String& message, int errorCode);
-};
+class socket_error : virtual public std::exception, virtual public boost::exception { };
 
 }
 
index bbd35505bc7dcd246f26faba6e7fbd73c48178cd..ab891b2cdb322ab7773ab10e7ce0486842d2eda1 100644 (file)
@@ -52,8 +52,16 @@ void TcpSocket::Bind(String node, String service, int family)
        hints.ai_flags = AI_PASSIVE;
 
        if (getaddrinfo(node.IsEmpty() ? NULL : node.CStr(),
-           service.CStr(), &hints, &result) < 0)
-               BOOST_THROW_EXCEPTION(SocketException("getaddrinfo() failed", GetLastSocketError()));
+           service.CStr(), &hints, &result) < 0) {
+               BOOST_THROW_EXCEPTION(socket_error()
+                   << errinfo_api_function("getaddrinfo")
+#ifndef _WIN32
+                   << errinfo_errno(errno)
+#else /* _WIN32 */
+                   << errinfo_win32_error(WSAGetLastError())
+#endif /* _WIN32 */
+               );
+       }
 
        int fd = INVALID_SOCKET;
 
@@ -114,8 +122,16 @@ void TcpSocket::Connect(const String& node, const String& service)
 
        int rc = getaddrinfo(node.CStr(), service.CStr(), &hints, &result);
 
-       if (rc < 0)
-               BOOST_THROW_EXCEPTION(SocketException("getaddrinfo() failed", GetLastSocketError()));
+       if (rc < 0) {
+               BOOST_THROW_EXCEPTION(socket_error()
+                   << errinfo_api_function("getaddrinfo")
+#ifndef _WIN32
+                   << errinfo_errno(errno)
+#else /* _WIN32 */
+                   << errinfo_win32_error(WSAGetLastError())
+#endif /* _WIN32 */
+               );
+       }
 
        int fd = INVALID_SOCKET;
 
index 3babd20db548ee0d13726d016083909129f2d076..f2de819380520cdd767a70fcba2d9ef47debcd93 100644 (file)
@@ -48,8 +48,11 @@ void TlsStream::Start(void)
 
        m_SSLContext.reset();
 
-       if (!m_SSL)
-               BOOST_THROW_EXCEPTION(OpenSSLException("SSL_new failed", ERR_get_error()));
+       if (!m_SSL) {
+               BOOST_THROW_EXCEPTION(openssl_error()
+                   << errinfo_api_function("SSL_new")
+                   << errinfo_openssl_error(ERR_get_error()));
+       }
 
        if (!GetClientCertificate())
                BOOST_THROW_EXCEPTION(logic_error("No X509 client certificate was specified."));
@@ -153,7 +156,9 @@ void TlsStream::HandleIO(void)
                                        return;
                                default:
                                        I2Stream_check_exception(m_BIO);
-                                       BOOST_THROW_EXCEPTION(OpenSSLException("SSL_do_handshake failed", ERR_get_error()));
+                                       BOOST_THROW_EXCEPTION(openssl_error()
+                                           << errinfo_api_function("SSL_do_handshake")
+                                           << errinfo_openssl_error(ERR_get_error()));
                        }
                }
        }
@@ -178,7 +183,9 @@ void TlsStream::HandleIO(void)
                                        return;
                                default:
                                        I2Stream_check_exception(m_BIO);
-                                       BOOST_THROW_EXCEPTION(OpenSSLException("SSL_read failed", ERR_get_error()));
+                                       BOOST_THROW_EXCEPTION(openssl_error()
+                                           << errinfo_api_function("SSL_read")
+                                           << errinfo_openssl_error(ERR_get_error()));
                        }
                }
        }
@@ -215,7 +222,9 @@ void TlsStream::HandleIO(void)
                                        return;
                                default:
                                        I2Stream_check_exception(m_BIO);
-                                       BOOST_THROW_EXCEPTION(OpenSSLException("SSL_write failed", ERR_get_error()));
+                                       BOOST_THROW_EXCEPTION(openssl_error()
+                                           << errinfo_api_function("SSL_write")
+                                           << errinfo_openssl_error(ERR_get_error()));
                        }
                }
        }
index f8ad65d5ffef16c684403c7edf6b6a0dada2227d..4075eb015a5b718215f0d80ec814d5a80250c0c8 100644 (file)
@@ -26,8 +26,11 @@ UnixSocket::UnixSocket(void)
 {
        int fd = socket(AF_UNIX, SOCK_STREAM, PF_UNIX);
 
-       if (fd < 0)
-               BOOST_THROW_EXCEPTION(PosixException("socket() failed", errno));
+       if (fd < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("socket")
+                   << errinfo_errno(errno));
+       }
 
        SetFD(fd);
 }
@@ -42,8 +45,11 @@ void UnixSocket::Bind(const String& path)
        strncpy(sun.sun_path, path.CStr(), sizeof(sun.sun_path));
        sun.sun_path[sizeof(sun.sun_path) - 1] = '\0';
 
-       if (bind(GetFD(), (sockaddr *)&sun, SUN_LEN(&sun)) < 0)
-               BOOST_THROW_EXCEPTION(PosixException("bind() failed", errno));
+       if (bind(GetFD(), (sockaddr *)&sun, SUN_LEN(&sun)) < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("bind")
+                   << errinfo_errno(errno));
+       }
 }
 
 void UnixSocket::Connect(const String& path)
@@ -54,7 +60,10 @@ void UnixSocket::Connect(const String& path)
        strncpy(sun.sun_path, path.CStr(), sizeof(sun.sun_path));
        sun.sun_path[sizeof(sun.sun_path) - 1] = '\0';
 
-       if (connect(GetFD(), (sockaddr *)&sun, SUN_LEN(&sun)) < 0 && errno != EINPROGRESS)
-               BOOST_THROW_EXCEPTION(PosixException("connect() failed", errno));
+       if (connect(GetFD(), (sockaddr *)&sun, SUN_LEN(&sun)) < 0 && errno != EINPROGRESS) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("connect")
+                   << errinfo_errno(errno));
+       }
 }
 #endif /* _WIN32 */
index 1165cf629581aeded2b3f368892aa7aa62263956..c9ee8ed713c994aafbfc1f7919d0facd27562404 100644 (file)
@@ -69,16 +69,24 @@ void Utility::Daemonize(void) {
        int fd;
 
        pid = fork();
-       if (pid < 0)
-               BOOST_THROW_EXCEPTION(PosixException("fork() failed", errno));
+
+       if (pid < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("fork")
+                   << errinfo_errno(errno));
+       }
 
        if (pid)
                _exit(0);
 
        fd = open("/dev/null", O_RDWR);
 
-       if (fd < 0)
-               BOOST_THROW_EXCEPTION(PosixException("open() failed", errno));
+       if (fd < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("open")
+                   << errinfo_errno(errno)
+                   << errinfo_file_name("/dev/null"));
+       }
 
        if (fd != STDIN_FILENO)
                dup2(fd, STDIN_FILENO);
@@ -92,8 +100,11 @@ void Utility::Daemonize(void) {
        if (fd > STDERR_FILENO)
                close(fd);
 
-       if (setsid() < 0)
-               BOOST_THROW_EXCEPTION(PosixException("setsid() failed", errno));
+       if (setsid() < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("setsid")
+                   << errinfo_errno(errno));
+       }
 #endif
 }
 
@@ -127,20 +138,36 @@ shared_ptr<SSL_CTX> Utility::MakeSSLContext(const String& pubkey, const String&
 
        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.CStr()))
-               BOOST_THROW_EXCEPTION(OpenSSLException("Could not load public X509 key file", ERR_get_error()));
+       if (!SSL_CTX_use_certificate_chain_file(sslContext.get(), pubkey.CStr())) {
+               BOOST_THROW_EXCEPTION(openssl_error()
+                   << errinfo_api_function("SSL_CTX_use_certificate_chain_file")
+                   << errinfo_openssl_error(ERR_get_error())
+                   << errinfo_file_name(pubkey));
+       }
 
-       if (!SSL_CTX_use_PrivateKey_file(sslContext.get(), privkey.CStr(), SSL_FILETYPE_PEM))
-               BOOST_THROW_EXCEPTION(OpenSSLException("Could not load private X509 key file", ERR_get_error()));
+       if (!SSL_CTX_use_PrivateKey_file(sslContext.get(), privkey.CStr(), SSL_FILETYPE_PEM)) {
+               BOOST_THROW_EXCEPTION(openssl_error()
+                   << errinfo_api_function("SSL_CTX_use_PrivateKey_file")
+                   << errinfo_openssl_error(ERR_get_error())
+                   << errinfo_file_name(privkey));
+       }
 
-       if (!SSL_CTX_load_verify_locations(sslContext.get(), cakey.CStr(), NULL))
-               BOOST_THROW_EXCEPTION(OpenSSLException("Could not load public CA key file", ERR_get_error()));
+       if (!SSL_CTX_load_verify_locations(sslContext.get(), cakey.CStr(), NULL)) {
+               BOOST_THROW_EXCEPTION(openssl_error()
+                   << errinfo_api_function("SSL_CTX_load_verify_locations")
+                   << errinfo_openssl_error(ERR_get_error())
+                   << errinfo_file_name(cakey));
+       }
 
        STACK_OF(X509_NAME) *cert_names;
 
        cert_names = SSL_load_client_CA_file(cakey.CStr());
-       if (cert_names == NULL)
-               BOOST_THROW_EXCEPTION(OpenSSLException("SSL_load_client_CA_file() failed", ERR_get_error()));
+       if (cert_names == NULL) {
+               BOOST_THROW_EXCEPTION(openssl_error()
+                   << errinfo_api_function("SSL_load_client_CA_file")
+                   << errinfo_openssl_error(ERR_get_error())
+                   << errinfo_file_name(cakey));
+       }
 
        SSL_CTX_set_client_CA_list(sslContext.get(), cert_names);
 
@@ -160,9 +187,11 @@ String Utility::GetCertificateCN(const shared_ptr<X509>& certificate)
        int rc = X509_NAME_get_text_by_NID(X509_get_subject_name(certificate.get()),
            NID_commonName, buffer, sizeof(buffer));
 
-       if (rc == -1)
-               BOOST_THROW_EXCEPTION(OpenSSLException("X509 certificate has no CN"
-                   " attribute", ERR_get_error()));
+       if (rc == -1) {
+               BOOST_THROW_EXCEPTION(openssl_error()
+                   << errinfo_api_function("X509_NAME_get_text_by_NID")
+                   << errinfo_openssl_error(ERR_get_error()));
+       }
 
        return buffer;
 }
@@ -178,18 +207,25 @@ shared_ptr<X509> Utility::GetX509Certificate(const String& pemfile)
        X509 *cert;
        BIO *fpcert = BIO_new(BIO_s_file());
 
-       if (fpcert == NULL)
-               BOOST_THROW_EXCEPTION(OpenSSLException("BIO_new failed",
-                   ERR_get_error()));
+       if (fpcert == NULL) {
+               BOOST_THROW_EXCEPTION(openssl_error()
+                   << errinfo_api_function("BIO_new")
+                   << errinfo_openssl_error(ERR_get_error()));
+       }
 
-       if (BIO_read_filename(fpcert, pemfile.CStr()) < 0)
-               BOOST_THROW_EXCEPTION(OpenSSLException("BIO_read_filename failed",
-                   ERR_get_error()));
+       if (BIO_read_filename(fpcert, pemfile.CStr()) < 0) {
+               BOOST_THROW_EXCEPTION(openssl_error()
+                   << errinfo_api_function("BIO_read_filename")
+                   << errinfo_openssl_error(ERR_get_error())
+                   << errinfo_file_name(pemfile));
+       }
 
        cert = PEM_read_bio_X509_AUX(fpcert, NULL, NULL, NULL);
-       if (cert == NULL)
-               BOOST_THROW_EXCEPTION(OpenSSLException("PEM_read_bio_X509_AUX failed",
-                   ERR_get_error()));
+       if (cert == NULL) {
+               BOOST_THROW_EXCEPTION(openssl_error()
+                   << errinfo_api_function("PEM_read_bio_X509_AUX")
+                   << errinfo_openssl_error(ERR_get_error()));
+       }
 
        BIO_free(fpcert);
 
@@ -319,8 +355,11 @@ double Utility::GetTime(void)
 #else /* _WIN32 */
        struct timeval tv;
 
-       if (gettimeofday(&tv, NULL) < 0)
-               BOOST_THROW_EXCEPTION(PosixException("gettimeofday() failed", errno));
+       if (gettimeofday(&tv, NULL) < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("gettimeofday")
+                   << errinfo_errno(errno));
+       }
 
        return tv.tv_sec + tv.tv_usec / 1000000.0;
 #endif /* _WIN32 */
@@ -444,7 +483,10 @@ bool Utility::Glob(const String& pathSpec, const function<void (const String&)>&
                if (rc == GLOB_NOMATCH)
                        return false;
 
-               BOOST_THROW_EXCEPTION(PosixException("glob() failed", errno));
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("glob")
+                   << errinfo_errno(errno)
+                   << errinfo_file_name(pathSpec));
        }
 
        if (gr.gl_pathc == 0) {
@@ -467,24 +509,36 @@ bool Utility::Glob(const String& pathSpec, const function<void (const String&)>&
 #ifndef _WIN32
 void Utility::SetNonBlocking(int fd)
 {
-       int flags;
-       flags = fcntl(fd, F_GETFL, 0);
-       if (flags < 0)
-               BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
+       int flags = fcntl(fd, F_GETFL, 0);
 
-       if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0)
-               BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
+       if (flags < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("fcntl")
+                   << errinfo_errno(errno));
+       }
+
+       if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("fcntl")
+                   << errinfo_errno(errno));
+       }
 }
 
 void Utility::SetCloExec(int fd)
 {
-       int flags;
-       flags = fcntl(fd, F_GETFD, 0);
-       if (flags < 0)
-               BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
+       int flags = fcntl(fd, F_GETFD, 0);
 
-       if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
-               BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
+       if (flags < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("fcntl")
+                   << errinfo_errno(errno));
+       }
+
+       if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("fcntl")
+                   << errinfo_errno(errno));
+       }
 }
 #endif /* _WIN32 */
 
@@ -512,13 +566,19 @@ String Utility::FormatDateTime(const char *format, double ts)
 #ifdef _MSC_VER
        tm *temp = localtime(&tempts);
 
-       if (temp == NULL)
-               BOOST_THROW_EXCEPTION(PosixException("localtime() failed", errno));
+       if (temp == NULL) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("localtime")
+                   << errinfo_errno(errno));
+       }
 
        tmthen = *temp;
 #else /* _MSC_VER */
-       if (localtime_r(&tempts, &tmthen) == NULL)
-               BOOST_THROW_EXCEPTION(PosixException("localtime_r() failed.", errno));
+       if (localtime_r(&tempts, &tmthen) == NULL) {
+               BOOST_THROW_EXCEPTION(posix_error()
+                   << errinfo_api_function("localtime_r")
+                   << errinfo_errno(errno));
+       }
 #endif /* _MSC_VER */
 
        strftime(timestamp, sizeof(timestamp), format, &tmthen);
index 4d5518867d3837204d08a8ceea76946bf3e55247..dc7cb06b513aa08db92fa5572bd332abb5154a9d 100644 (file)
@@ -228,7 +228,7 @@ void Endpoint::UnregisterTopicHandler(const String&, const function<Endpoint::Ca
        //m_TopicHandlers[method] -= callback;
        //UnregisterSubscription(method);
 
-       BOOST_THROW_EXCEPTION(NotImplementedException());
+       BOOST_THROW_EXCEPTION(runtime_error("Not implemented."));
 }
 
 void Endpoint::ProcessRequest(const Endpoint::Ptr& sender, const RequestMessage& request)