Only open a socket once for each unique "listen on" statement. This
authorreyk <reyk@openbsd.org>
Tue, 6 Jan 2015 14:07:48 +0000 (14:07 +0000)
committerreyk <reyk@openbsd.org>
Tue, 6 Jan 2015 14:07:48 +0000 (14:07 +0000)
prevents running out of file descriptors when loading a configuration
with many aliases.

OK florian@

usr.sbin/httpd/config.c
usr.sbin/httpd/parse.y
usr.sbin/httpd/server.c

index 14fe63e..4077d34 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: config.c,v 1.27 2015/01/03 15:49:18 reyk Exp $        */
+/*     $OpenBSD: config.c,v 1.28 2015/01/06 14:07:48 reyk Exp $        */
 
 /*
  * Copyright (c) 2011 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -200,7 +200,9 @@ config_setserver(struct httpd *env, struct server *srv)
                        n = -1;
                        proc_range(ps, id, &n, &m);
                        for (n = 0; n < m; n++) {
-                               if ((fd = dup(srv->srv_s)) == -1)
+                               if (srv->srv_s == -1)
+                                       fd = -1;
+                               else if ((fd = dup(srv->srv_s)) == -1)
                                        return (-1);
                                proc_composev_imsg(ps, id, n,
                                    IMSG_CFG_SERVER, fd, iov, c);
@@ -211,9 +213,6 @@ config_setserver(struct httpd *env, struct server *srv)
                }
        }
 
-       close(srv->srv_s);
-       srv->srv_s = -1;
-
        return (0);
 }
 
@@ -356,8 +355,12 @@ config_getserver(struct httpd *env, struct imsg *imsg)
        if ((srv = server_byaddr((struct sockaddr *)
            &srv_conf.ss, srv_conf.port)) != NULL) {
                /* Add "host" to existing listening server */
-               if (imsg->fd != -1)
-                       close(imsg->fd);
+               if (imsg->fd != -1) {
+                       if (srv->srv_s == -1)
+                               srv->srv_s = imsg->fd;
+                       else
+                               close(imsg->fd);
+               }
                return (config_getserver_config(env, srv, imsg));
        }
 
index 5a9616c..c7a536c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: parse.y,v 1.50 2015/01/04 22:23:58 chrisz Exp $       */
+/*     $OpenBSD: parse.y,v 1.51 2015/01/06 14:07:48 reyk Exp $ */
 
 /*
  * Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -226,6 +226,7 @@ server              : SERVER STRING         {
                        strlcpy(s->srv_conf.errorlog, HTTPD_ERROR_LOG,
                            sizeof(s->srv_conf.errorlog));
                        s->srv_conf.id = ++last_server_id;
+                       s->srv_s = -1;
                        s->srv_conf.timeout.tv_sec = SERVER_TIMEOUT;
                        s->srv_conf.maxrequests = SERVER_MAXREQUESTS;
                        s->srv_conf.maxrequestbody = SERVER_MAXREQUESTBODY;
@@ -484,6 +485,7 @@ serveroptsl : LISTEN ON STRING opttls port {
                        /* A location entry uses the parent id */
                        s->srv_conf.id = srv->srv_conf.id;
                        s->srv_conf.flags = SRVFLAG_LOCATION;
+                       s->srv_s = -1;
                        memcpy(&s->srv_conf.ss, &srv->srv_conf.ss,
                            sizeof(s->srv_conf.ss));
                        s->srv_conf.port = srv->srv_conf.port;
@@ -1760,6 +1762,8 @@ server_inherit(struct server *src, const char *name,
        dst->srv_conf.tls_key = NULL;
 
        dst->srv_conf.id = ++last_server_id;
+       dst->srv_s = -1;
+
        if (last_server_id == INT_MAX) {
                yyerror("too many servers defined");
                serverconfig_free(&dst->srv_conf);
@@ -1824,6 +1828,7 @@ server_inherit(struct server *src, const char *name,
                    sizeof(dstl->srv_conf.ss));
                dstl->srv_conf.port = addr->port;
                dstl->srv_conf.prefixlen = addr->prefixlen;
+               dstl->srv_s = -1;
 
                DPRINTF("adding location \"%s\" for \"%s[%u]\"",
                    dstl->srv_conf.location,
index 1d30f35..cc237ca 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: server.c,v 1.49 2014/12/21 00:54:49 guenther Exp $    */
+/*     $OpenBSD: server.c,v 1.50 2015/01/06 14:07:48 reyk Exp $        */
 
 /*
  * Copyright (c) 2006 - 2014 Reyk Floeter <reyk@openbsd.org>
@@ -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 */