[zeromq-dev] PATCH: zmq::signaler_t should not assert on EINTR
Martin Lucina
mato at kotelna.sk
Thu Aug 5 17:51:50 CEST 2010
Hi,
I've encountered a situation where zmq::signaler_t asserts due to the
recv() or send() returning with EINTR. This happens for example when I use
^C to exit some test programs.
The following patch fixes this by restarting the system calls when EINTR is
received. Martin, are you ok with the patch and behaviour? I cover both the
AIX/HPUX and default case, Win32 is not relevant since WSAEINTR does not
occur according to the docs in what seems to be a situation where we would
want to restart the call:
WSAEINTR: Interrupted function call.
A blocking operation was interrupted by a call to WSACancelBlockingCall.
Now there is one thing left which is that when my application handles
SIGINT and attempts to correctly close all sockets and do a zmq_term(), I
occasionally get the following assertion during the close():
Assertion failed: !more || pipes [current] != pipe_ (lb.cpp:48)
I'm assuming that this happens becase the socket that is being closed had
been left by the application in a bogus state where it started sending a
multipart message but did not finish it. Martin, is this correct?
-mato
diff --git a/src/signaler.cpp b/src/signaler.cpp
index 592688b..b2055bf 100644
--- a/src/signaler.cpp
+++ b/src/signaler.cpp
@@ -176,7 +176,10 @@ zmq::signaler_t::~signaler_t ()
void zmq::signaler_t::send (const command_t &cmd_)
{
- ssize_t nbytes = send (w, &cmd_, sizeof (command_t), 0);
+ ssize_t nbytes;
+ do {
+ ::send (w, &cmd_, sizeof (command_t), 0);
+ } while (nbytes == -1 && errno == EINTR);
errno_assert (nbytes != -1);
zmq_assert (nbytes == sizeof (command_t));
}
@@ -194,7 +197,10 @@ bool zmq::signaler_t::recv (command_t &cmd_, bool block_)
}
bool result;
- ssize_t nbytes = recv (r, buffer, sizeof (command_t), 0);
+ ssize_t nbytes;
+ do {
+ nbytes = ::recv (r, buffer, sizeof (command_t), 0);
+ } while (nbytes == -1 && errno == EINTR);
if (nbytes == -1 && errno == EAGAIN) {
result = false;
}
@@ -249,7 +255,10 @@ void zmq::signaler_t::send (const command_t &cmd_)
{
// TODO: Note that send is a blocking operation.
// How should we behave if the command cannot be written to the signaler?
- ssize_t nbytes = ::send (w, &cmd_, sizeof (command_t), 0);
+ ssize_t nbytes;
+ do {
+ nbytes = ::send (w, &cmd_, sizeof (command_t), 0);
+ } while (nbytes == -1 && errno == EINTR);
errno_assert (nbytes != -1);
// This should never happen as we've already checked that command size is
@@ -259,8 +268,11 @@ void zmq::signaler_t::send (const command_t &cmd_)
bool zmq::signaler_t::recv (command_t *cmd_, bool block_)
{
- ssize_t nbytes = ::recv (r, cmd_, sizeof (command_t),
- block_ ? 0 : MSG_DONTWAIT);
+ ssize_t nbytes;
+ do {
+ nbytes = ::recv (r, cmd_, sizeof (command_t),
+ block_ ? 0 : MSG_DONTWAIT);
+ } while (nbytes == -1 && errno == EINTR);
// If there's no signal available return false.
if (nbytes == -1 && errno == EAGAIN)
More information about the zeromq-dev
mailing list