Tarantool development patches archive
 help / color / mirror / Atom feed
From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
To: tarantool-patches@freelists.org
Cc: vdavydov.dev@gmail.com
Subject: [PATCH 07/11] coio: fix file descriptor leak on accept
Date: Fri, 30 Nov 2018 18:39:39 +0300	[thread overview]
Message-ID: <b737a7acc6118928dd9e3c2fff681a5243836243.1543590433.git.v.shpilevoy@tarantool.org> (raw)
In-Reply-To: <cover.1543590433.git.v.shpilevoy@tarantool.org>
In-Reply-To: <cover.1543590433.git.v.shpilevoy@tarantool.org>

coio_accept() calls evio_setsockopt_client, which
throws an exception and just accepted socket leaks.
Yes, server socket is protected, but not new client
socket.
---
 src/coio.cc |  7 +++++--
 src/evio.cc | 49 ++++++++++++++++++++++++++++---------------------
 src/evio.h  |  2 +-
 3 files changed, 34 insertions(+), 24 deletions(-)

diff --git a/src/coio.cc b/src/coio.cc
index 49ac10b70..575bae712 100644
--- a/src/coio.cc
+++ b/src/coio.cc
@@ -254,8 +254,11 @@ coio_accept(struct ev_io *coio, struct sockaddr *addr,
 		int fd = sio_accept(coio->fd, addr, &addrlen,
 				    &is_error_fatal);
 		if (fd >= 0) {
-			evio_setsockopt_client(fd, addr->sa_family,
-					       SOCK_STREAM);
+			if (evio_setsockopt_client(fd, addr->sa_family,
+						   SOCK_STREAM) != 0) {
+				close(fd);
+				diag_raise();
+			}
 			return fd;
 		}
 		if (is_error_fatal)
diff --git a/src/evio.cc b/src/evio.cc
index 4b7d37281..25f699bab 100644
--- a/src/evio.cc
+++ b/src/evio.cc
@@ -64,14 +64,17 @@ void
 evio_socket(struct ev_io *coio, int domain, int type, int protocol)
 {
 	assert(coio->fd == -1);
-	/* Don't leak fd if setsockopt fails. */
 	coio->fd = sio_socket(domain, type, protocol);
 	if (coio->fd < 0)
 		diag_raise();
-	evio_setsockopt_client(coio->fd, domain, type);
+	if (evio_setsockopt_client(coio->fd, domain, type) != 0) {
+		close(coio->fd);
+		coio->fd = -1;
+		diag_raise();
+	}
 }
 
-static void
+static int
 evio_setsockopt_keepalive(int fd)
 {
 	int on = 1;
@@ -79,9 +82,8 @@ evio_setsockopt_keepalive(int fd)
 	 * SO_KEEPALIVE to ensure connections don't hang
 	 * around for too long when a link goes away.
 	 */
-	if (sio_setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
-		       &on, sizeof(on)))
-		diag_raise();
+	if (sio_setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) != 0)
+		return -1;
 #ifdef __linux__
 	/*
 	 * On Linux, we are able to fine-tune keepalive
@@ -90,44 +92,46 @@ evio_setsockopt_keepalive(int fd)
 	 */
 	int keepcnt = 5;
 	if (sio_setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt,
-		       sizeof(int)))
-		diag_raise();
+			   sizeof(int)) != 0)
+		return -1;
 	int keepidle = 30;
 
 	if (sio_setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle,
-		       sizeof(int)))
-		diag_raise();
+			   sizeof(int)) != 0)
+		return -1;
 
 	int keepintvl = 60;
 	if (sio_setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &keepintvl,
-		       sizeof(int)))
-		diag_raise();
+			   sizeof(int)) != 0)
+		return -1;
 #endif
+	return 0;
 }
 
 /** Set common client socket options. */
-void
+int
 evio_setsockopt_client(int fd, int family, int type)
 {
 	int on = 1;
-	/* In case this throws, the socket is not leaked. */
 	if (sio_setfl(fd, O_NONBLOCK) != 0)
-		diag_raise();
+		return -1;
 	if (type == SOCK_STREAM && family != AF_UNIX) {
 		/*
 		 * SO_KEEPALIVE to ensure connections don't hang
 		 * around for too long when a link goes away.
 		 */
-		evio_setsockopt_keepalive(fd);
+		if (evio_setsockopt_keepalive(fd) != 0)
+			return -1;
 		/*
 		 * Lower latency is more important than higher
 		 * bandwidth, and we usually write entire
 		 * request/response in a single syscall.
 		 */
 		if (sio_setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
-				   &on, sizeof(on)))
-			diag_raise();
+				   &on, sizeof(on)) != 0)
+			return -1;
 	}
+	return 0;
 }
 
 /** Set options for server sockets. */
@@ -150,8 +154,9 @@ evio_setsockopt_server(int fd, int family, int type)
 	if (sio_setsockopt(fd, SOL_SOCKET, SO_LINGER,
 		       &linger, sizeof(linger)))
 		diag_raise();
-	if (type == SOCK_STREAM && family != AF_UNIX)
-		evio_setsockopt_keepalive(fd);
+	if (type == SOCK_STREAM && family != AF_UNIX &&
+	    evio_setsockopt_keepalive(fd) != 0)
+		diag_raise();
 }
 
 static inline const char *
@@ -191,7 +196,9 @@ evio_service_accept_cb(ev_loop * /* loop */, ev_io *watcher,
 				return;
 			}
 			/* set common client socket options */
-			evio_setsockopt_client(fd, service->addr.sa_family, SOCK_STREAM);
+			if (evio_setsockopt_client(fd, service->addr.sa_family,
+						   SOCK_STREAM) != 0)
+				diag_raise();
 			/*
 			 * Invoke the callback and pass it the accepted
 			 * socket.
diff --git a/src/evio.h b/src/evio.h
index f6c3a3a3e..9f80e84a5 100644
--- a/src/evio.h
+++ b/src/evio.h
@@ -150,7 +150,7 @@ evio_timeout_update(ev_loop *loop, ev_tstamp start, ev_tstamp *delay)
 	*delay = (elapsed >= *delay) ? 0 : *delay - elapsed;
 }
 
-void
+int
 evio_setsockopt_client(int fd, int family, int type);
 
 #endif /* TARANTOOL_EVIO_H_INCLUDED */
-- 
2.17.2 (Apple Git-113)

  parent reply	other threads:[~2018-11-30 15:39 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-30 15:39 [PATCH 00/11] SWIM preparation Vladislav Shpilevoy
2018-11-30 15:39 ` [PATCH 01/11] box: move info_handler interface into src/info Vladislav Shpilevoy
2018-12-03 11:05   ` Vladimir Davydov
2018-12-03 21:48     ` [tarantool-patches] " Vladislav Shpilevoy
2018-12-03 20:41   ` [tarantool-patches] " Konstantin Osipov
2018-12-03 21:48     ` [tarantool-patches] " Vladislav Shpilevoy
2018-12-04  8:52       ` Vladimir Davydov
2018-11-30 15:39 ` [PATCH 10/11] evio: remove exceptions Vladislav Shpilevoy
2018-11-30 15:39 ` [PATCH 11/11] evio: turn into C Vladislav Shpilevoy
2018-11-30 15:39 ` [PATCH 02/11] sio: remove unused functions, restyle code Vladislav Shpilevoy
2018-12-03 12:28   ` Vladimir Davydov
2018-12-04 21:29     ` [tarantool-patches] " Vladislav Shpilevoy
2018-12-05  8:41       ` Vladimir Davydov
2018-11-30 15:39 ` [PATCH 03/11] sio: remove exceptions Vladislav Shpilevoy
2018-12-03 12:36   ` Vladimir Davydov
2018-12-04 21:29     ` [tarantool-patches] " Vladislav Shpilevoy
2018-12-05  8:42       ` Vladimir Davydov
2018-11-30 15:39 ` [PATCH 04/11] sio: fix passing negative size_t to sio_add_to_iov Vladislav Shpilevoy
2018-12-03 13:50   ` Vladimir Davydov
2018-12-04 21:29     ` Vladislav Shpilevoy
2018-12-05  8:48       ` Vladimir Davydov
2018-11-30 15:39 ` [PATCH 05/11] sio: turn into C Vladislav Shpilevoy
2018-11-30 15:39 ` [PATCH 06/11] evio: make on_accept be nothrow Vladislav Shpilevoy
2018-12-03 14:58   ` Vladimir Davydov
2018-12-04 21:29     ` [tarantool-patches] " Vladislav Shpilevoy
2018-12-05  8:52       ` Vladimir Davydov
2018-11-30 15:39 ` Vladislav Shpilevoy [this message]
2018-12-03 16:16   ` [PATCH 07/11] coio: fix file descriptor leak on accept Vladimir Davydov
2018-12-04 21:29     ` [tarantool-patches] " Vladislav Shpilevoy
2018-11-30 15:39 ` [PATCH 08/11] coio: fix double close of a file descriptor Vladislav Shpilevoy
2018-12-03 16:19   ` Vladimir Davydov
2018-12-04 21:29     ` [tarantool-patches] " Vladislav Shpilevoy
2018-11-30 15:39 ` [PATCH 09/11] evio: refactoring Vladislav Shpilevoy
2018-12-03 16:37   ` Vladimir Davydov
2018-12-04 21:29     ` [tarantool-patches] " Vladislav Shpilevoy
2018-12-03  9:47 ` [PATCH 00/11] SWIM preparation Vladimir Davydov
2018-12-03 10:27   ` [tarantool-patches] " Vladislav Shpilevoy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b737a7acc6118928dd9e3c2fff681a5243836243.1543590433.git.v.shpilevoy@tarantool.org \
    --to=v.shpilevoy@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --cc=vdavydov.dev@gmail.com \
    --subject='Re: [PATCH 07/11] coio: fix file descriptor leak on accept' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox