Add more information to exceptions.

This commit is contained in:
Gunnar Beutner 2013-03-11 13:45:08 +01:00
parent 0029bc30b7
commit d8edd98e41
15 changed files with 411 additions and 396 deletions

View 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));
}
}

View 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();

View 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 */

View 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));
}
}
/*

View 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 *))

View 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
{
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)
{ }
typedef boost::error_info<struct errinfo_win32_error_, int> errinfo_win32_error;
/**
* 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);
};
inline std::string to_string(const errinfo_win32_error& e)
{
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
class openssl_error : virtual public std::exception, virtual public boost::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 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)
{ }
stringstream tmp;
int code = e.value();
/**
* 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);
};
const char *message = ERR_error_string(code, NULL);
/**
* An OpenSSL error encapsulated in an exception.
*
* @ingroup base
*/
class I2_BASE_API OpenSSLException : public Exception
{
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)
{ }
if (message == NULL)
message = "Unknown error.";
/**
* 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);
};
tmp << code << ", \"" << message << "\"";
return tmp.str();
}
}

View 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;

View 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);

View 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);

View 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 { };
}

View 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;

View 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()));
}
}
}

View 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 */

View 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);

View 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)