]> granicus.if.org Git - apache/commitdiff
core: Disallow multiple Listen on the same IP:port when listener buckets
authorYann Ylavic <ylavic@apache.org>
Tue, 28 Mar 2017 21:05:41 +0000 (21:05 +0000)
committerYann Ylavic <ylavic@apache.org>
Tue, 28 Mar 2017 21:05:41 +0000 (21:05 +0000)
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
server/listen.c

diff --git a/CHANGES b/CHANGES
index 16d64dd962ac089da06b23daaa3185e385f4ec3a..6576d4a6b5bcfe575eb72ce4da990a2ee634f644 100644 (file)
--- 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]
 
index 9989b8074865633ef02e79b594ebdfe9e483abab..a8f32ecc494725662bdfeacc949bbd6af39fb7a1 100644 (file)
@@ -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";
         }