From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Subject: Re: [tarantool-patches] Re: [PATCH v2 03/11] sio: remove exceptions References: <20181209125413.3zkcuchfltd4smph@esperanza> From: Vladislav Shpilevoy Message-ID: <1af45eb9-5b6e-9ea7-30d8-fc8ebcf37fa1@tarantool.org> Date: Mon, 10 Dec 2018 18:37:37 +0300 MIME-Version: 1.0 In-Reply-To: <20181209125413.3zkcuchfltd4smph@esperanza> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit To: Vladimir Davydov Cc: tarantool-patches@freelists.org List-ID: 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 #include #include +#include #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 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 #include #include +#include #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);