diff options
author | Yann Ylavic <ylavic@apache.org> | 2017-03-28 20:53:07 +0000 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2017-03-28 20:53:07 +0000 |
commit | 820f0d1d79a40fff4bf1ae1f34e2c95c5afe7047 (patch) | |
tree | 1d84d6b856c7143939c61b298f06d83e351780e7 /server | |
parent | fb9b64d5feb099001d80467533168644ea03ad72 (diff) | |
download | httpd-820f0d1d79a40fff4bf1ae1f34e2c95c5afe7047.tar.gz |
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/branches/2.4.x@1789213 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'server')
-rw-r--r-- | server/listen.c | 50 |
1 files changed, 33 insertions, 17 deletions
diff --git a/server/listen.c b/server/listen.c index d44c7c9f44..a8e9e6f6e3 100644 --- a/server/listen.c +++ b/server/listen.c @@ -277,18 +277,14 @@ static apr_status_t close_listeners_on_exec(void *v) return APR_SUCCESS; } -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; @@ -301,19 +297,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"; } |