From e68575506b922266574fcc8acc849ce1e557cafb Mon Sep 17 00:00:00 2001 From: Yann Ylavic Date: Tue, 28 Mar 2017 21:05:41 +0000 Subject: [PATCH] core: Disallow multiple Listen on the same IP:port when listener buckets are configured (ListenCoresBucketsRatio > 0), consistently with the single bucket case (default), thus fixing the leak of the corresponding socket descriptors on graceful restart. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1789220 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 5 +++++ server/listen.c | 50 ++++++++++++++++++++++++++++++++----------------- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/CHANGES b/CHANGES index 16d64dd962..6576d4a6b5 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,11 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) core: Disallow multiple Listen on the same IP:port when listener buckets + are configured (ListenCoresBucketsRatio > 0), consistently with the single + bucket case (default), thus avoiding the leak of the corresponding socket + descriptors on graceful restart. [Yann Ylavic] + *) mod_http2: input buffering and dynamic flow windows for increased throughput. [Stefan Eissing] diff --git a/server/listen.c b/server/listen.c index 9989b80748..a8f32ecc49 100644 --- a/server/listen.c +++ b/server/listen.c @@ -404,18 +404,14 @@ static const char *set_systemd_listener(process_rec *process, apr_port_t port, #endif /* HAVE_SYSTEMD */ -static const char *alloc_listener(process_rec *process, char *addr, - apr_port_t port, const char* proto, - void *slave) +static int find_listeners(ap_listen_rec **from, ap_listen_rec **to, + const char *addr, apr_port_t port) { - ap_listen_rec **walk, *last; - apr_status_t status; - apr_sockaddr_t *sa; - int found_listener = 0; + int found = 0; + + while (*from) { + apr_sockaddr_t *sa = (*from)->bind_addr; - /* see if we've got an old listener for this address:port */ - for (walk = &old_listeners; *walk;) { - sa = (*walk)->bind_addr; /* Some listeners are not real so they will not have a bind_addr. */ if (sa) { ap_listen_rec *new; @@ -428,19 +424,39 @@ static const char *alloc_listener(process_rec *process, char *addr, if (port == oldport && ((!addr && !sa->hostname) || ((addr && sa->hostname) && !strcmp(sa->hostname, addr)))) { - new = *walk; - *walk = new->next; - new->next = ap_listeners; - ap_listeners = new; - found_listener = 1; + found = 1; + if (!to) { + break; + } + new = *from; + *from = new->next; + new->next = *to; + *to = new; continue; } } - walk = &(*walk)->next; + from = &(*from)->next; + } + + return found; +} + +static const char *alloc_listener(process_rec *process, const char *addr, + apr_port_t port, const char* proto, + void *slave) +{ + ap_listen_rec *last; + apr_status_t status; + apr_sockaddr_t *sa; + + /* see if we've got a listener for this address:port, which is an error */ + if (find_listeners(&ap_listeners, NULL, addr, port)) { + return "Cannot define multiple Listeners on the same IP:port"; } - if (found_listener) { + /* see if we've got an old listener for this address:port */ + if (find_listeners(&old_listeners, &ap_listeners, addr, port)) { if (ap_listeners->slave != slave) { return "Cannot define a slave on the same IP:port as a Listener"; } -- 2.40.0