[tarantool-patches] [PATCH 06/11] evio: make on_accept be nothrow

  • From: Vladislav Shpilevoy <v.shpilevoy@xxxxxxxxxxxxx>
  • To: tarantool-patches@xxxxxxxxxxxxx
  • Date: Fri, 30 Nov 2018 18:39:38 +0300

Evio is going to be C, because it is needed in SWIM to
1) support UNIX sockets in future;
2) do not care about setting SocketError directly. It
is not possible via bare sio, because sio_bind ignores
EADDRINUSE.

A first step to make evio C - eliminate exceptions
from its callbacks available to other modules. The
only callback it has - on_accept.

Needed for #3234
---
 src/box/iproto.cc | 17 +++++++----------
 src/coio.cc       | 13 ++++++-------
 src/evio.cc       | 13 ++++++-------
 src/evio.h        | 15 ++++++++-------
 4 files changed, 27 insertions(+), 31 deletions(-)

diff --git a/src/box/iproto.cc b/src/box/iproto.cc
index 07ef23cac..dd76e28bd 100644
--- a/src/box/iproto.cc
+++ b/src/box/iproto.cc
@@ -1791,7 +1791,7 @@ static const struct cmsg_hop connect_route[] = {
 /**
  * Create a connection and start input.
  */
-static void
+static int
 iproto_on_accept(struct evio_service * /* service */, int fd,
                 struct sockaddr *addr, socklen_t addrlen)
 {
@@ -1800,26 +1800,23 @@ iproto_on_accept(struct evio_service * /* service */, 
int fd,
        struct iproto_msg *msg;
        struct iproto_connection *con = iproto_connection_new(fd);
        if (con == NULL)
-               goto error_conn;
+               return -1;
        /*
         * Ignore msg allocation failure - the queue size is
         * fixed so there is a limited number of msgs in
         * use, all stored in just a few blocks of the memory pool.
         */
        msg = iproto_msg_new(con);
-       if (msg == NULL)
-               goto error_msg;
+       if (msg == NULL) {
+               mempool_free(&iproto_connection_pool, con);
+               return -1;
+       }
        cmsg_init(&msg->base, connect_route);
        msg->p_ibuf = con->p_ibuf;
        msg->wpos = con->wpos;
        msg->close_connection = false;
        cpipe_push(&tx_pipe, &msg->base);
-       return;
-error_msg:
-       mempool_free(&iproto_connection_pool, con);
-error_conn:
-       close(fd);
-       return;
+       return 0;
 }
 
 static struct evio_service binary; /* iproto binary listener */
diff --git a/src/coio.cc b/src/coio.cc
index b69f5e31a..49ac10b70 100644
--- a/src/coio.cc
+++ b/src/coio.cc
@@ -596,7 +596,7 @@ coio_recvfrom_timeout(struct ev_io *coio, void *buf, size_t 
sz, int flags,
        }
 }
 
-void
+static int
 coio_service_on_accept(struct evio_service *evio_service,
                       int fd, struct sockaddr *addr, socklen_t addrlen)
 {
@@ -612,14 +612,12 @@ coio_service_on_accept(struct evio_service *evio_service,
                 "%s/%s", evio_service->name, sio_strfaddr(addr, addrlen));
 
        /* Create the worker fiber. */
-       struct fiber *f;
-       try {
-               f = fiber_new_xc(fiber_name, service->handler);
-       } catch (struct error *e) {
-               error_log(e);
+       struct fiber *f = fiber_new(fiber_name, service->handler);
+       if (f == NULL) {
+               diag_log();
                say_error("can't create a handler fiber, dropping client 
connection");
                evio_close(loop(), &coio);
-               throw;
+               return -1;
        }
        /*
         * The coio is passed into the created fiber, reset the
@@ -631,6 +629,7 @@ coio_service_on_accept(struct evio_service *evio_service,
         * and will have to close it and free before termination.
         */
        fiber_start(f, coio, addr, addrlen, service->handler_param);
+       return 0;
 }
 
 void
diff --git a/src/evio.cc b/src/evio.cc
index 401e71155..4b7d37281 100644
--- a/src/evio.cc
+++ b/src/evio.cc
@@ -196,8 +196,10 @@ evio_service_accept_cb(ev_loop * /* loop */, ev_io 
*watcher,
                         * Invoke the callback and pass it the accepted
                         * socket.
                         */
-                       service->on_accept(service, fd, (struct sockaddr 
*)&addr, addrlen);
-
+                       if (service->on_accept(service, fd,
+                                              (struct sockaddr *)&addr,
+                                              addrlen) != 0)
+                               diag_raise();
                } catch (Exception *e) {
                        if (fd >= 0)
                                close(fd);
@@ -304,11 +306,8 @@ evio_service_listen(struct evio_service *service)
 }
 
 void
-evio_service_init(ev_loop *loop,
-                 struct evio_service *service, const char *name,
-                 void (*on_accept)(struct evio_service *, int,
-                                   struct sockaddr *, socklen_t),
-                 void *on_accept_param)
+evio_service_init(ev_loop *loop, struct evio_service *service, const char 
*name,
+                 evio_accept_f on_accept, void *on_accept_param)
 {
        memset(service, 0, sizeof(struct evio_service));
        snprintf(service->name, sizeof(service->name), "%s", name);
diff --git a/src/evio.h b/src/evio.h
index e91ba11fc..f6c3a3a3e 100644
--- a/src/evio.h
+++ b/src/evio.h
@@ -62,6 +62,11 @@
  * If a service is not started, but only initialized, no
  * dedicated cleanup/destruction is necessary.
  */
+struct evio_service;
+
+typedef int (*evio_accept_f)(struct evio_service *, int, struct sockaddr *,
+                             socklen_t);
+
 struct evio_service
 {
        /** Service name. E.g. 'primary', 'secondary', etc. */
@@ -83,8 +88,7 @@ struct evio_service
         * when it happens, the exception is logged, and the
         * accepted socket is closed.
         */
-       void (*on_accept)(struct evio_service *, int,
-                         struct sockaddr *, socklen_t);
+       evio_accept_f on_accept;
        void *on_accept_param;
 
        /** libev io object for the acceptor socket. */
@@ -94,11 +98,8 @@ struct evio_service
 
 /** Initialize the service. Don't bind to the port yet. */
 void
-evio_service_init(ev_loop *loop,
-                 struct evio_service *service, const char *name,
-                 void (*on_accept)(struct evio_service *,
-                                   int, struct sockaddr *, socklen_t),
-                 void *on_accept_param);
+evio_service_init(ev_loop *loop, struct evio_service *service, const char 
*name,
+                 evio_accept_f on_accept, void *on_accept_param);
 
 /** Bind service to specified uri */
 void
-- 
2.17.2 (Apple Git-113)


Other related posts: