Commit 8e21bc0b authored by Pieter Hintjens's avatar Pieter Hintjens

Merge pull request #747 from hurtonm/master

Signal that the peer performed orderly shutdown
parents e66b42f3 05d59628
...@@ -217,17 +217,22 @@ void zmq::stream_engine_t::in_event () ...@@ -217,17 +217,22 @@ void zmq::stream_engine_t::in_event ()
// Note that buffer can be arbitrarily large. However, we assume // Note that buffer can be arbitrarily large. However, we assume
// the underlying TCP layer has fixed buffer size and thus the // the underlying TCP layer has fixed buffer size and thus the
// number of bytes read will be always limited. // number of bytes read will be always limited.
decoder->get_buffer (&inpos, &insize); size_t bufsize = 0;
const int bytes_read = read (inpos, insize); decoder->get_buffer (&inpos, &bufsize);
// Check whether the peer has closed the connection. int const rc = read (inpos, bufsize);
if (bytes_read == -1) { if (rc == 0) {
error (); error ();
return; return;
} }
if (rc == -1) {
if (errno != EAGAIN)
error ();
return;
}
// Adjust input size // Adjust input size
insize = static_cast <size_t> (bytes_read); insize = static_cast <size_t> (rc);
} }
int rc = 0; int rc = 0;
...@@ -396,12 +401,15 @@ bool zmq::stream_engine_t::handshake () ...@@ -396,12 +401,15 @@ bool zmq::stream_engine_t::handshake ()
while (greeting_bytes_read < greeting_size) { while (greeting_bytes_read < greeting_size) {
const int n = read (greeting_recv + greeting_bytes_read, const int n = read (greeting_recv + greeting_bytes_read,
greeting_size - greeting_bytes_read); greeting_size - greeting_bytes_read);
if (n == -1) { if (n == 0) {
error (); error ();
return false; return false;
} }
if (n == 0) if (n == -1) {
if (errno != EAGAIN)
error ();
return false; return false;
}
greeting_bytes_read += n; greeting_bytes_read += n;
...@@ -792,58 +800,45 @@ int zmq::stream_engine_t::read (void *data_, size_t size_) ...@@ -792,58 +800,45 @@ int zmq::stream_engine_t::read (void *data_, size_t size_)
{ {
#ifdef ZMQ_HAVE_WINDOWS #ifdef ZMQ_HAVE_WINDOWS
int nbytes = recv (s, (char*) data_, (int) size_, 0); const int rc = recv (s, (char*) data_, (int) size_, 0);
// If not a single byte can be read from the socket in non-blocking mode // If not a single byte can be read from the socket in non-blocking mode
// we'll get an error (this may happen during the speculative read). // we'll get an error (this may happen during the speculative read).
if (nbytes == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK) if (rc == SOCKET_ERROR) {
return 0; if (WSAGetLastError () == WSAEWOULDBLOCK)
errno = EAGAIN;
// Connection failure. else {
if (nbytes == SOCKET_ERROR && ( wsa_assert (WSAGetLastError () == WSAENETDOWN
WSAGetLastError () == WSAENETDOWN || || WSAGetLastError () == WSAENETRESET
WSAGetLastError () == WSAENETRESET || || WSAGetLastError () == WSAECONNABORTED
WSAGetLastError () == WSAECONNABORTED || || WSAGetLastError () == WSAETIMEDOUT
WSAGetLastError () == WSAETIMEDOUT || || WSAGetLastError () == WSAECONNRESET
WSAGetLastError () == WSAECONNRESET || || WSAGetLastError () == WSAECONNREFUSED
WSAGetLastError () == WSAECONNREFUSED || || WSAGetLastError () == WSAENOTCONN);
WSAGetLastError () == WSAENOTCONN)) errno = wsa_error_to_errno (WSAGetLastError ());
return -1; }
}
wsa_assert (nbytes != SOCKET_ERROR);
// Orderly shutdown by the other peer.
if (nbytes == 0)
return -1;
return nbytes; return rc == SOCKET_ERROR? -1: rc;
#else #else
ssize_t nbytes = recv (s, data_, size_, 0); const ssize_t rc = recv (s, data_, size_, 0);
// Several errors are OK. When speculative read is being done we may not // Several errors are OK. When speculative read is being done we may not
// be able to read a single byte from the socket. Also, SIGSTOP issued // be able to read a single byte from the socket. Also, SIGSTOP issued
// by a debugging tool can result in EINTR error. // by a debugging tool can result in EINTR error.
if (nbytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK || if (rc == -1) {
errno == EINTR))
return 0;
// Signalise peer failure.
if (nbytes == -1) {
errno_assert (errno != EBADF errno_assert (errno != EBADF
&& errno != EFAULT && errno != EFAULT
&& errno != EINVAL && errno != EINVAL
&& errno != ENOMEM && errno != ENOMEM
&& errno != ENOTSOCK); && errno != ENOTSOCK);
return -1; if (errno == EWOULDBLOCK || errno == EINTR)
errno = EAGAIN;
} }
// Orderly shutdown by the peer. return static_cast <int> (rc);
if (nbytes == 0)
return -1;
return static_cast <int> (nbytes);
#endif #endif
} }
...@@ -87,10 +87,9 @@ namespace zmq ...@@ -87,10 +87,9 @@ namespace zmq
// of error or orderly shutdown by the other peer -1 is returned. // of error or orderly shutdown by the other peer -1 is returned.
int write (const void *data_, size_t size_); int write (const void *data_, size_t size_);
// Reads data from the socket (up to 'size' bytes). Returns the number // Reads data from the socket (up to 'size' bytes).
// of bytes actually read (even zero is to be considered to be // Returns the number of bytes actually read or -1 on error.
// a success). In case of error or orderly shutdown by the other // Zero indicates the peer has closed the connection.
// peer -1 is returned.
int read (void *data_, size_t size_); int read (void *data_, size_t size_);
int read_identity (msg_t *msg_); int read_identity (msg_t *msg_);
......
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