]> granicus.if.org Git - libevent/commitdiff
Merge branch 'evconnlistener-do-not-close-client-fd'
authorAzat Khuzhin <a3at.mail@gmail.com>
Sun, 10 Dec 2017 20:57:19 +0000 (23:57 +0300)
committerAzat Khuzhin <azat@libevent.org>
Sat, 2 Feb 2019 12:13:54 +0000 (15:13 +0300)
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
test/regress_listener.c

index 2862d32e38d0335c218e7ce8defc23a7911a8126..942fa45180f957fd4a6b751c21d8792cc5ce9d43 100644 (file)
@@ -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;
index 72f7237be6e48465ca495b9babfa45caff5200d7..32f2307426e5272daacd14be2f914e5d645c1e05 100644 (file)
@@ -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,
 };