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)
next prev 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