From 42e851bb8c38e799bbd31fcf0a4c6b11fdb10df6 Mon Sep 17 00:00:00 2001 From: Azat Khuzhin Date: Sun, 10 Dec 2017 23:57:19 +0300 Subject: [PATCH] Merge branch 'evconnlistener-do-not-close-client-fd' Fixes: #577 * evconnlistener-do-not-close-client-fd: listener: cover closing of fd in case evconnlistener_free() called from acceptcb Revert "Fix potential fd leak in listener_read_cb()" (cherry picked from commit bc65ffc14c62c10feffefe6c3d9975ce1d1a8cd8) --- listener.c | 2 -- test/regress_listener.c | 48 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/listener.c b/listener.c index 2862d32e..942fa451 100644 --- a/listener.c +++ b/listener.c @@ -421,8 +421,6 @@ listener_read_cb(evutil_socket_t fd, short what, void *p) if (lev->refcnt == 1) { int freed = listener_decref_and_unlock(lev); EVUTIL_ASSERT(freed); - - evutil_closesocket(new_fd); return; } --lev->refcnt; diff --git a/test/regress_listener.c b/test/regress_listener.c index 72f7237b..32f23074 100644 --- a/test/regress_listener.c +++ b/test/regress_listener.c @@ -185,6 +185,51 @@ end: evconnlistener_free(listener); } +static void +acceptcb_free(struct evconnlistener *listener, evutil_socket_t fd, + struct sockaddr *addr, int socklen, void *arg) +{ + int *ptr = arg; + --*ptr; + TT_BLATHER(("Got one for %p", ptr)); + evutil_closesocket(fd); + + if (! *ptr) + evconnlistener_free(listener); +} +static void +regress_listener_close_accepted_fd(void *arg) +{ + struct basic_test_data *data = arg; + struct event_base *base = data->base; + struct evconnlistener *listener = NULL; + struct sockaddr_in sin; + struct sockaddr_storage ss; + ev_socklen_t slen = sizeof(ss); + int count = 1; + unsigned int flags = LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE; + int fd = -1; + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */ + sin.sin_port = 0; /* "You pick!" */ + + /* Start a listener with a bogus socket. */ + listener = evconnlistener_new_bind(base, acceptcb_free, &count, + flags, -1, (struct sockaddr *)&sin, sizeof(sin)); + tt_assert(listener); + + tt_assert(getsockname(evconnlistener_get_fd(listener), + (struct sockaddr*)&ss, &slen) == 0); + evutil_socket_connect_(&fd, (struct sockaddr*)&ss, slen); + + event_base_dispatch(base); + +end: + ; +} + #ifdef EVENT__HAVE_SETRLIMIT static void regress_listener_error_unlock(void *arg) @@ -242,6 +287,9 @@ struct testcase_t listener_testcases[] = { TT_FORK|TT_NEED_BASE|TT_NEED_SOCKETPAIR, &basic_setup, (char*)"ts"}, + { "close_accepted_fd", regress_listener_close_accepted_fd, + TT_FORK|TT_NEED_BASE, &basic_setup, NULL, }, + END_OF_TESTCASES, }; -- 2.40.0