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

File 0001-Socket-activation-support-for-systemd.patch, 9.7 KB (added by David Strauss, 21 months 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;