Skip to content

Commit

Permalink
fix(Net): #4594: PollSet::poll on Windows always returns immediately …
Browse files Browse the repository at this point in the history
…after first connection, due to bad event socket implementation
  • Loading branch information
obiltschnig committed Jun 26, 2024
1 parent 3196b27 commit 45d0b25
Showing 1 changed file with 32 additions and 50 deletions.
82 changes: 32 additions & 50 deletions Net/src/PollSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

#if defined(POCO_HAVE_FD_EPOLL)
#ifdef POCO_OS_FAMILY_WINDOWS
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/DatagramSocket.h"
#include "Poco/Net/SocketAddress.h"
#include "wepoll.h"
#else
Expand All @@ -48,16 +48,13 @@ namespace Net {


#ifdef WEPOLL_H_

namespace {

int close(HANDLE h)
namespace
{
return epoll_close(h);
}

int close(HANDLE h)
{
return epoll_close(h);
}
}

#endif // WEPOLL_H_


Expand All @@ -72,11 +69,7 @@ class PollSetImpl
static const epoll_event EPOLL_NULL_EVENT;

PollSetImpl(): _events(FD_SETSIZE, EPOLL_NULL_EVENT),
#if defined(WEPOLL_H_)
_eventfd(eventfd()),
#else
_eventfd(eventfd(0, 0)),
#endif // WEPOLL_H_
_epollfd(epoll_create(1))
{
int err = addFD(_eventfd, PollSet::POLL_READ, EPOLL_CTL_ADD);
Expand Down Expand Up @@ -174,8 +167,7 @@ class PollSetImpl
while (true)
{
Poco::Timestamp start;
rc = epoll_wait(_epollfd, &_events[0],
static_cast<int>(_events.size()), static_cast<int>(remainingTime.totalMilliseconds()));
rc = epoll_wait(_epollfd, &_events[0], static_cast<int>(_events.size()), static_cast<int>(remainingTime.totalMilliseconds()));
if (rc == 0)
{
if (keepWaiting(start, remainingTime)) continue;
Expand All @@ -185,7 +177,10 @@ class PollSetImpl
// if we are hitting the events limit, resize it; even without resizing, the subseqent
// calls would round-robin through the remaining ready sockets, but it's better to give
// the call enough room once we start hitting the boundary
if (rc >= _events.size()) _events.resize(_events.size()*2);
if (rc >= _events.size())
{
_events.resize(_events.size()*2);
}
else if (rc < 0)
{
// if interrupted and there's still time left, keep waiting
Expand Down Expand Up @@ -217,11 +212,15 @@ class PollSetImpl
}
else if (_events[i].events & EPOLLIN) // eventfd signaled
{
uint64_t val;
#ifdef WEPOLL_H_
if (_pSocket && _pSocket->available())
_pSocket->impl()->receiveBytes(&val, sizeof(val));
if (_pEventSocket)
{
char val;
Poco::Net::SocketAddress sa;
_pEventSocket->receiveFrom(&val, sizeof(val), sa);
}
#else
std::uint64_t val;
read(_eventfd, &val, sizeof(val));
#endif
}
Expand All @@ -231,19 +230,14 @@ class PollSetImpl

void wakeUp()
{
uint64_t val = 1;
#ifdef WEPOLL_H_
#ifdef POCO_HAS_UNIX_SOCKET
poco_check_ptr (_pSockFile);
StreamSocket ss(SocketAddress(_pSockFile->path()));
#else
StreamSocket ss(SocketAddress("127.0.0.1", _port));
#endif
ss.sendBytes(&val, sizeof(val));
char val = 1;
_pEventSocket->sendTo(&val, sizeof(val), _pEventSocket->address());
#else
// This is guaranteed to write into a valid fd,
// or 0 (meaning PollSet is being destroyed).
// Errors are ignored.
std::uint64_t val = 1;
write(_eventfd, &val, sizeof(val));
#endif
}
Expand Down Expand Up @@ -319,31 +313,18 @@ class PollSetImpl
#else // WEPOLL_H_
using EPollHandle = std::atomic<HANDLE>;

#ifdef POCO_HAS_UNIX_SOCKET
int eventfd()
{
if (!_pSockFile)
{
_pSockFile.reset(new TemporaryFile);
_pSocket.reset(new ServerSocket(SocketAddress(_pSockFile->path())));
}
_pSocket->setBlocking(false);
return static_cast<int>(_pSocket->impl()->sockfd());
}
std::unique_ptr<TemporaryFile> _pSockFile;
#else // no unix socket, listen on localhost
int eventfd()
int eventfd(int, int)
{
static const SocketAddress eventSA("127.0.0.238"s, 0);
if (!_pEventSocket)
{
if (!_pSocket)
_pSocket.reset(new ServerSocket(SocketAddress("127.0.0.1", 0)));
_port = _pSocket->address().port();
_pSocket->setBlocking(false);
return static_cast<int>(_pSocket->impl()->sockfd());
_pEventSocket.reset(new DatagramSocket(eventSA, true));
_pEventSocket->setBlocking(false);
}
int _port = 0;
#endif // POCO_HAS_UNIX_SOCKET
return static_cast<int>(_pEventSocket->impl()->sockfd());
}

std::unique_ptr<ServerSocket> _pSocket;
std::unique_ptr<DatagramSocket> _pEventSocket;
#endif // WEPOLL_H_

mutable Mutex _mutex;
Expand All @@ -353,8 +334,10 @@ class PollSetImpl
EPollHandle _epollfd;
};


const epoll_event PollSetImpl::EPOLL_NULL_EVENT = {0, {0}};


#elif defined(POCO_HAVE_FD_POLL)


Expand Down Expand Up @@ -529,7 +512,6 @@ class PollSetImpl
}

private:

void setMode(short& target, int mode)
{
if (mode & PollSet::POLL_READ)
Expand Down

0 comments on commit 45d0b25

Please sign in to comment.