Commit 5bc4034b authored by Yann Ylavic's avatar Yann Ylavic
Browse files

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
parent 4d713314
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
                                                         -*- 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]

+33 −17
Original line number Diff line number Diff line
@@ -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";
        }