[PATCH v2 03/11] sio: remove exceptions
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Wed Dec 5 00:28:50 MSK 2018
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)
More information about the Tarantool-patches
mailing list