changeset 678:981b4c44593b NGINX_1_3_2

nginx 1.3.2 *) Change: the "single" parameter of the "keepalive" directive is now ignored. *) Change: SSL compression is now disabled when using all versions of OpenSSL, including ones prior to 1.0.0. *) Feature: it is now possible to use the "ip_hash" directive to balance IPv6 clients. *) Feature: the $status variable can now be used not only in the "log_format" directive. *) Bugfix: a segmentation fault might occur in a worker process on shutdown if the "resolver" directive was used. *) Bugfix: a segmentation fault might occur in a worker process if the ngx_http_mp4_module was used. *) Bugfix: in the ngx_http_mp4_module. *) Bugfix: a segmentation fault might occur in a worker process if conflicting wildcard server names were used. *) Bugfix: nginx might be terminated abnormally on a SIGBUS signal on ARM platform. *) Bugfix: an alert "sendmsg() failed (9: Bad file number)" on HP-UX while reconfiguration.
author Igor Sysoev <http://sysoev.ru>
date Tue, 26 Jun 2012 00:00:00 +0400
parents 47f0934d8824
children cad34cec7d3b
files CHANGES CHANGES.ru auto/endianess auto/endianness auto/lib/google-perftools/conf auto/modules auto/os/conf auto/unix src/core/nginx.h src/core/ngx_hash.c src/core/ngx_resolver.c src/event/ngx_event_openssl.c src/http/modules/ngx_http_geo_module.c src/http/modules/ngx_http_log_module.c src/http/modules/ngx_http_mp4_module.c src/http/modules/ngx_http_upstream_ip_hash_module.c src/http/modules/ngx_http_upstream_keepalive_module.c src/http/modules/perl/nginx.pm src/http/ngx_http_header_filter_module.c src/http/ngx_http_request.c src/http/ngx_http_request.h src/http/ngx_http_variables.c src/os/unix/ngx_errno.c src/os/unix/ngx_errno.h src/os/unix/ngx_posix_config.h src/os/unix/ngx_process_cycle.c
diffstat 26 files changed, 279 insertions(+), 131 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,36 @@
 
+Changes with nginx 1.3.2                                         26 Jun 2012
+
+    *) Change: the "single" parameter of the "keepalive" directive is now
+       ignored.
+
+    *) Change: SSL compression is now disabled when using all versions of
+       OpenSSL, including ones prior to 1.0.0.
+
+    *) Feature: it is now possible to use the "ip_hash" directive to balance
+       IPv6 clients.
+
+    *) Feature: the $status variable can now be used not only in the
+       "log_format" directive.
+
+    *) Bugfix: a segmentation fault might occur in a worker process on
+       shutdown if the "resolver" directive was used.
+
+    *) Bugfix: a segmentation fault might occur in a worker process if the
+       ngx_http_mp4_module was used.
+
+    *) Bugfix: in the ngx_http_mp4_module.
+
+    *) Bugfix: a segmentation fault might occur in a worker process if
+       conflicting wildcard server names were used.
+
+    *) Bugfix: nginx might be terminated abnormally on a SIGBUS signal on
+       ARM platform.
+
+    *) Bugfix: an alert "sendmsg() failed (9: Bad file number)" on HP-UX
+       while reconfiguration.
+
+
 Changes with nginx 1.3.1                                         05 Jun 2012
 
     *) Security: now nginx/Windows ignores trailing dot in URI path
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,35 @@
 
+Изменения в nginx 1.3.2                                           26.06.2012
+
+    *) Изменение: параметр single директивы keepalive теперь игнорируется.
+
+    *) Изменение: сжатие SSL теперь отключено в том числе при использовании
+       OpenSSL cтарее 1.0.0.
+
+    *) Добавление: директиву "ip_hash" теперь можно использовать для
+       балансировки IPv6 клиентов.
+
+    *) Добавление: переменную $status теперь можно использовать не только в
+       директиве log_format.
+
+    *) Исправление: при завершении рабочего процесса мог произойти
+       segmentation fault, если использовалась директива resolver.
+
+    *) Исправление: в рабочем процессе мог произойти segmentation fault,
+       если использовался модуль ngx_http_mp4_module.
+
+    *) Исправление: в модуле ngx_http_mp4_module.
+
+    *) Исправление: в рабочем процессе мог произойти segmentation fault,
+       если использовались конфликтующие имена серверов с масками.
+
+    *) Исправление: на платформе ARM nginx мог аварийно завершаться по
+       сигналу SIGBUS.
+
+    *) Исправление: во время переконфигурации на HP-UX в лог записывался
+       alert "sendmsg() failed (9: Bad file number)".
+
+
 Изменения в nginx 1.3.1                                           05.06.2012
 
     *) Безопасность: теперь nginx/Windows игнорирует точку в конце
deleted file mode 100644
--- a/auto/endianess
+++ /dev/null
@@ -1,45 +0,0 @@
-
-# Copyright (C) Igor Sysoev
-# Copyright (C) Nginx, Inc.
-
-
-echo $ngx_n "checking for system endianess ...$ngx_c"
-echo >> $NGX_ERR
-echo "checking for system endianess" >> $NGX_ERR
-
-
-cat << END > $NGX_AUTOTEST.c
-
-int main() {
-    int i = 0x11223344;
-    char *p;
-
-    p = (char *) &i;
-    if (*p == 0x44) return 0;
-    return 1;
-}
-
-END
-
-ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS \
-          -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_LD_OPT $ngx_feature_libs"
-
-eval "$ngx_test >> $NGX_AUTOCONF_ERR 2>&1"
-
-if [ -x $NGX_AUTOTEST ]; then
-    if $NGX_AUTOTEST >/dev/null 2>&1; then
-        echo " little endianess"
-        have=NGX_HAVE_LITTLE_ENDIAN . auto/have
-    else
-        echo " big endianess"
-    fi
-
-    rm $NGX_AUTOTEST*
-
-else
-    rm $NGX_AUTOTEST*
-
-    echo
-    echo "$0: error: can not detect system endianess"
-    exit 1
-fi
new file mode 100644
--- /dev/null
+++ b/auto/endianness
@@ -0,0 +1,45 @@
+
+# Copyright (C) Igor Sysoev
+# Copyright (C) Nginx, Inc.
+
+
+echo $ngx_n "checking for system byte ordering ...$ngx_c"
+echo >> $NGX_ERR
+echo "checking for system byte ordering" >> $NGX_ERR
+
+
+cat << END > $NGX_AUTOTEST.c
+
+int main() {
+    int i = 0x11223344;
+    char *p;
+
+    p = (char *) &i;
+    if (*p == 0x44) return 0;
+    return 1;
+}
+
+END
+
+ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS \
+          -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_LD_OPT $ngx_feature_libs"
+
+eval "$ngx_test >> $NGX_AUTOCONF_ERR 2>&1"
+
+if [ -x $NGX_AUTOTEST ]; then
+    if $NGX_AUTOTEST >/dev/null 2>&1; then
+        echo " little endian"
+        have=NGX_HAVE_LITTLE_ENDIAN . auto/have
+    else
+        echo " big endian"
+    fi
+
+    rm $NGX_AUTOTEST*
+
+else
+    rm $NGX_AUTOTEST*
+
+    echo
+    echo "$0: error: cannot detect system byte ordering"
+    exit 1
+fi
--- a/auto/lib/google-perftools/conf
+++ b/auto/lib/google-perftools/conf
@@ -29,6 +29,22 @@ if [ $ngx_found = no ]; then
 fi
 
 
+if [ $ngx_found = no ]; then
+
+    # MacPorts
+
+    ngx_feature="Google perftools in /opt/local/"
+
+    if [ $NGX_RPATH = YES ]; then
+        ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lprofiler"
+    else
+        ngx_feature_libs="-L/opt/local/lib -lprofiler"
+    fi
+
+    . auto/feature
+fi
+
+
 if [ $ngx_found = yes ]; then
     CORE_LIBS="$CORE_LIBS $ngx_feature_libs"
 
--- a/auto/modules
+++ b/auto/modules
@@ -223,6 +223,7 @@ fi
 
 if [ $HTTP_REALIP = YES ]; then
     have=NGX_HTTP_REALIP . auto/have
+    have=NGX_HTTP_X_FORWARDED_FOR . auto/have
     HTTP_MODULES="$HTTP_MODULES $HTTP_REALIP_MODULE"
     HTTP_SRCS="$HTTP_SRCS $HTTP_REALIP_SRCS"
 fi
@@ -233,12 +234,13 @@ if [ $HTTP_STATUS = YES ]; then
 fi
 
 if [ $HTTP_GEO = YES ]; then
-    have=NGX_HTTP_GEO . auto/have
+    have=NGX_HTTP_X_FORWARDED_FOR . auto/have
     HTTP_MODULES="$HTTP_MODULES $HTTP_GEO_MODULE"
     HTTP_SRCS="$HTTP_SRCS $HTTP_GEO_SRCS"
 fi
 
 if [ $HTTP_GEOIP = YES ]; then
+    have=NGX_HTTP_X_FORWARDED_FOR . auto/have
     HTTP_MODULES="$HTTP_MODULES $HTTP_GEOIP_MODULE"
     HTTP_SRCS="$HTTP_SRCS $HTTP_GEOIP_SRCS"
 fi
@@ -273,7 +275,7 @@ if [ $HTTP_SSL = YES ]; then
 fi
 
 if [ $HTTP_PROXY = YES ]; then
-    have=NGX_HTTP_PROXY . auto/have
+    have=NGX_HTTP_X_FORWARDED_FOR . auto/have
     #USE_MD5=YES
     HTTP_MODULES="$HTTP_MODULES $HTTP_PROXY_MODULE"
     HTTP_DEPS="$HTTP_DEPS $HTTP_PROXY_DEPS"
--- a/auto/os/conf
+++ b/auto/os/conf
@@ -48,6 +48,7 @@ case "$NGX_PLATFORM" in
         CORE_DEPS="$UNIX_DEPS $POSIX_DEPS"
         CORE_SRCS="$UNIX_SRCS"
         CC_AUX_FLAGS="$CC_AUX_FLAGS -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1"
+        CC_AUX_FLAGS="$CC_AUX_FLAGS -D_HPUX_ALT_XOPEN_SOCKET_API"
     ;;
 
     OSF1:*)
@@ -93,6 +94,7 @@ case "$NGX_MACHINE" in
     ;;
 
     *)
+        have=NGX_ALIGNMENT value=16 . auto/define
         NGX_MACH_CACHE_LINE=32
     ;;
 
--- a/auto/unix
+++ b/auto/unix
@@ -464,7 +464,7 @@ ngx_type="rlim_t"; ngx_types="int"; . au
 
 . auto/types/uintptr_t
 
-. auto/endianess
+. auto/endianness
 
 ngx_type="size_t"; . auto/types/sizeof
 ngx_param=NGX_MAX_SIZE_T_VALUE; ngx_value=$ngx_max_value; . auto/types/value
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,8 +9,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version      1003001
-#define NGINX_VERSION      "1.3.1"
+#define nginx_version      1003002
+#define NGINX_VERSION      "1.3.2"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_hash.c
+++ b/src/core/ngx_hash.c
@@ -924,17 +924,6 @@ wildcard:
     }
 
 
-    hk = ngx_array_push(hwc);
-    if (hk == NULL) {
-        return NGX_ERROR;
-    }
-
-    hk->key.len = last - 1;
-    hk->key.data = p;
-    hk->key_hash = 0;
-    hk->value = value;
-
-
     /* check conflicts in wildcard hash */
 
     name = keys->elts;
@@ -972,5 +961,18 @@ wildcard:
 
     ngx_memcpy(name->data, key->data + skip, name->len);
 
+
+    /* add to wildcard hash */
+
+    hk = ngx_array_push(hwc);
+    if (hk == NULL) {
+        return NGX_ERROR;
+    }
+
+    hk->key.len = last - 1;
+    hk->key.data = p;
+    hk->key_hash = 0;
+    hk->value = value;
+
     return NGX_OK;
 }
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -96,7 +96,7 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_
 {
     ngx_str_t              s;
     ngx_url_t              u;
-    ngx_uint_t             i;
+    ngx_uint_t             i, j;
     ngx_resolver_t        *r;
     ngx_pool_cleanup_t    *cln;
     ngx_udp_connection_t  *uc;
@@ -184,16 +184,18 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_
             return NULL;
         }
 
-        uc = ngx_array_push(&r->udp_connections);
+        uc = ngx_array_push_n(&r->udp_connections, u.naddrs);
         if (uc == NULL) {
             return NULL;
         }
 
-        ngx_memzero(uc, sizeof(ngx_udp_connection_t));
-
-        uc->sockaddr = u.addrs->sockaddr;
-        uc->socklen = u.addrs->socklen;
-        uc->server = u.addrs->name;
+        ngx_memzero(uc, u.naddrs * sizeof(ngx_udp_connection_t));
+
+        for (j = 0; j < u.naddrs; j++) {
+            uc[j].sockaddr = u.addrs[j].sockaddr;
+            uc[j].socklen = u.addrs[j].socklen;
+            uc[j].server = u.addrs[j].name;
+        }
     }
 
     return r;
@@ -977,12 +979,11 @@ ngx_resolver_resend(ngx_resolver_t *r, n
 
         if (rn->waiting) {
 
-            if (ngx_resolver_send_query(r, rn) == NGX_OK) {
-
-                rn->expire = now + r->resend_timeout;
-
-                ngx_queue_insert_head(queue, &rn->queue);
-            }
+            (void) ngx_resolver_send_query(r, rn);
+
+            rn->expire = now + r->resend_timeout;
+
+            ngx_queue_insert_head(queue, q);
 
             continue;
         }
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -94,6 +94,24 @@ ngx_ssl_init(ngx_log_t *log)
 
     OpenSSL_add_all_algorithms();
 
+#ifndef SSL_OP_NO_COMPRESSION
+    {
+    /*
+     * Disable gzip compression in OpenSSL prior to 1.0.0 version,
+     * this saves about 522K per connection.
+     */
+    int                 i, n;
+    STACK_OF(SSL_COMP)  *ssl_comp_methods;
+
+    ssl_comp_methods = SSL_COMP_get_compression_methods();
+    n = sk_SSL_COMP_num(ssl_comp_methods);
+
+    for (i = 0; i < n; i++) {
+        (void) sk_SSL_COMP_delete(ssl_comp_methods, i);
+    }
+    }
+#endif
+
     ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
 
     if (ngx_ssl_connection_index == -1) {
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -145,7 +145,7 @@ typedef struct {
     u_char    GEORNG[6];
     u_char    version;
     u_char    ptr_size;
-    uint32_t  endianess;
+    uint32_t  endianness;
     uint32_t  crc32;
 } ngx_http_geo_header_t;
 
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -584,10 +584,7 @@ ngx_http_log_status(ngx_http_request_t *
         status = r->headers_out.status;
 
     } else if (r->http_version == NGX_HTTP_VERSION_9) {
-        *buf++ = '0';
-        *buf++ = '0';
-        *buf++ = '9';
-        return buf;
+        status = 9;
 
     } else {
         status = 0;
--- a/src/http/modules/ngx_http_mp4_module.c
+++ b/src/http/modules/ngx_http_mp4_module.c
@@ -1024,6 +1024,10 @@ ngx_http_mp4_read_moov_atom(ngx_http_mp4
                          + NGX_HTTP_MP4_MOOV_BUFFER_EXCESS * no_mdat;
     }
 
+    if (ngx_http_mp4_read(mp4, (size_t) atom_data_size) != NGX_OK) {
+        return NGX_ERROR;
+    }
+
     mp4->trak.elts = &mp4->traks;
     mp4->trak.size = sizeof(ngx_http_mp4_trak_t);
     mp4->trak.nalloc = 2;
@@ -1044,6 +1048,12 @@ ngx_http_mp4_read_moov_atom(ngx_http_mp4
         mp4->buffer_start = mp4->buffer_pos;
         mp4->buffer_size = NGX_HTTP_MP4_MOOV_BUFFER_EXCESS;
 
+        if (mp4->buffer_start + mp4->buffer_size > mp4->buffer_end) {
+            mp4->buffer = NULL;
+            mp4->buffer_pos = NULL;
+            mp4->buffer_end = NULL;
+        }
+
     } else {
         /* skip atoms after moov atom */
         mp4->offset = mp4->end;
@@ -2488,7 +2498,13 @@ found:
 
     ngx_mp4_set_32value(entry->chunk, 1);
 
-    if (trak->chunk_samples) {
+    if (trak->chunk_samples && next_chunk - trak->start_chunk == 2) {
+
+        /* last chunk in the entry */
+
+        ngx_mp4_set_32value(entry->samples, samples - trak->chunk_samples);
+
+    } else if (trak->chunk_samples) {
 
         first = &trak->stsc_chunk_entry;
         ngx_mp4_set_32value(first->chunk, 1);
@@ -2504,6 +2520,7 @@ found:
 
         ngx_mp4_set_32value(entry->chunk, 2);
 
+        entries++;
         atom_size += sizeof(ngx_mp4_stsc_entry_t);
     }
 
--- a/src/http/modules/ngx_http_upstream_ip_hash_module.c
+++ b/src/http/modules/ngx_http_upstream_ip_hash_module.c
@@ -16,7 +16,8 @@ typedef struct {
 
     ngx_uint_t                         hash;
 
-    u_char                             addr[3];
+    u_char                             addrlen;
+    u_char                            *addr;
 
     u_char                             tries;
 
@@ -76,7 +77,10 @@ ngx_module_t  ngx_http_upstream_ip_hash_
 };
 
 
-ngx_int_t
+static u_char ngx_http_upstream_ip_hash_pseudo_addr[3];
+
+
+static ngx_int_t
 ngx_http_upstream_init_ip_hash(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us)
 {
     if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) {
@@ -93,8 +97,10 @@ static ngx_int_t
 ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r,
     ngx_http_upstream_srv_conf_t *us)
 {
-    u_char                                 *p;
     struct sockaddr_in                     *sin;
+#if (NGX_HAVE_INET6)
+    struct sockaddr_in6                    *sin6;
+#endif
     ngx_http_upstream_ip_hash_peer_data_t  *iphp;
 
     iphp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_ip_hash_peer_data_t));
@@ -110,20 +116,25 @@ ngx_http_upstream_init_ip_hash_peer(ngx_
 
     r->upstream->peer.get = ngx_http_upstream_get_ip_hash_peer;
 
-    /* AF_INET only */
+    switch (r->connection->sockaddr->sa_family) {
 
-    if (r->connection->sockaddr->sa_family == AF_INET) {
-
+    case AF_INET:
         sin = (struct sockaddr_in *) r->connection->sockaddr;
-        p = (u_char *) &sin->sin_addr.s_addr;
-        iphp->addr[0] = p[0];
-        iphp->addr[1] = p[1];
-        iphp->addr[2] = p[2];
+        iphp->addr = (u_char *) &sin->sin_addr.s_addr;
+        iphp->addrlen = 3;
+        break;
 
-    } else {
-        iphp->addr[0] = 0;
-        iphp->addr[1] = 0;
-        iphp->addr[2] = 0;
+#if (NGX_HAVE_INET6)
+    case AF_INET6:
+        sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
+        iphp->addr = (u_char *) &sin6->sin6_addr.s6_addr;
+        iphp->addrlen = 16;
+        break;
+#endif
+
+    default:
+        iphp->addr = ngx_http_upstream_ip_hash_pseudo_addr;
+        iphp->addrlen = 3;
     }
 
     iphp->hash = 89;
@@ -163,7 +174,7 @@ ngx_http_upstream_get_ip_hash_peer(ngx_p
 
     for ( ;; ) {
 
-        for (i = 0; i < 3; i++) {
+        for (i = 0; i < iphp->addrlen; i++) {
             hash = (hash * 113 + iphp->addr[i]) % 6271;
         }
 
--- a/src/http/modules/ngx_http_upstream_keepalive_module.c
+++ b/src/http/modules/ngx_http_upstream_keepalive_module.c
@@ -12,7 +12,6 @@
 
 typedef struct {
     ngx_uint_t                         max_cached;
-    ngx_uint_t                         single;       /* unsigned:1 */
 
     ngx_queue_t                        cache;
     ngx_queue_t                        free;
@@ -223,36 +222,11 @@ ngx_http_upstream_get_keepalive_peer(ngx
 
     kp->failed = 0;
 
-    /* single pool of cached connections */
-
-    if (kp->conf->single && !ngx_queue_empty(&kp->conf->cache)) {
-
-        q = ngx_queue_head(&kp->conf->cache);
-
-        item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue);
-        c = item->connection;
-
-        ngx_queue_remove(q);
-        ngx_queue_insert_head(&kp->conf->free, q);
-
-        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
-                       "get keepalive peer: using connection %p", c);
-
-        c->idle = 0;
-        c->log = pc->log;
-        c->read->log = pc->log;
-        c->write->log = pc->log;
-        c->pool->log = pc->log;
-
-        pc->connection = c;
-        pc->cached = 1;
-
-        return NGX_DONE;
-    }
+    /* ask balancer */
 
     rc = kp->original_get_peer(pc, kp->data);
 
-    if (kp->conf->single || rc != NGX_OK) {
+    if (rc != NGX_OK) {
         return rc;
     }
 
@@ -552,7 +526,8 @@ ngx_http_upstream_keepalive(ngx_conf_t *
     for (i = 2; i < cf->args->nelts; i++) {
 
         if (ngx_strcmp(value[i].data, "single") == 0) {
-            kcf->single = 1;
+            ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+                               "the \"single\" parameter is deprecated");
             continue;
         }
 
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -50,7 +50,7 @@ our @EXPORT = qw(
     HTTP_INSUFFICIENT_STORAGE
 );
 
-our $VERSION = '1.3.1';
+our $VERSION = '1.3.2';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -395,7 +395,7 @@ ngx_http_header_filter(ngx_http_request_
         }
 
     } else {
-        len += sizeof("Connection: closed" CRLF) - 1;
+        len += sizeof("Connection: close" CRLF) - 1;
     }
 
 #if (NGX_HTTP_GZIP)
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -138,7 +138,7 @@ ngx_http_header_t  ngx_http_headers_in[]
     { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
                  ngx_http_process_header_line },
 
-#if (NGX_HTTP_PROXY || NGX_HTTP_REALIP || NGX_HTTP_GEO)
+#if (NGX_HTTP_X_FORWARDED_FOR)
     { ngx_string("X-Forwarded-For"),
                  offsetof(ngx_http_headers_in_t, x_forwarded_for),
                  ngx_http_process_header_line },
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -192,7 +192,7 @@ typedef struct {
 
     ngx_table_elt_t                  *keep_alive;
 
-#if (NGX_HTTP_PROXY || NGX_HTTP_REALIP || NGX_HTTP_GEO)
+#if (NGX_HTTP_X_FORWARDED_FOR)
     ngx_table_elt_t                  *x_forwarded_for;
 #endif
 
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -77,6 +77,8 @@ static ngx_int_t ngx_http_variable_reque
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_variable_request_body_file(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_variable_status(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
 
 static ngx_int_t ngx_http_variable_sent_content_type(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
@@ -132,7 +134,7 @@ static ngx_http_variable_t  ngx_http_cor
       offsetof(ngx_http_request_t, headers_in.via), 0, 0 },
 #endif
 
-#if (NGX_HTTP_PROXY || NGX_HTTP_REALIP)
+#if (NGX_HTTP_X_FORWARDED_FOR)
     { ngx_string("http_x_forwarded_for"), NULL, ngx_http_variable_header,
       offsetof(ngx_http_request_t, headers_in.x_forwarded_for), 0, 0 },
 #endif
@@ -225,6 +227,10 @@ static ngx_http_variable_t  ngx_http_cor
       ngx_http_variable_request_body_file,
       0, 0, 0 },
 
+    { ngx_string("status"), NULL,
+      ngx_http_variable_status, 0,
+      NGX_HTTP_VAR_NOCACHEABLE, 0 },
+
     { ngx_string("sent_http_content_type"), NULL,
       ngx_http_variable_sent_content_type, 0, 0, 0 },
 
@@ -1456,6 +1462,39 @@ ngx_http_variable_body_bytes_sent(ngx_ht
 
 
 static ngx_int_t
+ngx_http_variable_status(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    ngx_uint_t  status;
+
+    v->data = ngx_pnalloc(r->pool, NGX_INT_T_LEN);
+    if (v->data == NULL) {
+        return NGX_ERROR;
+    }
+
+    if (r->err_status) {
+        status = r->err_status;
+
+    } else if (r->headers_out.status) {
+        status = r->headers_out.status;
+
+    } else if (r->http_version == NGX_HTTP_VERSION_9) {
+        status = 9;
+
+    } else {
+        status = 0;
+    }
+
+    v->len = ngx_sprintf(v->data, "%03ui", status) - v->data;
+    v->valid = 1;
+    v->no_cacheable = 0;
+    v->not_found = 0;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
 ngx_http_variable_sent_content_type(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
--- a/src/os/unix/ngx_errno.c
+++ b/src/os/unix/ngx_errno.c
@@ -42,7 +42,7 @@ ngx_strerror(ngx_err_t err, u_char *errs
 }
 
 
-ngx_uint_t
+ngx_int_t
 ngx_strerror_init(void)
 {
     char       *msg;
--- a/src/os/unix/ngx_errno.h
+++ b/src/os/unix/ngx_errno.h
@@ -69,7 +69,7 @@ typedef int               ngx_err_t;
 
 
 u_char *ngx_strerror(ngx_err_t err, u_char *errstr, size_t size);
-ngx_uint_t ngx_strerror_init(void);
+ngx_int_t ngx_strerror_init(void);
 
 
 #endif /* _NGX_ERRNO_H_INCLUDED_ */
--- a/src/os/unix/ngx_posix_config.h
+++ b/src/os/unix/ngx_posix_config.h
@@ -12,6 +12,7 @@
 #if (NGX_HPUX)
 #define _XOPEN_SOURCE
 #define _XOPEN_SOURCE_EXTENDED  1
+#define _HPUX_ALT_XOPEN_SOCKET_API
 #endif
 
 
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -711,6 +711,8 @@ ngx_master_process_exit(ngx_cycle_t *cyc
     ngx_exit_log.file = &ngx_exit_log_file;
 
     ngx_exit_cycle.log = &ngx_exit_log;
+    ngx_exit_cycle.files = ngx_cycle->files;
+    ngx_exit_cycle.files_n = ngx_cycle->files_n;
     ngx_cycle = &ngx_exit_cycle;
 
     ngx_destroy_pool(cycle->pool);
@@ -1054,6 +1056,8 @@ ngx_worker_process_exit(ngx_cycle_t *cyc
     ngx_exit_log.file = &ngx_exit_log_file;
 
     ngx_exit_cycle.log = &ngx_exit_log;
+    ngx_exit_cycle.files = ngx_cycle->files;
+    ngx_exit_cycle.files_n = ngx_cycle->files_n;
     ngx_cycle = &ngx_exit_cycle;
 
     ngx_destroy_pool(cycle->pool);