diff options
author | Jim Jagielski <jim@apache.org> | 2017-08-16 16:48:29 +0000 |
---|---|---|
committer | Jim Jagielski <jim@apache.org> | 2017-08-16 16:48:29 +0000 |
commit | d64568ba342541da74f988811774a41a5e7cdb10 (patch) | |
tree | 5f279f8ea2812072e157b7236611e9c317d3968f /server | |
parent | 8a671405124f2930785fa91a5a5f207f51f5f160 (diff) | |
download | httpd-d64568ba342541da74f988811774a41a5e7cdb10.tar.gz |
Merge r1789220, r1792675 from trunk:
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.
Follow up to r1789220.
Document the implicit behaviour of ListenCoresBucketsRatio when multiple
Listen-ers are configured on the same IP:port.
Submitted by: ylavic
Reviewed by: ylavic, jim, jorton
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1805221 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"; } |