[tarantool-patches] Re: [PATCH v2 03/11] sio: remove exceptions

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Mon Dec 10 18:37:37 MSK 2018



On 09/12/2018 15:54, Vladimir Davydov wrote:
> On Wed, Dec 05, 2018 at 12:28:50AM +0300, Vladislav Shpilevoy wrote:
>> @@ -40,6 +40,14 @@
>>   #include "trivia/util.h"
>>   #include "exception.h"
>>   
>> +enum { SIO_ERROR_FATAL = -2 };
>> +
>> +bool
>> +sio_is_error_fatal(int retcode)
>> +{
>> +	return retcode == SIO_ERROR_FATAL;
>> +}
>> +
>>   /** Pretty print socket name and peer (for exceptions) */
>>   const char *
>>   sio_socketname(int fd)
>> @@ -224,9 +234,11 @@ sio_accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
>>   {
>>   	/* Accept a connection. */
>>   	int newfd = accept(fd, addr, addrlen);
>> -	if (newfd < 0 &&
>> -	    (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR))
>> -		tnt_raise(SocketError, sio_socketname(fd), "accept");
>> +	if (newfd < 0 && errno != EAGAIN && errno != EWOULDBLOCK &&
>> +	    errno != EINTR) {
>> +		diag_set(SocketError, sio_socketname(fd), "accept");
>> +		return SIO_ERROR_FATAL;
>> +	}
>>   	return newfd;
>>   }
> 
> This looks bad. It's not just my opinion. I consulted with Kostja
> verbally and he agrees with me.
> 
> Let's please set diag on any error in all sio functions and let the
> caller decide which ones are critical and which are not by checking

There is a problem - each diag increments error counter visible in
stat. But I believe you know it, so as you wish.

> errno. To simplify the caller's job we can introduce a helper function
> checking errno for cetain types of errors, say
> 
>    sio_wouldblock(errno): errno in EINTR, EAGAIN, EWOULDBLOCK
> 
> I've already suggested you to do this. Quoting your reply here:
> 
>> Any names having 'wouldblock', 'block' or describing other concrete
>> behaviour can not be used. At least, sio_bind/listen can set EADDRINUSE,
>> which is not about blocking.
> 
> Yeah, I agree, we should only use sio_wouldblock for EAGAIN, EINTR, and
> EWOULDBLOCK. Other error codes should be checked explicitly.

I do not like that 1) sio user should rely on the fact that errno is not
reset already by another function, 2) sio user sometimes checks errno
explicitly, and sometimes via calling sio_wouldblock, 3) sio_wouldblock
is applicable not only to sio. But I am sure both you and especially
Kostja know it, so as you wish.

> 
>>
>> Also, notion of 'critical' is different for various functions. I've
>> grouped errors in 4 groups:
>>
>> EINPROGRESS - sio_connect
> 
> Check (errno != EINPROGRESS) after calling sio_connect().
> 
>>
>> EADDRINUSE  - sio_bind, sio_listen
> 
> errno != EADDRINUSE
> 
>>
>> EAGAIN      - sio_accept, sio_write,
>> EWOULDBLOCK   sio_writev, sio_readn_ahead,
>> EINTR         sio_sendto, sio_recvfrom
> 
> sio_wouldblock(errno)
> 
>>
>> ECONNRESET  - sio_read
>> EAGAIN
>> EWOULDBLOCK
>> EINTR
> 
> Actually, sio_read() never returns ECONNRESET - it treats it as EOF
> (i.e. returns 0) and doesn't raise an error. So for sio_read(), the
> caller can use sio_wouldblock() as well.
> 

If you say so.

Diff is right below. The whole patch follows the diff.

diff --git a/src/box/iproto.cc b/src/box/iproto.cc
index fe42bb250..108bb8665 100644
--- a/src/box/iproto.cc
+++ b/src/box/iproto.cc
@@ -859,7 +859,7 @@ iproto_connection_on_input(ev_loop *loop, struct ev_io *watcher,
  		/* Read input. */
  		int nrd = sio_read(fd, in->wpos, ibuf_unused(in));
  		if (nrd < 0) {                  /* Socket is not ready. */
-			if (sio_is_error_fatal(nrd))
+			if (! sio_wouldblock(errno))
  				diag_raise();
  			ev_io_start(loop, &con->input);
  			return;
@@ -938,7 +938,7 @@ iproto_flush(struct iproto_connection *con)
  		begin->iov_len = advance == 0 ? begin->iov_len + offset: offset;
  		begin->pos += advance;
  		assert(begin->pos <= end->pos);
-	} else if (sio_is_error_fatal(nwr)) {
+	} else if (! sio_wouldblock(errno)) {
  		diag_raise();
  	}
  	return -1;
@@ -1766,7 +1766,7 @@ net_send_greeting(struct cmsg *m)
  					 obuf_iovcnt(out));
  		if (nwr > 0)
  			rmean_collect(rmean_net, IPROTO_SENT, nwr);
-		else if (sio_is_error_fatal(nwr))
+		else if (! sio_wouldblock(errno))
  			diag_log();
  		assert(iproto_connection_is_idle(con));
  		iproto_connection_close(con);
diff --git a/src/coio.cc b/src/coio.cc
index a546f647d..18baa5444 100644
--- a/src/coio.cc
+++ b/src/coio.cc
@@ -35,6 +35,7 @@
  #include <netinet/tcp.h>
  #include <stdio.h>
  #include <arpa/inet.h>
+#include <errno.h>
  
  #include "sio.h"
  #include "scoped_guard.h"
@@ -258,7 +259,7 @@ coio_accept(struct ev_io *coio, struct sockaddr *addr,
  					       SOCK_STREAM);
  			return fd;
  		}
-		if (sio_is_error_fatal(fd))
+		if (! sio_wouldblock(errno))
  			diag_raise();
  		/* The socket is not ready, yield */
  		if (! ev_is_active(coio)) {
@@ -315,7 +316,7 @@ coio_read_ahead_timeout(struct ev_io *coio, void *buf, size_t sz,
  		} else if (nrd == 0) {
  			errno = 0;
  			return sz - to_read;
-		} else if (sio_is_error_fatal(nrd)) {
+		} else if (! sio_wouldblock(errno)) {
  			diag_raise();
  		}
  
@@ -408,7 +409,7 @@ coio_write_timeout(struct ev_io *coio, const void *buf, size_t sz,
  				return sz;
  			towrite -= nwr;
  			buf = (char *) buf + nwr;
-		} else if (sio_is_error_fatal(nwr)) {
+		} else if (! sio_wouldblock(errno)) {
  			diag_raise();
  		}
  		if (! ev_is_active(coio)) {
@@ -442,7 +443,7 @@ coio_flush(int fd, struct iovec *iov, ssize_t offset, int iovcnt)
  	sio_add_to_iov(iov, -offset);
  	ssize_t nwr = sio_writev(fd, iov, iovcnt);
  	sio_add_to_iov(iov, offset);
-	if (nwr < 0 && sio_is_error_fatal(nwr))
+	if (nwr < 0 && ! sio_wouldblock(errno))
  		diag_raise();
  	return nwr;
  }
@@ -524,7 +525,7 @@ coio_sendto_timeout(struct ev_io *coio, const void *buf, size_t sz, int flags,
  					 flags, dest_addr, addrlen);
  		if (nwr > 0)
  			return nwr;
-		if (sio_is_error_fatal(nwr))
+		if (! sio_wouldblock(errno))
  			diag_raise();
  		if (! ev_is_active(coio)) {
  			ev_io_set(coio, coio->fd, EV_WRITE);
@@ -569,7 +570,7 @@ coio_recvfrom_timeout(struct ev_io *coio, void *buf, size_t sz, int flags,
  					   src_addr, &addrlen);
  		if (nrd >= 0)
  			return nrd;
-		if (sio_is_error_fatal(nrd))
+		if (! sio_wouldblock(errno))
  			diag_raise();
  		if (! ev_is_active(coio)) {
  			ev_io_set(coio, coio->fd, EV_READ);
diff --git a/src/evio.cc b/src/evio.cc
index 32aece0f0..55968f351 100644
--- a/src/evio.cc
+++ b/src/evio.cc
@@ -185,7 +185,7 @@ evio_service_accept_cb(ev_loop * /* loop */, ev_io *watcher,
  				(struct sockaddr *)&addr, &addrlen);
  
  			if (fd < 0) {
-				if (sio_is_error_fatal(fd))
+				if (! sio_wouldblock(errno))
  					diag_raise();
  				return;
  			}
@@ -262,20 +262,13 @@ evio_service_bind_addr(struct evio_service *service)
  
  	evio_setsockopt_server(fd, service->addr.sa_family, SOCK_STREAM);
  
-	int rc = sio_bind(fd, &service->addr, service->addr_len);
-	if (rc != 0) {
-		if (sio_is_error_fatal(rc))
+	if (sio_bind(fd, &service->addr, service->addr_len) != 0) {
+		if (errno != EADDRINUSE)
  			diag_raise();
  		if (evio_service_reuse_addr(service, fd))
  			diag_raise();
-		rc = sio_bind(fd, &service->addr, service->addr_len);
-		if (rc != 0) {
-			if (! sio_is_error_fatal(rc)) {
-				diag_set(SocketError, sio_socketname(fd),
-					 "bind");
-			}
+		if (sio_bind(fd, &service->addr, service->addr_len) != 0)
  			diag_raise();
-		}
  	}
  
  	say_info("%s: bound to %s", evio_service_name(service),
diff --git a/src/sio.cc b/src/sio.cc
index 6ca2f4802..125464192 100644
--- a/src/sio.cc
+++ b/src/sio.cc
@@ -41,12 +41,10 @@
  #include "trivia/util.h"
  #include "exception.h"
  
-enum { SIO_ERROR_FATAL = -2 };
-
  bool
-sio_is_error_fatal(int retcode)
+sio_wouldblock(int err)
  {
-	return retcode == SIO_ERROR_FATAL;
+	return err == EAGAIN || err == EWOULDBLOCK || err == EINTR;
  }
  
  /** Pretty print socket name and peer (for exceptions) */
@@ -200,7 +198,7 @@ sio_connect(int fd, struct sockaddr *addr, socklen_t addrlen)
  {
  	/* Establish the connection. */
  	int rc = connect(fd, (struct sockaddr *) addr, addrlen);
-	if (rc < 0 && errno != EINPROGRESS) {
+	if (rc < 0) {
  		diag_set(SocketError, sio_socketname(fd), "connect to %s",
  			 sio_strfaddr((struct sockaddr *)addr, addrlen));
  	}
@@ -212,7 +210,7 @@ int
  sio_bind(int fd, struct sockaddr *addr, socklen_t addrlen)
  {
  	int rc = bind(fd, addr, addrlen);
-	if (rc < 0 && errno != EADDRINUSE)
+	if (rc < 0)
  		diag_set(SocketError, sio_socketname(fd), "bind");
  	return rc;
  }
@@ -222,10 +220,8 @@ int
  sio_listen(int fd)
  {
  	int rc = listen(fd, sio_listen_backlog());
-	if (rc < 0) {
+	if (rc < 0)
  		diag_set(SocketError, sio_socketname(fd), "listen");
-		return SIO_ERROR_FATAL;
-	}
  	return rc;
  }
  
@@ -235,11 +231,8 @@ sio_accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
  {
  	/* Accept a connection. */
  	int newfd = accept(fd, addr, addrlen);
-	if (newfd < 0 && errno != EAGAIN && errno != EWOULDBLOCK &&
-	    errno != EINTR) {
+	if (newfd < 0)
  		diag_set(SocketError, sio_socketname(fd), "accept");
-		return SIO_ERROR_FATAL;
-	}
  	return newfd;
  }
  
@@ -249,26 +242,18 @@ sio_read(int fd, void *buf, size_t count)
  {
  	ssize_t n = read(fd, buf, count);
  	if (n < 0) {
-		if (errno == EWOULDBLOCK)
-			errno = EINTR;
-		switch (errno) {
-		case EAGAIN:
-		case EINTR:
-			break;
  		/*
  		 * Happens typically when the client closes
  		 * socket on timeout without reading the previous
  		 * query's response completely. Treat the same as
  		 * EOF.
  		 */
-		case ECONNRESET:
+		if (errno == ECONNRESET) {
  			errno = 0;
  			n = 0;
-			break;
-		default:
+		} else {
  			diag_set(SocketError, sio_socketname(fd), "read(%zd)",
  				 count);
-			return SIO_ERROR_FATAL;
  		}
  	}
  	return n;
@@ -279,11 +264,8 @@ ssize_t
  sio_write(int fd, const void *buf, size_t count)
  {
  	ssize_t n = write(fd, buf, count);
-	if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK &&
-	    errno != EINTR) {
+	if (n < 0)
  		diag_set(SocketError, sio_socketname(fd), "write(%zd)", count);
-		return SIO_ERROR_FATAL;
-	}
  	return n;
  }
  
@@ -293,11 +275,8 @@ sio_writev(int fd, const struct iovec *iov, int iovcnt)
  {
  	int cnt = iovcnt < IOV_MAX ? iovcnt : IOV_MAX;
  	ssize_t n = writev(fd, iov, cnt);
-	if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK &&
-	    errno != EINTR) {
+	if (n < 0)
  		diag_set(SocketError, sio_socketname(fd), "writev(%d)", iovcnt);
-		return SIO_ERROR_FATAL;
-	}
  	return n;
  }
  
@@ -308,11 +287,8 @@ sio_sendto(int fd, const void *buf, size_t len, int flags,
  {
  	ssize_t n = sendto(fd, buf, len, flags, (struct sockaddr*)dest_addr,
  	                   addrlen);
-	if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK &&
-	    errno != EINTR) {
+	if (n < 0)
  		diag_set(SocketError, sio_socketname(fd), "sendto(%zd)", len);
-		return SIO_ERROR_FATAL;
-	}
  	return n;
  }
  
@@ -323,11 +299,8 @@ sio_recvfrom(int fd, void *buf, size_t len, int flags,
  {
  	ssize_t n = recvfrom(fd, buf, len, flags, (struct sockaddr*)src_addr,
  	                     addrlen);
-	if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK &&
-	    errno != EINTR) {
+	if (n < 0)
  		diag_set(SocketError, sio_socketname(fd), "recvfrom(%zd)", len);
-		return SIO_ERROR_FATAL;
-	}
  	return n;
  }
  
diff --git a/src/sio.h b/src/sio.h
index 5d12f35f9..864fa16d9 100644
--- a/src/sio.h
+++ b/src/sio.h
@@ -49,11 +49,11 @@ extern "C" {
  enum { SERVICE_NAME_MAXLEN = 32 };
  
  /**
- * Check if a code, returned from a sio function, means a
- * critical error.
+ * Check if an errno, returned from a sio function, means a
+ * non-critical error: EAGAIN, EWOULDBLOCK, EINTR.
   */
  bool
-sio_is_error_fatal(int retcode);
+sio_wouldblock(int err);
  
  const char *
  sio_strfaddr(struct sockaddr *addr, socklen_t addrlen);


========================================================================

Whole patch:

========================================================================

commit 6c901a731d5c7d63c31a36858e32052c7e94c57f
Author: Vladislav Shpilevoy <v.shpilevoy at tarantool.org>
Date:   Tue Dec 4 20:08:54 2018 +0300

     sio: remove exceptions
     
     To turn sio into C it should not have exceptions.
     Replace them with diagnostics setting. In some cases
     errors are not critical so several functions can be
     retried or called with another arguments. To check if
     an error was not critical, a user's code can look at
     errno or check errno via sio_wouldblock() which checks
     EINTR, EWOULDBLOCK, EAGAIN.
     
     Needed for #3234

diff --git a/src/box/iproto.cc b/src/box/iproto.cc
index 7c11d05b3..108bb8665 100644
--- a/src/box/iproto.cc
+++ b/src/box/iproto.cc
@@ -859,6 +859,8 @@ iproto_connection_on_input(ev_loop *loop, struct ev_io *watcher,
  		/* Read input. */
  		int nrd = sio_read(fd, in->wpos, ibuf_unused(in));
  		if (nrd < 0) {                  /* Socket is not ready. */
+			if (! sio_wouldblock(errno))
+				diag_raise();
  			ev_io_start(loop, &con->input);
  			return;
  		}
@@ -923,10 +925,8 @@ iproto_flush(struct iproto_connection *con)
  	iov[iovcnt-1].iov_len = end->iov_len - begin->iov_len * (iovcnt == 1);
  
  	ssize_t nwr = sio_writev(fd, iov, iovcnt);
-
-	/* Count statistics */
-	rmean_collect(rmean_net, IPROTO_SENT, nwr);
  	if (nwr > 0) {
+		rmean_collect(rmean_net, IPROTO_SENT, nwr);
  		if (begin->used + nwr == end->used) {
  			*begin = *end;
  			return 0;
@@ -938,6 +938,8 @@ iproto_flush(struct iproto_connection *con)
  		begin->iov_len = advance == 0 ? begin->iov_len + offset: offset;
  		begin->pos += advance;
  		assert(begin->pos <= end->pos);
+	} else if (! sio_wouldblock(errno)) {
+		diag_raise();
  	}
  	return -1;
  }
@@ -1760,15 +1762,12 @@ net_send_greeting(struct cmsg *m)
  	struct iproto_connection *con = msg->connection;
  	if (msg->close_connection) {
  		struct obuf *out = msg->wpos.obuf;
-		try {
-			int64_t nwr = sio_writev(con->output.fd, out->iov,
-						 obuf_iovcnt(out));
-
-			/* Count statistics */
+		int64_t nwr = sio_writev(con->output.fd, out->iov,
+					 obuf_iovcnt(out));
+		if (nwr > 0)
  			rmean_collect(rmean_net, IPROTO_SENT, nwr);
-		} catch (Exception *e) {
-			e->log();
-		}
+		else if (! sio_wouldblock(errno))
+			diag_log();
  		assert(iproto_connection_is_idle(con));
  		iproto_connection_close(con);
  		iproto_msg_delete(msg);
diff --git a/src/coio.cc b/src/coio.cc
index e91de40b5..18baa5444 100644
--- a/src/coio.cc
+++ b/src/coio.cc
@@ -35,6 +35,7 @@
  #include <netinet/tcp.h>
  #include <stdio.h>
  #include <arpa/inet.h>
+#include <errno.h>
  
  #include "sio.h"
  #include "scoped_guard.h"
@@ -258,6 +259,8 @@ coio_accept(struct ev_io *coio, struct sockaddr *addr,
  					       SOCK_STREAM);
  			return fd;
  		}
+		if (! sio_wouldblock(errno))
+			diag_raise();
  		/* The socket is not ready, yield */
  		if (! ev_is_active(coio)) {
  			ev_io_set(coio, coio->fd, EV_READ);
@@ -313,6 +316,8 @@ coio_read_ahead_timeout(struct ev_io *coio, void *buf, size_t sz,
  		} else if (nrd == 0) {
  			errno = 0;
  			return sz - to_read;
+		} else if (! sio_wouldblock(errno)) {
+			diag_raise();
  		}
  
  		/* The socket is not ready, yield */
@@ -404,6 +409,8 @@ coio_write_timeout(struct ev_io *coio, const void *buf, size_t sz,
  				return sz;
  			towrite -= nwr;
  			buf = (char *) buf + nwr;
+		} else if (! sio_wouldblock(errno)) {
+			diag_raise();
  		}
  		if (! ev_is_active(coio)) {
  			ev_io_set(coio, coio->fd, EV_WRITE);
@@ -433,15 +440,11 @@ coio_write_timeout(struct ev_io *coio, const void *buf, size_t sz,
  static inline ssize_t
  coio_flush(int fd, struct iovec *iov, ssize_t offset, int iovcnt)
  {
-	ssize_t nwr;
-	try {
-		sio_add_to_iov(iov, -offset);
-		nwr = sio_writev(fd, iov, iovcnt);
-		sio_add_to_iov(iov, offset);
-	} catch (SocketError *e) {
-		sio_add_to_iov(iov, offset);
-		throw;
-	}
+	sio_add_to_iov(iov, -offset);
+	ssize_t nwr = sio_writev(fd, iov, iovcnt);
+	sio_add_to_iov(iov, offset);
+	if (nwr < 0 && ! sio_wouldblock(errno))
+		diag_raise();
  	return nwr;
  }
  
@@ -522,6 +525,8 @@ coio_sendto_timeout(struct ev_io *coio, const void *buf, size_t sz, int flags,
  					 flags, dest_addr, addrlen);
  		if (nwr > 0)
  			return nwr;
+		if (! sio_wouldblock(errno))
+			diag_raise();
  		if (! ev_is_active(coio)) {
  			ev_io_set(coio, coio->fd, EV_WRITE);
  			ev_io_start(loop(), coio);
@@ -565,7 +570,8 @@ coio_recvfrom_timeout(struct ev_io *coio, void *buf, size_t sz, int flags,
  					   src_addr, &addrlen);
  		if (nrd >= 0)
  			return nrd;
-
+		if (! sio_wouldblock(errno))
+			diag_raise();
  		if (! ev_is_active(coio)) {
  			ev_io_set(coio, coio->fd, EV_READ);
  			ev_io_start(loop(), coio);
diff --git a/src/evio.cc b/src/evio.cc
index a6ac65daf..55968f351 100644
--- a/src/evio.cc
+++ b/src/evio.cc
@@ -184,8 +184,11 @@ evio_service_accept_cb(ev_loop * /* loop */, ev_io *watcher,
  			fd = sio_accept(service->ev.fd,
  				(struct sockaddr *)&addr, &addrlen);
  
-			if (fd < 0) /* EAGAIN, EWOULDLOCK, EINTR */
+			if (fd < 0) {
+				if (! sio_wouldblock(errno))
+					diag_raise();
  				return;
+			}
  			/* set common client socket options */
  			evio_setsockopt_client(fd, service->addr.sa_family, SOCK_STREAM);
  			/*
@@ -259,18 +262,13 @@ evio_service_bind_addr(struct evio_service *service)
  
  	evio_setsockopt_server(fd, service->addr.sa_family, SOCK_STREAM);
  
-	if (sio_bind(fd, &service->addr, service->addr_len)) {
+	if (sio_bind(fd, &service->addr, service->addr_len) != 0) {
  		if (errno != EADDRINUSE)
  			diag_raise();
  		if (evio_service_reuse_addr(service, fd))
  			diag_raise();
-		if (sio_bind(fd, &service->addr, service->addr_len)) {
-			if (errno == EADDRINUSE) {
-				diag_set(SocketError, sio_socketname(fd),
-					 "bind");
-			}
+		if (sio_bind(fd, &service->addr, service->addr_len) != 0)
  			diag_raise();
-		}
  	}
  
  	say_info("%s: bound to %s", evio_service_name(service),
@@ -294,10 +292,8 @@ evio_service_listen(struct evio_service *service)
  		  sio_strfaddr(&service->addr, service->addr_len));
  
  	int fd = service->ev.fd;
-	if (sio_listen(fd)) {
-		/* raise for addr in use to */
-		tnt_raise(SocketError, sio_socketname(fd), "listen");
-	}
+	if (sio_listen(fd) != 0)
+		diag_raise();
  	ev_io_start(service->loop, &service->ev);
  }
  
diff --git a/src/sio.cc b/src/sio.cc
index f2e103460..125464192 100644
--- a/src/sio.cc
+++ b/src/sio.cc
@@ -41,6 +41,12 @@
  #include "trivia/util.h"
  #include "exception.h"
  
+bool
+sio_wouldblock(int err)
+{
+	return err == EAGAIN || err == EWOULDBLOCK || err == EINTR;
+}
+
  /** Pretty print socket name and peer (for exceptions) */
  const char *
  sio_socketname(int fd)
@@ -192,7 +198,7 @@ sio_connect(int fd, struct sockaddr *addr, socklen_t addrlen)
  {
  	/* Establish the connection. */
  	int rc = connect(fd, (struct sockaddr *) addr, addrlen);
-	if (rc < 0 && errno != EINPROGRESS) {
+	if (rc < 0) {
  		diag_set(SocketError, sio_socketname(fd), "connect to %s",
  			 sio_strfaddr((struct sockaddr *)addr, addrlen));
  	}
@@ -204,7 +210,7 @@ int
  sio_bind(int fd, struct sockaddr *addr, socklen_t addrlen)
  {
  	int rc = bind(fd, addr, addrlen);
-	if (rc < 0 && errno != EADDRINUSE)
+	if (rc < 0)
  		diag_set(SocketError, sio_socketname(fd), "bind");
  	return rc;
  }
@@ -214,8 +220,8 @@ int
  sio_listen(int fd)
  {
  	int rc = listen(fd, sio_listen_backlog());
-	if (rc < 0 && errno != EADDRINUSE)
-		tnt_raise(SocketError, sio_socketname(fd), "listen");
+	if (rc < 0)
+		diag_set(SocketError, sio_socketname(fd), "listen");
  	return rc;
  }
  
@@ -225,9 +231,8 @@ sio_accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
  {
  	/* Accept a connection. */
  	int newfd = accept(fd, addr, addrlen);
-	if (newfd < 0 &&
-	    (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR))
-		tnt_raise(SocketError, sio_socketname(fd), "accept");
+	if (newfd < 0)
+		diag_set(SocketError, sio_socketname(fd), "accept");
  	return newfd;
  }
  
@@ -237,25 +242,18 @@ sio_read(int fd, void *buf, size_t count)
  {
  	ssize_t n = read(fd, buf, count);
  	if (n < 0) {
-		if (errno == EWOULDBLOCK)
-			errno = EINTR;
-		switch (errno) {
-		case EAGAIN:
-		case EINTR:
-			break;
  		/*
  		 * Happens typically when the client closes
  		 * socket on timeout without reading the previous
  		 * query's response completely. Treat the same as
  		 * EOF.
  		 */
-		case ECONNRESET:
+		if (errno == ECONNRESET) {
  			errno = 0;
  			n = 0;
-			break;
-		default:
-			tnt_raise(SocketError, sio_socketname(fd),
-				  "read(%zd)", count);
+		} else {
+			diag_set(SocketError, sio_socketname(fd), "read(%zd)",
+				 count);
  		}
  	}
  	return n;
@@ -266,10 +264,8 @@ ssize_t
  sio_write(int fd, const void *buf, size_t count)
  {
  	ssize_t n = write(fd, buf, count);
-	if (n < 0 && errno != EAGAIN &&
-	    errno != EWOULDBLOCK && errno != EINTR)
-			tnt_raise(SocketError, sio_socketname(fd),
-				  "write(%zd)", count);
+	if (n < 0)
+		diag_set(SocketError, sio_socketname(fd), "write(%zd)", count);
  	return n;
  }
  
@@ -279,11 +275,8 @@ sio_writev(int fd, const struct iovec *iov, int iovcnt)
  {
  	int cnt = iovcnt < IOV_MAX ? iovcnt : IOV_MAX;
  	ssize_t n = writev(fd, iov, cnt);
-	if (n < 0 && errno != EAGAIN && errno != EWOULDBLOCK &&
-	    errno != EINTR) {
-		tnt_raise(SocketError, sio_socketname(fd),
-			  "writev(%d)", iovcnt);
-	}
+	if (n < 0)
+		diag_set(SocketError, sio_socketname(fd), "writev(%d)", iovcnt);
  	return n;
  }
  
@@ -294,10 +287,8 @@ sio_sendto(int fd, const void *buf, size_t len, int flags,
  {
  	ssize_t n = sendto(fd, buf, len, flags, (struct sockaddr*)dest_addr,
  	                   addrlen);
-	if (n < 0 && errno != EAGAIN &&
-	    errno != EWOULDBLOCK && errno != EINTR)
-			tnt_raise(SocketError, sio_socketname(fd),
-				  "sendto(%zd)", len);
+	if (n < 0)
+		diag_set(SocketError, sio_socketname(fd), "sendto(%zd)", len);
  	return n;
  }
  
@@ -308,10 +299,8 @@ sio_recvfrom(int fd, void *buf, size_t len, int flags,
  {
  	ssize_t n = recvfrom(fd, buf, len, flags, (struct sockaddr*)src_addr,
  	                     addrlen);
-	if (n < 0 && errno != EAGAIN &&
-	    errno != EWOULDBLOCK && errno != EINTR)
-			tnt_raise(SocketError, sio_socketname(fd),
-				  "recvfrom(%zd)", len);
+	if (n < 0)
+		diag_set(SocketError, sio_socketname(fd), "recvfrom(%zd)", len);
  	return n;
  }
  
diff --git a/src/sio.h b/src/sio.h
index 2843c0c45..864fa16d9 100644
--- a/src/sio.h
+++ b/src/sio.h
@@ -48,6 +48,13 @@ extern "C" {
  
  enum { SERVICE_NAME_MAXLEN = 32 };
  
+/**
+ * Check if an errno, returned from a sio function, means a
+ * non-critical error: EAGAIN, EWOULDBLOCK, EINTR.
+ */
+bool
+sio_wouldblock(int err);
+
  const char *
  sio_strfaddr(struct sockaddr *addr, socklen_t addrlen);
  






More information about the Tarantool-patches mailing list