Commit 7c0efcb5 authored by Simon Giesecke's avatar Simon Giesecke

Problem: huge stack allocation in Windows select code

Solution: use fast_vector_t as in poll implementation
parent 2533ffed
...@@ -853,6 +853,31 @@ static size_t valid_pollset_bytes (const fd_set &pollset_) ...@@ -853,6 +853,31 @@ static size_t valid_pollset_bytes (const fd_set &pollset_)
return sizeof (fd_set); return sizeof (fd_set);
#endif #endif
} }
#if defined ZMQ_HAVE_WINDOWS
class optimized_fd_set_t
{
public:
optimized_fd_set_t (size_t nevents_) : _fd_set (nevents_) {}
fd_set *get () { return reinterpret_cast<fd_set *> (&_fd_set[0]); }
private:
fast_vector_t<char, sizeof (u_int) + ZMQ_POLLITEMS_DFLT * sizeof (SOCKET)>
_fd_set;
};
#else
class optimized_fd_set_t
{
public:
optimized_fd_set_t (size_t /*nevents_*/) {}
fd_set *get () { return &_fd_set; }
private:
fd_set _fd_set;
};
#endif
#endif #endif
#endif #endif
...@@ -924,12 +949,12 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_) ...@@ -924,12 +949,12 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
// TODO since this function is called by a client, we could return errno EINVAL/ENOMEM/... here // TODO since this function is called by a client, we could return errno EINVAL/ENOMEM/... here
zmq_assert (nitems_ <= FD_SETSIZE); zmq_assert (nitems_ <= FD_SETSIZE);
fd_set pollset_in; optimized_fd_set_t pollset_in (nitems_);
FD_ZERO (&pollset_in); FD_ZERO (pollset_in.get ());
fd_set pollset_out; optimized_fd_set_t pollset_out (nitems_);
FD_ZERO (&pollset_out); FD_ZERO (pollset_out.get ());
fd_set pollset_err; optimized_fd_set_t pollset_err (nitems_);
FD_ZERO (&pollset_err); FD_ZERO (pollset_err.get ());
zmq::fd_t maxfd = 0; zmq::fd_t maxfd = 0;
...@@ -945,7 +970,7 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_) ...@@ -945,7 +970,7 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
== -1) == -1)
return -1; return -1;
if (items_[i].events) { if (items_[i].events) {
FD_SET (notify_fd, &pollset_in); FD_SET (notify_fd, pollset_in.get ());
if (maxfd < notify_fd) if (maxfd < notify_fd)
maxfd = notify_fd; maxfd = notify_fd;
} }
...@@ -954,17 +979,19 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_) ...@@ -954,17 +979,19 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
// events to the appropriate fd_sets. // events to the appropriate fd_sets.
else { else {
if (items_[i].events & ZMQ_POLLIN) if (items_[i].events & ZMQ_POLLIN)
FD_SET (items_[i].fd, &pollset_in); FD_SET (items_[i].fd, pollset_in.get ());
if (items_[i].events & ZMQ_POLLOUT) if (items_[i].events & ZMQ_POLLOUT)
FD_SET (items_[i].fd, &pollset_out); FD_SET (items_[i].fd, pollset_out.get ());
if (items_[i].events & ZMQ_POLLERR) if (items_[i].events & ZMQ_POLLERR)
FD_SET (items_[i].fd, &pollset_err); FD_SET (items_[i].fd, pollset_err.get ());
if (maxfd < items_[i].fd) if (maxfd < items_[i].fd)
maxfd = items_[i].fd; maxfd = items_[i].fd;
} }
} }
fd_set inset, outset, errset; optimized_fd_set_t inset (nitems_);
optimized_fd_set_t outset (nitems_);
optimized_fd_set_t errset (nitems_);
#endif #endif
bool first_pass = true; bool first_pass = true;
...@@ -1041,18 +1068,23 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_) ...@@ -1041,18 +1068,23 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
// Wait for events. Ignore interrupts if there's infinite timeout. // Wait for events. Ignore interrupts if there's infinite timeout.
while (true) { while (true) {
memcpy (&inset, &pollset_in, valid_pollset_bytes (pollset_in)); memcpy (inset.get (), pollset_in.get (),
memcpy (&outset, &pollset_out, valid_pollset_bytes (pollset_out)); valid_pollset_bytes (*pollset_in.get ()));
memcpy (&errset, &pollset_err, valid_pollset_bytes (pollset_err)); memcpy (outset.get (), pollset_out.get (),
valid_pollset_bytes (*pollset_out.get ()));
memcpy (errset.get (), pollset_err.get (),
valid_pollset_bytes (*pollset_err.get ()));
#if defined ZMQ_HAVE_WINDOWS #if defined ZMQ_HAVE_WINDOWS
int rc = select (0, &inset, &outset, &errset, ptimeout); int rc =
select (0, inset.get (), outset.get (), errset.get (), ptimeout);
if (unlikely (rc == SOCKET_ERROR)) { if (unlikely (rc == SOCKET_ERROR)) {
errno = zmq::wsa_error_to_errno (WSAGetLastError ()); errno = zmq::wsa_error_to_errno (WSAGetLastError ());
wsa_assert (errno == ENOTSOCK); wsa_assert (errno == ENOTSOCK);
return -1; return -1;
} }
#else #else
int rc = select (maxfd + 1, &inset, &outset, &errset, ptimeout); int rc = select (maxfd + 1, inset.get (), outset.get (),
errset.get (), ptimeout);
if (unlikely (rc == -1)) { if (unlikely (rc == -1)) {
errno_assert (errno == EINTR || errno == EBADF); errno_assert (errno == EINTR || errno == EBADF);
return -1; return -1;
...@@ -1084,11 +1116,11 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_) ...@@ -1084,11 +1116,11 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
// Else, the poll item is a raw file descriptor, simply convert // Else, the poll item is a raw file descriptor, simply convert
// the events to zmq_pollitem_t-style format. // the events to zmq_pollitem_t-style format.
else { else {
if (FD_ISSET (items_[i].fd, &inset)) if (FD_ISSET (items_[i].fd, inset.get ()))
items_[i].revents |= ZMQ_POLLIN; items_[i].revents |= ZMQ_POLLIN;
if (FD_ISSET (items_[i].fd, &outset)) if (FD_ISSET (items_[i].fd, outset.get ()))
items_[i].revents |= ZMQ_POLLOUT; items_[i].revents |= ZMQ_POLLOUT;
if (FD_ISSET (items_[i].fd, &errset)) if (FD_ISSET (items_[i].fd, errset.get ()))
items_[i].revents |= ZMQ_POLLERR; items_[i].revents |= ZMQ_POLLERR;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment