[PATCH v2 06/11] evio: make on_accept be nothrow

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Wed Dec 5 00:28:53 MSK 2018


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        | 20 ++++++++++----------
 4 files changed, 29 insertions(+), 34 deletions(-)

diff --git a/src/box/iproto.cc b/src/box/iproto.cc
index fe42bb250..f4051e791 100644
--- a/src/box/iproto.cc
+++ b/src/box/iproto.cc
@@ -1795,7 +1795,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)
 {
@@ -1804,26 +1804,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 a546f647d..9b9c71c79 100644
--- a/src/coio.cc
+++ b/src/coio.cc
@@ -589,7 +589,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)
 {
@@ -605,14 +605,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
@@ -624,6 +622,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 32aece0f0..1d906db8e 100644
--- a/src/evio.cc
+++ b/src/evio.cc
@@ -195,8 +195,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);
@@ -305,11 +307,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..e56e2b8a7 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. */
@@ -79,12 +84,10 @@ struct evio_service
 
 	/**
 	 * A callback invoked on every accepted client socket.
-	 * It's OK to throw an exception in the callback:
-	 * when it happens, the exception is logged, and the
-	 * accepted socket is closed.
+	 * If a callback returned != 0, the accepted socket is
+	 * closed and the error is logged.
 	 */
-	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 +97,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)




More information about the Tarantool-patches mailing list