Ticket #237: 0001-Socket-activation-support-for-systemd.patch

File 0001-Socket-activation-support-for-systemd.patch, 9.7 KB (added by www.google.com/accounts/o8/id?id=AItOawlxK-3n_q42GrF-mzBqEsTzq6OKK29sKqE, 4 years ago)
  • auto/options

    From d9263fccaa22296e28d926ef99be2551d003c423 Mon Sep 17 00:00:00 2001
    From: David Strauss <david@davidstrauss.net>
    Date: Sat, 27 Oct 2012 07:11:58 -0400
    Subject: [PATCH] Socket activation support for systemd.
    
    ---
     auto/options                    |   3 +
     auto/os/linux                   |  18 +++++
     src/core/ngx_inet.c             | 147 ++++++++++++++++++++++++++++++++++++++++
     src/core/ngx_inet.h             |   3 +
     src/http/ngx_http.c             |   8 +++
     src/http/ngx_http_core_module.c |  10 ++-
     src/http/ngx_http_core_module.h |   3 +
     7 files changed, 191 insertions(+), 1 deletion(-)
    
    diff --git a/auto/options b/auto/options
    index a75bead..94ae615 100644
    a b USE_THREADS=NO 
    4646
    4747NGX_FILE_AIO=NO
    4848NGX_IPV6=NO
     49NGX_SYSTEMD=NO
    4950
    5051HTTP=YES
    5152
    do 
    190191
    191192        --with-file-aio)                 NGX_FILE_AIO=YES           ;;
    192193        --with-ipv6)                     NGX_IPV6=YES               ;;
     194        --with-systemd)                  NGX_SYSTEMD=YES            ;;
    193195
    194196        --without-http)                  HTTP=NO                    ;;
    195197        --without-http-cache)            HTTP_CACHE=NO              ;;
    cat << END 
    347349
    348350  --with-file-aio                    enable file AIO support
    349351  --with-ipv6                        enable IPv6 support
     352  --with-systemd                     enable systemd socket support
    350353
    351354  --with-http_ssl_module             enable ngx_http_ssl_module
    352355  --with-http_realip_module          enable ngx_http_realip_module
  • auto/os/linux

    diff --git a/auto/os/linux b/auto/os/linux
    index c506d3d..470528f 100644
    a b ngx_feature_test="cpu_set_t mask; 
    134134. auto/feature
    135135
    136136
     137# systemd()
     138
     139if [ $NGX_SYSTEMD = YES ]; then
     140    ngx_feature="systemd()"
     141    ngx_feature_name="NGX_HAVE_SYSTEMD"
     142    ngx_feature_run=yes
     143    ngx_feature_incs="#include <systemd/sd-daemon.h>"
     144    ngx_feature_path=
     145    ngx_feature_libs=-lsystemd-daemon
     146    ngx_feature_test="sd_is_socket(1, 0, 0, 0);"
     147    . auto/feature
     148   
     149    if [ $ngx_found = yes ]; then
     150        CORE_LIBS="$CORE_LIBS -lsystemd-daemon"
     151    fi
     152fi
     153
     154
    137155# crypt_r()
    138156
    139157ngx_feature="crypt_r()"
  • src/core/ngx_inet.c

    diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c
    index 3db0136..c8302fc 100644
    a b  
    88#include <ngx_config.h>
    99#include <ngx_core.h>
    1010
     11#if (NGX_HAVE_SYSTEMD)
     12#include <systemd/sd-daemon.h>
     13#endif
    1114
    1215static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u);
    1316static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u);
    1417static ngx_int_t ngx_parse_inet6_url(ngx_pool_t *pool, ngx_url_t *u);
     18static ngx_int_t ngx_parse_file_descriptor_url(ngx_pool_t *pool, ngx_url_t *u);
    1519
    1620
    1721in_addr_t
    ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u) 
    522526        return ngx_parse_unix_domain_url(pool, u);
    523527    }
    524528
     529    if (ngx_strncasecmp(p, (u_char *) "fd:", 3) == 0) {
     530        return ngx_parse_file_descriptor_url(pool, u);
     531    }
     532
    525533    if (p[0] == '[') {
    526534        return ngx_parse_inet6_url(pool, u);
    527535    }
    ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u) 
    607615#endif
    608616}
    609617
     618static ngx_int_t
     619ngx_parse_file_descriptor_url(ngx_pool_t *pool, ngx_url_t *u)
     620{
     621#if (NGX_HAVE_SYSTEMD)
     622    u_char               *path;
     623    size_t                len;
     624    socklen_t             l;
     625    int                   fd;
     626    u_char                printable[256];
     627    struct sockaddr      *sa;
     628    struct sockaddr_in   *sin;
     629#if (NGX_HAVE_INET6)
     630    struct sockaddr_in6  *sin6;
     631#endif
     632#if (NGX_HAVE_UNIX_DOMAIN)
     633    struct sockaddr_un   *saun;
     634#endif
     635
     636    printf("Parsing listening URL: %s\n", u->url.data);
     637
     638    // This doesn't seem to be used for fd: listeners, but validate that assumption.
     639    if (u->uri_part) {
     640        u->err = "u->uri_part is unsupported for file descriptors";
     641        return NGX_ERROR;
     642    }
     643
     644    // Truncate the preceding "fd:" and ensure there's text left.
     645    path = u->url.data + 3;
     646    len = u->url.len - 3;
     647    if (len == 0) {
     648        u->err = "No number specified for the listening file descriptor.";
     649        return NGX_ERROR;
     650    }
     651
     652    // Convert the fd text to a numeric file descriptor.
     653    fd = ngx_atoi(path, len);
     654    printf("Parsed file descriptor #%d\n", fd);
     655
     656    // Check that it's the proper type of socket.
     657    if (!sd_is_socket(fd, 0, SOCK_STREAM, 1)) {
     658        u->err = "the systemd file descriptor passed in is not is listening, streaming socket";
     659        return NGX_ERROR;
     660    }
     661   
     662    u->fd = fd;
     663    sa = (struct sockaddr *) &u->sockaddr;
     664    l = sizeof(sa);
     665   
     666#if (NGX_HAVE_UNIX_DOMAIN)
     667    // Bump up the allocation if it's a Unix domain socket.
     668    if (sd_is_socket_unix(fd, SOCK_STREAM, 1, NULL, 0) > 0) {
     669        printf("Reallocating for socket size %lu\n", sizeof(struct sockaddr_un));
     670        sa = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
     671        if (sa == NULL) {
     672            return NGX_ERROR;
     673        }
     674        memset(sa, 0, sizeof(struct sockaddr_un));
     675        l = sizeof(struct sockaddr_un);
     676    }
     677#endif
     678
     679    // Get the socket information from the file descriptor.
     680    if (getsockname(u->fd, sa, &l) < 0) {
     681        u->err = "Couldn't read socket information out of the specified file descriptor.";
     682        return NGX_ERROR;
     683    }
     684   
     685    u->family = sa->sa_family;
     686
     687    // Get type-specific information.
     688    if (u->family == AF_INET) {
     689        printf("INET\n");
     690        sin = (struct sockaddr_in *) sa;
     691        u->socklen = sizeof(struct sockaddr_in);
     692        u->port = ntohs(sin->sin_port);
     693        u->no_port = 1;
     694        sin->sin_family = AF_INET;
     695
     696        if (&sin->sin_addr == NULL) {
     697            printf("Wildcard address.\n");
     698            u->wildcard = 1;
     699        }
     700    }
     701#if (NGX_HAVE_INET6)
     702    else if (u->family == AF_INET6) {
     703        printf("INET6\n");
     704        sin6 = (struct sockaddr_in6 *) sa;
     705        u->socklen = sizeof(struct sockaddr_in6);
     706        u->port = ntohs(sin6->sin6_port);
     707        u->no_port = 1;
     708        sin6->sin6_family = AF_INET6;
     709
     710        if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
     711            printf("Wildcard address.\n");
     712            u->wildcard = 1;
     713        }
     714    }
     715#endif
     716#if (NGX_HAVE_UNIX_DOMAIN)
     717    else if (u->family == AF_UNIX) {
     718        saun = (struct sockaddr_un *) sa;
     719        saun->sun_family = AF_UNIX;
     720        u->socklen = sizeof(struct sockaddr_un);       
     721        u->naddrs = 1;
     722        u->addrs = ngx_pcalloc(pool, sizeof(ngx_addr_t));
     723        if (u->addrs == NULL) {
     724            return NGX_ERROR;
     725        }
     726        u->addrs[0].sockaddr = (struct sockaddr *) saun;
     727        u->addrs[0].socklen = sizeof(struct sockaddr_un);
     728        u->addrs[0].name.len = len + 2;
     729        u->addrs[0].name.data = u->url.data;
     730    }
     731#endif
     732    else {
     733        u->err = "File descriptor uses a socket family whose support is not compiled in";
     734        return NGX_ERROR;
     735    }
     736
     737    // Get a human-readable/printable representation of the socket address.
     738    ngx_sock_ntop(sa, printable, sizeof(printable), u->port);
     739
     740    // Set the "host" to the file descriptor number text (for now).
     741    u->host.len = len + 1;
     742    u->host.data = path;
     743
     744    printf("Prepared socket: %s\n", printable);
     745
     746    return NGX_OK;
     747
     748#else
     749
     750    u->err = "the systemd file descriptor sockets are not supported on this platform";
     751
     752    return NGX_ERROR;
     753
     754#endif
     755}
     756
    610757
    611758static ngx_int_t
    612759ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u)
  • src/core/ngx_inet.h

    diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h
    index c5a3d76..6396e3e 100644
    a b typedef struct { 
    9999    ngx_uint_t                naddrs;
    100100
    101101    char                     *err;
     102
     103    // Pre-initialized file descriptor.
     104    int                       fd;
    102105} ngx_url_t;
    103106
    104107
  • src/http/ngx_http.c

    diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
    index f1f8a48..2bdcd90 100644
    a b ngx_http_add_listening(ngx_conf_t *cf, ngx_http_conf_addr_t *addr) 
    17911791    ls->setfib = addr->opt.setfib;
    17921792#endif
    17931793
     1794    ngx_log_error(NGX_LOG_INFO, cf->log, 0,
     1795                  "Looking for a file descriptor in the listening options.");
     1796    if (addr->opt.fd) {
     1797        ngx_log_error(NGX_LOG_INFO, cf->log, 0,
     1798                      "Found file descriptor %d on listening options. Using it.", addr->opt.fd);
     1799        ls->fd = addr->opt.fd;
     1800    }
     1801
    17941802    return ls;
    17951803}
    17961804
  • src/http/ngx_http_core_module.c

    diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
    index 826e4e5..5593b27 100644
    a b ngx_http_set_etag(ngx_http_request_t *r) 
    18201820{
    18211821    ngx_table_elt_t           *etag;
    18221822    ngx_http_core_loc_conf_t  *clcf;
    1823 
     1823   
    18241824    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
    18251825
    18261826    if (!clcf->etag) {
    ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 
    39053905
    39063906    ngx_memcpy(&lsopt.u.sockaddr, u.sockaddr, u.socklen);
    39073907
     3908    // If there's a file descriptor to inherit, use it.
     3909    if (u.fd) {
     3910        ngx_conf_log_error(NGX_LOG_INFO, cf, 0,
     3911                   "Found file descriptor #%d. Setting it as a listening option.\n",
     3912                    u.fd);
     3913        lsopt.fd = u.fd;
     3914    }
     3915
    39083916    lsopt.socklen = u.socklen;
    39093917    lsopt.backlog = NGX_LISTEN_BACKLOG;
    39103918    lsopt.rcvbuf = -1;
  • src/http/ngx_http_core_module.h

    diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
    index ff1c2df..21454d2 100644
    a b typedef struct { 
    6767    } u;
    6868
    6969    socklen_t                  socklen;
     70   
     71    // Inherited file descriptor.
     72    int                        fd;
    7073
    7174    unsigned                   set:1;
    7275    unsigned                   default_server:1;