Misc fixes in error handling.

This commit is contained in:
Vincent Richard 2016-03-25 21:50:35 +01:00
parent fed1469ade
commit 08a3ba2ba1
3 changed files with 65 additions and 17 deletions

View File

@ -978,6 +978,8 @@ CHECK_SYMBOL_EXISTS(SYS_gettid sys/syscall.h VMIME_HAVE_SYSCALL_GETTID)
CHECK_SYMBOL_EXISTS(SO_KEEPALIVE sys/socket.h VMIME_HAVE_SO_KEEPALIVE) CHECK_SYMBOL_EXISTS(SO_KEEPALIVE sys/socket.h VMIME_HAVE_SO_KEEPALIVE)
CHECK_SYMBOL_EXISTS(strerror_r string.h VMIME_HAVE_STRERROR_R)
FIND_PACKAGE(Threads) FIND_PACKAGE(Threads)
IF(VMIME_BUILD_SHARED_LIBRARY) IF(VMIME_BUILD_SHARED_LIBRARY)

View File

@ -84,6 +84,7 @@ typedef unsigned @VMIME_64BIT_TYPE@ vmime_uint64;
#cmakedefine01 VMIME_HAVE_GMTIME_R #cmakedefine01 VMIME_HAVE_GMTIME_R
#cmakedefine01 VMIME_HAVE_LOCALTIME_S #cmakedefine01 VMIME_HAVE_LOCALTIME_S
#cmakedefine01 VMIME_HAVE_LOCALTIME_R #cmakedefine01 VMIME_HAVE_LOCALTIME_R
#cmakedefine01 VMIME_HAVE_STRERROR_R
#cmakedefine01 VMIME_HAVE_MLANG #cmakedefine01 VMIME_HAVE_MLANG
#cmakedefine01 VMIME_HAVE_SO_KEEPALIVE #cmakedefine01 VMIME_HAVE_SO_KEEPALIVE
#cmakedefine01 VMIME_SHARED_PTR_USE_CXX #cmakedefine01 VMIME_SHARED_PTR_USE_CXX

View File

@ -114,8 +114,8 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port
m_timeoutHandler->resetTimeOut(); m_timeoutHandler->resetTimeOut();
for (struct ::addrinfo* curAddrInfo = addrInfo ; for (struct ::addrinfo* curAddrInfo = addrInfo ;
sock == -1 && curAddrInfo != NULL ; sock == -1 && curAddrInfo != NULL ;
curAddrInfo = curAddrInfo->ai_next, connectErrno = ETIMEDOUT) curAddrInfo = curAddrInfo->ai_next, connectErrno = ETIMEDOUT)
{ {
if (curAddrInfo->ai_family != AF_INET && curAddrInfo->ai_family != AF_INET6) if (curAddrInfo->ai_family != AF_INET && curAddrInfo->ai_family != AF_INET6)
continue; continue;
@ -422,8 +422,26 @@ void posixSocket::resolve(struct ::addrinfo** addrInfo, const vmime::string& add
} }
else if (gaiError != EAI_AGAIN) else if (gaiError != EAI_AGAIN)
{ {
throw vmime::exceptions::connection_error if (gaiError == EAI_SYSTEM)
("gai_suspend() failed: " + std::string(gai_strerror(gaiError))); {
if (errno != 0)
{
try
{
throwSocketError(errno);
}
catch (exceptions::socket_exception& e)
{
throw vmime::exceptions::connection_error
("Error while connecting socket.", e);
}
}
}
else
{
throw vmime::exceptions::connection_error
("gai_suspend() failed: " + std::string(gai_strerror(gaiError)));
}
} }
// Check for timeout // Check for timeout
@ -616,7 +634,7 @@ bool posixSocket::waitForData(const bool read, const bool write, const int msecs
// No data available at this time // No data available at this time
// Check if we are timed out // Check if we are timed out
if (m_timeoutHandler && if (m_timeoutHandler &&
m_timeoutHandler->isTimeOut()) m_timeoutHandler->isTimeOut())
{ {
if (!m_timeoutHandler->handleTimeOut()) if (!m_timeoutHandler->handleTimeOut())
{ {
@ -677,7 +695,7 @@ size_t posixSocket::receiveRaw(byte_t* buffer, const size_t count)
// Check if we are timed out // Check if we are timed out
if (m_timeoutHandler && if (m_timeoutHandler &&
m_timeoutHandler->isTimeOut()) m_timeoutHandler->isTimeOut())
{ {
if (!m_timeoutHandler->handleTimeOut()) if (!m_timeoutHandler->handleTimeOut())
{ {
@ -767,7 +785,7 @@ size_t posixSocket::sendRawNonBlocking(const byte_t* buffer, const size_t count)
// Check if we are timed out // Check if we are timed out
if (m_timeoutHandler && if (m_timeoutHandler &&
m_timeoutHandler->isTimeOut()) m_timeoutHandler->isTimeOut())
{ {
if (!m_timeoutHandler->handleTimeOut()) if (!m_timeoutHandler->handleTimeOut())
{ {
@ -797,7 +815,7 @@ size_t posixSocket::sendRawNonBlocking(const byte_t* buffer, const size_t count)
void posixSocket::throwSocketError(const int err) void posixSocket::throwSocketError(const int err)
{ {
string msg; const char* msg = NULL;
switch (err) switch (err)
{ {
@ -815,19 +833,46 @@ void posixSocket::throwSocketError(const int err)
case EMSGSIZE: msg = "EMSGSIZE: message cannot be sent atomically"; break; case EMSGSIZE: msg = "EMSGSIZE: message cannot be sent atomically"; break;
case ENOBUFS: msg = "ENOBUFS: output queue is full"; break; case ENOBUFS: msg = "ENOBUFS: output queue is full"; break;
case ENOMEM: msg = "ENOMEM: out of memory"; break; case ENOMEM: msg = "ENOMEM: out of memory"; break;
case EPIPE: case EPIPE: msg = "EPIPE: broken pipe"; break;
case ENOTCONN: msg = "ENOTCONN: not connected"; break; case ENOTCONN: msg = "ENOTCONN: not connected"; break;
case ECONNREFUSED: msg = "ECONNREFUSED: connection refused"; break; case ECONNREFUSED: msg = "ECONNREFUSED: connection refused"; break;
default:
std::ostringstream oss;
oss << ::strerror(err);
msg = oss.str();
break;
} }
throw exceptions::socket_exception(msg); if (msg)
{
throw exceptions::socket_exception(msg);
}
else
{
// Use strerror() to get string describing error number
#if VMIME_HAVE_STRERROR_R
char errbuf[512];
#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE
// XSI-compliant strerror_r()
strerror_r(err, errbuf, sizeof(errbuf));
throw exceptions::socket_exception(errbuf);
#else
// GNU-specific strerror_r()
const std::string strmsg(strerror_r(err, errbuf, sizeof(errbuf)));
throw exceptions::socket_exception(strmsg);
#endif
#else // !VMIME_HAVE_STRERROR_R
const std::string strmsg(strerror(err));
throw exceptions::socket_exception(strmsg);
#endif // VMIME_HAVE_STRERROR_R
}
} }