From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Vladislav Shpilevoy Subject: [PATCH v2 03/11] sio: remove exceptions Date: Wed, 5 Dec 2018 00:28:50 +0300 Message-Id: In-Reply-To: References: In-Reply-To: References: To: tarantool-patches@freelists.org Cc: vdavydov.dev@gmail.com List-ID: 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)