Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: tarantool-patches@freelists.org
Cc: vdavydov.dev@gmail.com
Subject: [PATCH v2 03/11] sio: remove exceptions
Date: Wed,  5 Dec 2018 00:28:50 +0300	[thread overview]
Message-ID: <fd79be8d0a088041d5a33dca9af6a5c78691159d.1543958698.git.v.shpilevoy@tarantool.org> (raw)
In-Reply-To: <cover.1543958698.git.v.shpilevoy@tarantool.org>
In-Reply-To: <cover.1543958698.git.v.shpilevoy@tarantool.org>

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 do not
set diagnosticts on a number of specific errors.

To check if an error, returned from a function, is
critical, a new function is introduced:
sio_is_error_fatal(). It takes a code, returned by a
function, and checks if it means a critical error.

Needed for #3234
---
 src/box/iproto.cc | 21 ++++++++---------
 src/coio.cc       | 25 ++++++++++++--------
 src/evio.cc       | 18 ++++++++++-----
 src/sio.cc        | 58 ++++++++++++++++++++++++++++++-----------------
 src/sio.h         |  7 ++++++
 5 files changed, 81 insertions(+), 48 deletions(-)

diff --git a/src/box/iproto.cc b/src/box/iproto.cc
index 7c11d05b3..fe42bb250 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_is_error_fatal(nrd))
+				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_is_error_fatal(nwr)) {
+		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_is_error_fatal(nwr))
+			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..a546f647d 100644
--- a/src/coio.cc
+++ b/src/coio.cc
@@ -258,6 +258,8 @@ coio_accept(struct ev_io *coio, struct sockaddr *addr,
 					       SOCK_STREAM);
 			return fd;
 		}
+		if (sio_is_error_fatal(fd))
+			diag_raise();
 		/* The socket is not ready, yield */
 		if (! ev_is_active(coio)) {
 			ev_io_set(coio, coio->fd, EV_READ);
@@ -313,6 +315,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_is_error_fatal(nrd)) {
+			diag_raise();
 		}
 
 		/* The socket is not ready, yield */
@@ -404,6 +408,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_is_error_fatal(nwr)) {
+			diag_raise();
 		}
 		if (! ev_is_active(coio)) {
 			ev_io_set(coio, coio->fd, EV_WRITE);
@@ -433,15 +439,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_is_error_fatal(nwr))
+		diag_raise();
 	return nwr;
 }
 
@@ -522,6 +524,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_is_error_fatal(nwr))
+			diag_raise();
 		if (! ev_is_active(coio)) {
 			ev_io_set(coio, coio->fd, EV_WRITE);
 			ev_io_start(loop(), coio);
@@ -565,7 +569,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_is_error_fatal(nrd))
+			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 9df797c78..32aece0f0 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_is_error_fatal(fd))
+					diag_raise();
 				return;
+			}
 			/* set common client socket options */
 			evio_setsockopt_client(fd, service->addr.sa_family, SOCK_STREAM);
 			/*
@@ -259,13 +262,15 @@ 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 (errno != EADDRINUSE)
+	int rc = sio_bind(fd, &service->addr, service->addr_len);
+	if (rc != 0) {
+		if (sio_is_error_fatal(rc))
 			diag_raise();
 		if (evio_service_reuse_addr(service, fd))
 			diag_raise();
-		if (sio_bind(fd, &service->addr, service->addr_len)) {
-			if (errno == EADDRINUSE) {
+		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");
 			}
@@ -294,7 +299,8 @@ evio_service_listen(struct evio_service *service)
 		  sio_strfaddr(&service->addr, service->addr_len));
 
 	int fd = service->ev.fd;
-	sio_listen(fd);
+	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 aa44b4912..a13e7d9de 100644
--- a/src/sio.cc
+++ b/src/sio.cc
@@ -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)
@@ -213,8 +221,10 @@ int
 sio_listen(int fd)
 {
 	int rc = listen(fd, sio_listen_backlog());
-	if (rc < 0)
-		tnt_raise(SocketError, sio_socketname(fd), "listen");
+	if (rc < 0) {
+		diag_set(SocketError, sio_socketname(fd), "listen");
+		return SIO_ERROR_FATAL;
+	}
 	return rc;
 }
 
@@ -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;
 }
 
@@ -253,8 +265,9 @@ sio_read(int fd, void *buf, size_t count)
 			n = 0;
 			break;
 		default:
-			tnt_raise(SocketError, sio_socketname(fd),
-				  "read(%zd)", count);
+			diag_set(SocketError, sio_socketname(fd), "read(%zd)",
+				 count);
+			return SIO_ERROR_FATAL;
 		}
 	}
 	return n;
@@ -265,10 +278,11 @@ 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 && errno != EAGAIN && errno != EWOULDBLOCK &&
+	    errno != EINTR) {
+		diag_set(SocketError, sio_socketname(fd), "write(%zd)", count);
+		return SIO_ERROR_FATAL;
+	}
 	return n;
 }
 
@@ -280,8 +294,8 @@ sio_writev(int fd, const struct iovec *iov, int iovcnt)
 	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);
+		diag_set(SocketError, sio_socketname(fd), "writev(%d)", iovcnt);
+		return SIO_ERROR_FATAL;
 	}
 	return n;
 }
@@ -293,10 +307,11 @@ 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 && errno != EAGAIN && errno != EWOULDBLOCK &&
+	    errno != EINTR) {
+		diag_set(SocketError, sio_socketname(fd), "sendto(%zd)", len);
+		return SIO_ERROR_FATAL;
+	}
 	return n;
 }
 
@@ -307,10 +322,11 @@ 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 && errno != EAGAIN && errno != EWOULDBLOCK &&
+	    errno != EINTR) {
+		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 2843c0c45..5d12f35f9 100644
--- a/src/sio.h
+++ b/src/sio.h
@@ -48,6 +48,13 @@ extern "C" {
 
 enum { SERVICE_NAME_MAXLEN = 32 };
 
+/**
+ * Check if a code, returned from a sio function, means a
+ * critical error.
+ */
+bool
+sio_is_error_fatal(int retcode);
+
 const char *
 sio_strfaddr(struct sockaddr *addr, socklen_t addrlen);
 
-- 
2.17.2 (Apple Git-113)

  parent reply	other threads:[~2018-12-04 21:28 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-04 21:28 [PATCH v2 00/11] SWIM preparation Vladislav Shpilevoy
2018-12-04 21:28 ` [PATCH v2 01/11] sio: remove unused functions Vladislav Shpilevoy
2018-12-09 12:10   ` Vladimir Davydov
2018-12-04 21:28 ` [PATCH v2 10/11] evio: make code C compatible Vladislav Shpilevoy
2018-12-05  8:56   ` Vladimir Davydov
2018-12-05 20:07     ` [tarantool-patches] " Vladislav Shpilevoy
2018-12-04 21:28 ` [PATCH v2 11/11] evio: turn nto c Vladislav Shpilevoy
2018-12-04 21:28 ` [PATCH v2 02/11] sio: treat EADDRINUSE in sio_listen as error Vladislav Shpilevoy
2018-12-09 12:57   ` Vladimir Davydov
2018-12-10 15:36     ` [tarantool-patches] " Vladislav Shpilevoy
2018-12-04 21:28 ` Vladislav Shpilevoy [this message]
2018-12-09 12:54   ` [PATCH v2 03/11] sio: remove exceptions Vladimir Davydov
2018-12-10 15:37     ` [tarantool-patches] " Vladislav Shpilevoy
2018-12-11  8:44       ` Vladimir Davydov
2018-12-04 21:28 ` [PATCH v2 04/11] sio: make code compatible with C Vladislav Shpilevoy
2018-12-05  8:57   ` Vladimir Davydov
2018-12-05 20:07     ` [tarantool-patches] " Vladislav Shpilevoy
2018-12-04 21:28 ` [PATCH v2 05/11] sio: turn into C Vladislav Shpilevoy
2018-12-04 21:28 ` [PATCH v2 06/11] evio: make on_accept be nothrow Vladislav Shpilevoy
2018-12-04 21:28 ` [PATCH v2 07/11] coio: fix double close of a file descriptor Vladislav Shpilevoy
2018-12-04 21:28 ` [PATCH v2 08/11] evio: remove exceptions Vladislav Shpilevoy
2018-12-04 21:28 ` [PATCH v2 09/11] coio: fix file descriptor leak on accept Vladislav Shpilevoy
2018-12-11  8:47 ` [PATCH v2 00/11] SWIM preparation Vladimir Davydov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=fd79be8d0a088041d5a33dca9af6a5c78691159d.1543958698.git.v.shpilevoy@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --cc=vdavydov.dev@gmail.com \
    --subject='Re: [PATCH v2 03/11] sio: remove exceptions' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox