summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2017-03-28 20:53:07 +0000
committerYann Ylavic <ylavic@apache.org>2017-03-28 20:53:07 +0000
commit820f0d1d79a40fff4bf1ae1f34e2c95c5afe7047 (patch)
tree1d84d6b856c7143939c61b298f06d83e351780e7 /server
parentfb9b64d5feb099001d80467533168644ea03ad72 (diff)
downloadhttpd-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.c50
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";
}