Fixed #133: poll() is preferred over select().

This commit is contained in:
Vincent Richard 2016-03-04 20:56:14 +01:00
parent b8b5586d6a
commit d271534548

View File

@ -45,6 +45,7 @@
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <poll.h>
#include "vmime/utility/stringUtils.hpp" #include "vmime/utility/stringUtils.hpp"
@ -169,7 +170,7 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port
// Wait for socket to be connected. // Wait for socket to be connected.
bool connected = false; bool connected = false;
const int selectTimeout = 1000; // select() timeout (ms) const int pollTimeout = 1000; // poll() timeout (ms)
const int tryNextTimeout = 5000; // maximum time before trying next (ms) const int tryNextTimeout = 5000; // maximum time before trying next (ms)
timeval startTime = { 0, 0 }; timeval startTime = { 0, 0 };
@ -177,18 +178,16 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port
do do
{ {
struct timeval tm; pollfd fds[1];
tm.tv_sec = selectTimeout / 1000; fds[0].fd = sock;
tm.tv_usec = selectTimeout % 1000; fds[0].events = POLLIN | POLLOUT;
fd_set fds; const int ret = ::poll(fds, sizeof(fds) / sizeof(fds[0]), pollTimeout);
FD_ZERO(&fds);
FD_SET(sock, &fds);
const int ret = select(sock + 1, NULL, &fds, NULL, &tm);
// Success // Success
if (ret > 0) if (ret > 0)
{
if (fds[0].revents & (POLLIN | POLLOUT))
{ {
int error = 0; int error = 0;
socklen_t len = sizeof(error); socklen_t len = sizeof(error);
@ -204,22 +203,22 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port
else else
connected = true; connected = true;
} }
}
break; break;
} }
// Error // Error
else if (ret < -1) else if (ret < -1)
{ {
if (errno != EINTR) if (errno != EAGAIN && errno != EINTR)
{ {
// Cancel connection // Cancel connection
connectErrno = errno; connectErrno = errno;
break; break;
} }
} }
// Check for timeout // Check for timeout
else if (ret == 0)
{
if (m_timeoutHandler->isTimeOut()) if (m_timeoutHandler->isTimeOut())
{ {
if (!m_timeoutHandler->handleTimeOut()) if (!m_timeoutHandler->handleTimeOut())
@ -238,7 +237,6 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port
{ {
// Keep waiting for connection // Keep waiting for connection
} }
}
timeval curTime = { 0, 0 }; timeval curTime = { 0, 0 };
gettimeofday(&curTime, /* timezone */ NULL); gettimeofday(&curTime, /* timezone */ NULL);
@ -584,20 +582,28 @@ bool posixSocket::waitForData(const bool read, const bool write, const int msecs
for (int i = 0 ; i <= msecs / 10 ; ++i) for (int i = 0 ; i <= msecs / 10 ; ++i)
{ {
// Check whether data is available // Check whether data is available
fd_set fds; pollfd fds[1];
FD_ZERO(&fds); fds[0].fd = m_desc;
FD_SET(m_desc, &fds); fds[0].events = 0;
struct timeval tv; if (read)
tv.tv_sec = 0; fds[0].events |= POLLIN;
tv.tv_usec = 10000; // 10 ms
ssize_t ret = ::select(m_desc + 1, read ? &fds : NULL, write ? &fds : NULL, NULL, &tv); if (write)
fds[0].events |= POLLOUT;
if (ret <= 0) const int ret = ::poll(fds, sizeof(fds) / sizeof(fds[0]), 10 /* ms */);
if (ret < 0)
{ {
if (ret < 0 && !IS_EAGAIN(errno)) if (errno != EAGAIN && errno != EINTR)
throwSocketError(errno); throwSocketError(errno);
}
else if (ret > 0)
{
if (fds[0].revents & (POLLIN | POLLOUT))
return true;
}
// No data available at this time // No data available at this time
// Check if we are timed out // Check if we are timed out
@ -616,11 +622,6 @@ bool posixSocket::waitForData(const bool read, const bool write, const int msecs
} }
} }
} }
else if (ret > 0)
{
return true;
}
}
return false; // time out return false; // time out
} }