From f24955519ac0d3b0da5dd87fbb7bfc8cc1e24295 Mon Sep 17 00:00:00 2001 From: Martin Sustrik Date: Mon, 22 Feb 2010 18:19:26 +0100 Subject: zmq_poll doesn't exit when infinite timeout is set and interrupt occurs --- src/zmq.cpp | 56 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/src/zmq.cpp b/src/zmq.cpp index 4170b3f..1275804 100644 --- a/src/zmq.cpp +++ b/src/zmq.cpp @@ -383,11 +383,11 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_) // prevent exiting on any events that may already been signaled on // 0MQ sockets. int rc = poll (pollfds, npollfds, 0); - if (rc == -1 && errno == EINTR) { + if (rc == -1 && errno == EINTR && timeout_ >= 0) { free (pollfds); return 0; } - errno_assert (rc >= 0); + errno_assert (rc >= 0 || (rc == -1 && errno == EINTR)); int timeout = timeout_ > 0 ? timeout_ / 1000 : -1; int nevents = 0; @@ -427,15 +427,24 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_) // If there's at least one event, or if we are asked not to block, // return immediately. - if (nevents || !timeout) + if (nevents || !timeout_) break; - // Wait for events. - rc = poll (pollfds, npollfds, timeout); - if (rc == -1 && errno == EINTR) + // Wait for events. Ignore interrupts if there's infinite timeout. + while (true) { + rc = poll (pollfds, npollfds, timeout); + if (rc == -1 && errno == EINTR) { + if (timeout_ < 0) + continue; + else { + rc = 0; + break; + } + } + errno_assert (rc >= 0); break; - errno_assert (rc >= 0); - + } + // If timeout was hit with no events signaled, return zero. if (rc == 0) break; @@ -523,7 +532,9 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_) #if defined ZMQ_HAVE_WINDOWS wsa_assert (rc != SOCKET_ERROR); #else - errno_assert (rc != -1 || errno != EINTR); + if (rc == -1 && errno == EINTR && timeout_ >= 0) + return 0; + errno_assert (rc >= 0 || (rc == -1 && errno == EINTR)); #endif while (true) { @@ -562,17 +573,28 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_) if (nevents || (timeout.tv_sec == 0 && timeout.tv_usec == 0)) break; - // Wait for events. - memcpy (&inset, &pollset_in, sizeof (fd_set)); - memcpy (&outset, &pollset_out, sizeof (fd_set)); - memcpy (&errset, &pollset_err, sizeof (fd_set)); - int rc = select (maxfd, &inset, &outset, &errset, - block ? NULL : &timeout); + // Wait for events. Ignore interrupts if there's infinite timeout. + while (true) { + memcpy (&inset, &pollset_in, sizeof (fd_set)); + memcpy (&outset, &pollset_out, sizeof (fd_set)); + memcpy (&errset, &pollset_err, sizeof (fd_set)); + int rc = select (maxfd, &inset, &outset, &errset, + block ? NULL : &timeout); #if defined ZMQ_HAVE_WINDOWS - wsa_assert (rc != SOCKET_ERROR); + wsa_assert (rc != SOCKET_ERROR); #else - errno_assert (rc != -1 || errno != EINTR); + if (rc == -1 && errno == EINTR) { + if (timeout_ < 0) + continue; + else { + rc = 0; + break; + } + } + errno_assert (rc >= 0); #endif + break; + } // If timeout was hit with no events signaled, return zero. if (rc == 0) -- cgit v1.2.3