summaryrefslogtreecommitdiff
path: root/server.c
diff options
context:
space:
mode:
authorReyk Floeter <reyk@esdenera.com>2015-01-03 21:06:57 +0100
committerReyk Floeter <reyk@esdenera.com>2015-01-03 21:06:57 +0100
commit4f5dd228f08c132afdef71c1a5a124595905d8ae (patch)
tree653146e322b074f6a796a7b247b8113edcc943df /server.c
parent461ae7b2ed14e4c38ecf78d791138922a6c050f3 (diff)
downloadhttpd-4f5dd228f08c132afdef71c1a5a124595905d8ae.tar.gz
httpd-4f5dd228f08c132afdef71c1a5a124595905d8ae.zip
In the parent, only open a socket once per unique listen statement.
Fixes possible file descriptor exhaustion on configuration load time.
Diffstat (limited to 'server.c')
-rw-r--r--server.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/server.c b/server.c
index 1d30f35..3b4c0dc 100644
--- a/server.c
+++ b/server.c
@@ -101,11 +101,27 @@ server_shutdown(void)
int
server_privinit(struct server *srv)
{
+ struct server *s;
+
if (srv->srv_conf.flags & SRVFLAG_LOCATION)
return (0);
log_debug("%s: adding server %s", __func__, srv->srv_conf.name);
+ /*
+ * There's no need to open a new socket if a server with the
+ * same address already exists.
+ */
+ TAILQ_FOREACH(s, env->sc_servers, srv_entry) {
+ if (s != srv && s->srv_s != -1 &&
+ s->srv_conf.port == srv->srv_conf.port &&
+ sockaddr_cmp((struct sockaddr *)&s->srv_conf.ss,
+ (struct sockaddr *)&srv->srv_conf.ss,
+ s->srv_conf.prefixlen) == 0)
+ return (0);
+ }
+
+ /* Open listening socket in the privileged process */
if ((srv->srv_s = server_socket_listen(&srv->srv_conf.ss,
srv->srv_conf.port, &srv->srv_conf)) == -1)
return (-1);
@@ -277,7 +293,8 @@ server_purge(struct server *srv)
if (evtimer_initialized(&srv->srv_evt))
evtimer_del(&srv->srv_evt);
- close(srv->srv_s);
+ if (srv->srv_s != -1)
+ close(srv->srv_s);
TAILQ_REMOVE(env->sc_servers, srv, srv_entry);
/* cleanup sessions */