changeset 646:615b5ea36fc0 NGINX_1_1_7

nginx 1.1.7 *) Feature: support of several resolvers in the "resolver" directive. Thanks to Kirill A. Korinskiy. *) Bugfix: a segmentation fault occurred on start or while reconfiguration if the "ssl" directive was used at http level and there was no "ssl_certificate" defined. *) Bugfix: reduced memory consumption while proxying of big files if they were buffered to disk. *) Bugfix: a segmentation fault might occur in a worker process if "proxy_http_version 1.1" directive was used. *) Bugfix: in the "expires @time" directive.
author Igor Sysoev <http://sysoev.ru>
date Mon, 31 Oct 2011 00:00:00 +0400
parents e461dead01e9
children bec017127243
files CHANGES CHANGES.ru README auto/cc/name auto/options conf/mime.types src/core/nginx.c src/core/nginx.h src/core/ngx_inet.c src/core/ngx_resolver.c src/core/ngx_resolver.h src/core/ngx_slab.c src/event/ngx_event_openssl.c src/event/ngx_event_pipe.c src/event/ngx_event_pipe.h src/http/modules/ngx_http_headers_filter_module.c src/http/modules/ngx_http_ssl_module.c src/http/modules/perl/nginx.pm src/http/ngx_http_core_module.c src/mail/ngx_mail_auth_http_module.c src/mail/ngx_mail_core_module.c src/os/unix/ngx_darwin.h src/os/unix/ngx_darwin_config.h src/os/unix/ngx_darwin_init.c src/os/unix/ngx_files.c src/os/unix/ngx_freebsd.h src/os/unix/ngx_freebsd_config.h src/os/unix/ngx_freebsd_init.c src/os/unix/ngx_linux_config.h src/os/unix/ngx_os.h src/os/unix/ngx_posix_config.h src/os/unix/ngx_solaris_config.h
diffstat 32 files changed, 343 insertions(+), 223 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,22 @@
 
+Changes with nginx 1.1.7                                         31 Oct 2011
+
+    *) Feature: support of several resolvers in the "resolver" directive.
+       Thanks to Kirill A. Korinskiy.
+
+    *) Bugfix: a segmentation fault occurred on start or while
+       reconfiguration if the "ssl" directive was used at http level and
+       there was no "ssl_certificate" defined.
+
+    *) Bugfix: reduced memory consumption while proxying of big files if
+       they were buffered to disk.
+
+    *) Bugfix: a segmentation fault might occur in a worker process if
+       "proxy_http_version 1.1" directive was used.
+
+    *) Bugfix: in the "expires @time" directive.
+
+
 Changes with nginx 1.1.6                                         17 Oct 2011
 
     *) Change in internal API: now module context data are cleared while
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,22 @@
 
+Изменения в nginx 1.1.7                                           31.10.2011
+
+    *) Добавление: поддержка нескольких DNS серверов в директиве "resolver".
+       Спасибо Кириллу Коринскому.
+
+    *) Исправление: на старте или во время переконфигурации происходил
+       segmentation fault, если директива ssl использовалась на уровне http
+       и не был указан ssl_certificate.
+
+    *) Исправление: уменьшено потребление памяти при проксировании больших
+       файлов, если они буферизировались на диск.
+
+    *) Исправление: в рабочем процессе мог произойти segmentation fault,
+       если использовалась директива "proxy_http_version 1.1".
+
+    *) Исправление: в директиве "expires @time".
+
+
 Изменения в nginx 1.1.6                                           17.10.2011
 
     *) Изменение во внутреннем API: теперь при внутреннем редиректе в
--- a/README
+++ b/README
@@ -1,4 +1,3 @@
 
-The Russian documentation is available at http://sysoev.ru/nginx/
-The English documentation is available at http://nginx.net
+Documentation is available at http://nginx.org
 
--- a/auto/cc/name
+++ b/auto/cc/name
@@ -25,6 +25,13 @@ fi
 
 if [ "$CC" = cl ]; then
     if `$NGX_WINE $CC -v 2>&1 \
+        | grep '^Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16' \
+        >/dev/null 2>&1`; then
+
+        NGX_CC_NAME=msvc10
+        echo " + using Microsoft Visual C++ 10 compiler"
+
+    else if `$NGX_WINE $CC -v 2>&1 \
         | grep '^Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14' \
         >/dev/null 2>&1`; then
 
@@ -43,6 +50,7 @@ if [ "$CC" = cl ]; then
         echo " + using Microsoft Visual C++ compiler"
     fi
     fi
+    fi
 
 else
 if [ "$CC" = wcl386 ]; then
--- a/auto/options
+++ b/auto/options
@@ -306,21 +306,21 @@ if [ $help = yes ]; then
 
 cat << END
 
-  --help                             this message
+  --help                             print this message
 
-  --prefix=PATH                      set the installation prefix
-  --sbin-path=PATH                   set path to the nginx binary file
-  --conf-path=PATH                   set path to the nginx.conf file
-  --error-log-path=PATH              set path to the error log
-  --pid-path=PATH                    set path to nginx.pid file
-  --lock-path=PATH                   set path to nginx.lock file
+  --prefix=PATH                      set installation prefix
+  --sbin-path=PATH                   set nginx binary pathname
+  --conf-path=PATH                   set nginx.conf pathname
+  --error-log-path=PATH              set error log pathname
+  --pid-path=PATH                    set nginx.pid pathname
+  --lock-path=PATH                   set nginx.lock pathname
 
-  --user=USER                        set non-privilege user
-                                     for the worker processes
-  --group=GROUP                      set non-privilege group
-                                     for the worker processes
+  --user=USER                        set non-privileged user for
+                                     worker processes
+  --group=GROUP                      set non-privileged group for
+                                     worker processes
 
-  --builddir=DIR                     set the build directory
+  --builddir=DIR                     set build directory
 
   --with-rtsig_module                enable rtsig module
   --with-select_module               enable select module
@@ -328,8 +328,8 @@ cat << END
   --with-poll_module                 enable poll module
   --without-poll_module              disable poll module
 
-  --with-file-aio                    enable file aio support
-  --with-ipv6                        enable ipv6 support
+  --with-file-aio                    enable file AIO support
+  --with-ipv6                        enable IPv6 support
 
   --with-http_ssl_module             enable ngx_http_ssl_module
   --with-http_realip_module          enable ngx_http_realip_module
@@ -372,17 +372,20 @@ cat << END
                                      disable ngx_http_upstream_ip_hash_module
 
   --with-http_perl_module            enable ngx_http_perl_module
-  --with-perl_modules_path=PATH      set path to the perl modules
-  --with-perl=PATH                   set path to the perl binary
+  --with-perl_modules_path=PATH      set Perl modules path
+  --with-perl=PATH                   set perl binary pathname
 
-  --http-log-path=PATH               set path to the http access log
-  --http-client-body-temp-path=PATH  set path to the http client request body
-                                     temporary files
-  --http-proxy-temp-path=PATH        set path to the http proxy temporary files
-  --http-fastcgi-temp-path=PATH      set path to the http fastcgi temporary
-                                     files
-  --http-uwsgi-temp-path=PATH        set path to the http uwsgi temporary files
-  --http-scgi-temp-path=PATH         set path to the http scgi temporary files
+  --http-log-path=PATH               set http access log pathname
+  --http-client-body-temp-path=PATH  set path to store
+                                     http client request body temporary files
+  --http-proxy-temp-path=PATH        set path to store
+                                     http proxy temporary files
+  --http-fastcgi-temp-path=PATH      set path to store
+                                     http fastcgi temporary files
+  --http-uwsgi-temp-path=PATH        set path to store
+                                     http uwsgi temporary files
+  --http-scgi-temp-path=PATH         set path to store
+                                     http scgi temporary files
 
   --without-http                     disable HTTP server
   --without-http-cache               disable HTTP cache
@@ -398,40 +401,40 @@ cat << END
 
   --add-module=PATH                  enable an external module
 
-  --with-cc=PATH                     set path to C compiler
-  --with-cpp=PATH                    set path to C preprocessor
-  --with-cc-opt=OPTIONS              set additional options for C compiler
-  --with-ld-opt=OPTIONS              set additional options for linker
-  --with-cpu-opt=CPU                 build for specified CPU, the valid values:
+  --with-cc=PATH                     set C compiler pathname
+  --with-cpp=PATH                    set C preprocessor pathname
+  --with-cc-opt=OPTIONS              set additional C compiler options
+  --with-ld-opt=OPTIONS              set additional linker options
+  --with-cpu-opt=CPU                 build for the specified CPU, valid values:
                                      pentium, pentiumpro, pentium3, pentium4,
                                      athlon, opteron, sparc32, sparc64, ppc64
 
   --without-pcre                     disable PCRE library usage
   --with-pcre                        force PCRE library usage
   --with-pcre=DIR                    set path to PCRE library sources
-  --with-pcre-opt=OPTIONS            set additional options for PCRE building
+  --with-pcre-opt=OPTIONS            set additional build options for PCRE
 
   --with-md5=DIR                     set path to md5 library sources
-  --with-md5-opt=OPTIONS             set additional options for md5 building
+  --with-md5-opt=OPTIONS             set additional build options for md5
   --with-md5-asm                     use md5 assembler sources
 
   --with-sha1=DIR                    set path to sha1 library sources
-  --with-sha1-opt=OPTIONS            set additional options for sha1 building
+  --with-sha1-opt=OPTIONS            set additional build options for sha1
   --with-sha1-asm                    use sha1 assembler sources
 
   --with-zlib=DIR                    set path to zlib library sources
-  --with-zlib-opt=OPTIONS            set additional options for zlib building
+  --with-zlib-opt=OPTIONS            set additional build options for zlib
   --with-zlib-asm=CPU                use zlib assembler sources optimized
-                                     for specified CPU, the valid values:
+                                     for the specified CPU, valid values:
                                      pentium, pentiumpro
 
   --with-libatomic                   force libatomic_ops library usage
   --with-libatomic=DIR               set path to libatomic_ops library sources
 
   --with-openssl=DIR                 set path to OpenSSL library sources
-  --with-openssl-opt=OPTIONS         set additional options for OpenSSL building
+  --with-openssl-opt=OPTIONS         set additional build options for OpenSSL
 
-  --with-debug                       enable the debugging logging
+  --with-debug                       enable debug logging
 
 END
 
--- a/conf/mime.types
+++ b/conf/mime.types
@@ -62,6 +62,7 @@ types {
     audio/midi                            mid midi kar;
     audio/mpeg                            mp3;
     audio/ogg                             ogg;
+    audio/x-m4a                           m4a;
     audio/x-realaudio                     ra;
 
     video/3gpp                            3gpp 3gp;
@@ -69,6 +70,7 @@ types {
     video/mpeg                            mpeg mpg;
     video/quicktime                       mov;
     video/x-flv                           flv;
+    video/x-m4v                           m4v;
     video/x-mng                           mng;
     video/x-ms-asf                        asx asf;
     video/x-ms-wmv                        wmv;
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -203,6 +203,8 @@ main(int argc, char *const *argv)
     ngx_cycle_t      *cycle, init_cycle;
     ngx_core_conf_t  *ccf;
 
+    ngx_debug_init();
+
     if (ngx_strerror_init() != NGX_OK) {
         return 1;
     }
@@ -260,10 +262,6 @@ main(int argc, char *const *argv)
         }
     }
 
-#if (NGX_FREEBSD)
-    ngx_debug_init();
-#endif
-
     /* TODO */ ngx_max_sockets = -1;
 
     ngx_time_init();
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version      1001006
-#define NGINX_VERSION      "1.1.6"
+#define nginx_version      1001007
+#define NGINX_VERSION      "1.1.7"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -671,7 +671,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx
 
         n = ngx_atoi(port, len);
 
-        if (n < 1 || n > 65536) {
+        if (n < 1 || n > 65535) {
             u->err = "invalid port";
             return NGX_ERROR;
         }
@@ -695,7 +695,7 @@ ngx_parse_inet_url(ngx_pool_t *pool, ngx
 
                 if (n != NGX_ERROR) {
 
-                    if (n < 1 || n > 65536) {
+                    if (n < 1 || n > 65535) {
                         u->err = "invalid port";
                         return NGX_ERROR;
                     }
@@ -835,7 +835,7 @@ ngx_parse_inet6_url(ngx_pool_t *pool, ng
 
             n = ngx_atoi(port, len);
 
-            if (n < 1 || n > 65536) {
+            if (n < 1 || n > 65535) {
                 u->err = "invalid port";
                 return NGX_ERROR;
             }
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -91,8 +91,10 @@ static u_char *ngx_resolver_log_error(ng
 
 
 ngx_resolver_t *
-ngx_resolver_create(ngx_conf_t *cf, ngx_addr_t *addr)
+ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
 {
+    ngx_url_t              u;
+    ngx_uint_t             i;
     ngx_resolver_t        *r;
     ngx_pool_cleanup_t    *cln;
     ngx_udp_connection_t  *uc;
@@ -109,6 +111,15 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_
         return NULL;
     }
 
+    if (n) {
+        if (ngx_array_init(&r->udp_connections, cf->pool, n,
+                           sizeof(ngx_udp_connection_t))
+            != NGX_OK)
+        {
+            return NULL;
+        }
+    }
+
     cln->data = r;
 
     r->event = ngx_calloc(sizeof(ngx_event_t), cf->log);
@@ -140,17 +151,27 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_
     r->log = &cf->cycle->new_log;
     r->log_level = NGX_LOG_ERR;
 
-    if (addr) {
-        uc = ngx_calloc(sizeof(ngx_udp_connection_t), cf->log);
+    for (i = 0; i < n; i++) {
+        ngx_memzero(&u, sizeof(ngx_url_t));
+
+        u.host = names[i];
+        u.port = 53;
+
+        if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err);
+            return NULL;
+        }
+
+        uc = ngx_array_push(&r->udp_connections);
         if (uc == NULL) {
             return NULL;
         }
 
-        r->udp_connection = uc;
-
-        uc->sockaddr = addr->sockaddr;
-        uc->socklen = addr->socklen;
-        uc->server = addr->name;
+        ngx_memzero(uc, sizeof(ngx_udp_connection_t));
+
+        uc->sockaddr = u.addrs->sockaddr;
+        uc->socklen = u.addrs->socklen;
+        uc->server = u.addrs->name;
 
         uc->log = cf->cycle->new_log;
         uc->log.handler = ngx_resolver_log_error;
@@ -167,6 +188,9 @@ ngx_resolver_cleanup(void *data)
 {
     ngx_resolver_t  *r = data;
 
+    ngx_uint_t             i;
+    ngx_udp_connection_t  *uc;
+
     if (r) {
         ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
                        "cleanup resolver");
@@ -179,12 +203,13 @@ ngx_resolver_cleanup(void *data)
             ngx_free(r->event);
         }
 
-        if (r->udp_connection) {
-            if (r->udp_connection->connection) {
-                ngx_close_connection(r->udp_connection->connection);
+
+        uc = r->udp_connections.elts;
+
+        for (i = 0; i < r->udp_connections.nelts; i++) {
+            if (uc[i].connection) {
+                ngx_close_connection(uc[i].connection);
             }
-
-            ngx_free(r->udp_connection);
         }
 
         ngx_free(r);
@@ -242,7 +267,7 @@ ngx_resolve_start(ngx_resolver_t *r, ngx
         }
     }
 
-    if (r->udp_connection == NULL) {
+    if (r->udp_connections.nelts == 0) {
         return NGX_NO_RESOLVER;
     }
 
@@ -826,7 +851,12 @@ ngx_resolver_send_query(ngx_resolver_t *
     ssize_t                n;
     ngx_udp_connection_t  *uc;
 
-    uc = r->udp_connection;
+    uc = r->udp_connections.elts;
+
+    uc = &uc[r->last_connection++];
+    if (r->last_connection == r->udp_connections.nelts) {
+        r->last_connection = 0;
+    }
 
     if (uc->connection == NULL) {
         if (ngx_udp_connect(uc) != NGX_OK) {
--- a/src/core/ngx_resolver.h
+++ b/src/core/ngx_resolver.h
@@ -77,16 +77,16 @@ typedef struct {
 typedef struct {
     /* has to be pointer because of "incomplete type" */
     ngx_event_t              *event;
-
-    /* TODO: DNS peers balancer */
-    /* STUB */
-    ngx_udp_connection_t     *udp_connection;
-
+    void                     *dummy;
     ngx_log_t                *log;
 
     /* ident must be after 3 pointers */
     ngx_int_t                 ident;
 
+    /* simple round robin DNS peers balancer */
+    ngx_array_t               udp_connections;
+    ngx_uint_t                last_connection;
+
     ngx_rbtree_t              name_rbtree;
     ngx_rbtree_node_t         name_sentinel;
 
@@ -123,8 +123,6 @@ struct ngx_resolver_ctx_s {
     in_addr_t                *addrs;
     in_addr_t                 addr;
 
-    /* TODO: DNS peers balancer ctx */
-
     ngx_resolver_handler_pt   handler;
     void                     *data;
     ngx_msec_t                timeout;
@@ -135,7 +133,8 @@ struct ngx_resolver_ctx_s {
 };
 
 
-ngx_resolver_t *ngx_resolver_create(ngx_conf_t *cf, ngx_addr_t *addr);
+ngx_resolver_t *ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names,
+    ngx_uint_t n);
 ngx_resolver_ctx_t *ngx_resolve_start(ngx_resolver_t *r,
     ngx_resolver_ctx_t *temp);
 ngx_int_t ngx_resolve_name(ngx_resolver_ctx_t *ctx);
--- a/src/core/ngx_slab.c
+++ b/src/core/ngx_slab.c
@@ -42,14 +42,14 @@
 
 #if (NGX_DEBUG_MALLOC)
 
-#define ngx_slab_junk(p, size)     ngx_memset(p, 0xD0, size)
+#define ngx_slab_junk(p, size)     ngx_memset(p, 0xA5, size)
 
 #else
 
-#if (NGX_FREEBSD)
+#if (NGX_HAVE_DEBUG_MALLOC)
 
 #define ngx_slab_junk(p, size)                                                \
-    if (ngx_freebsd_debug_malloc)  ngx_memset(p, 0xD0, size)
+    if (ngx_debug_malloc)          ngx_memset(p, 0xA5, size)
 
 #else
 
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -863,6 +863,13 @@ ngx_ssl_handle_recv(ngx_connection_t *c,
 
         ngx_log_error(NGX_LOG_NOTICE, c->log, 0, "SSL renegotiation disabled");
 
+        while (ERR_peek_error()) {
+            ngx_ssl_error(NGX_LOG_DEBUG, c->log, 0,
+                          "ignoring stale global SSL error");
+        }
+
+        ERR_clear_error();
+
         c->ssl->no_wait_shutdown = 1;
         c->ssl->no_send_shutdown = 1;
 
@@ -1352,19 +1359,37 @@ ngx_ssl_connection_error(ngx_connection_
         n = ERR_GET_REASON(ERR_peek_error());
 
             /* handshake failures */
-        if (n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG                     /*  129 */
+        if (n == SSL_R_BAD_CHANGE_CIPHER_SPEC                        /*  103 */
+            || n == SSL_R_BLOCK_CIPHER_PAD_IS_WRONG                  /*  129 */
             || n == SSL_R_DIGEST_CHECK_FAILED                        /*  149 */
+            || n == SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST              /*  151 */
+            || n == SSL_R_EXCESSIVE_MESSAGE_SIZE                     /*  152 */
             || n == SSL_R_LENGTH_MISMATCH                            /*  159 */
             || n == SSL_R_NO_CIPHERS_PASSED                          /*  182 */
             || n == SSL_R_NO_CIPHERS_SPECIFIED                       /*  183 */
+            || n == SSL_R_NO_COMPRESSION_SPECIFIED                   /*  187 */
             || n == SSL_R_NO_SHARED_CIPHER                           /*  193 */
             || n == SSL_R_RECORD_LENGTH_MISMATCH                     /*  213 */
+#ifdef SSL_R_PARSE_TLSEXT
+            || n == SSL_R_PARSE_TLSEXT                               /*  227 */
+#endif
             || n == SSL_R_UNEXPECTED_MESSAGE                         /*  244 */
             || n == SSL_R_UNEXPECTED_RECORD                          /*  245 */
             || n == SSL_R_UNKNOWN_ALERT_TYPE                         /*  246 */
             || n == SSL_R_UNKNOWN_PROTOCOL                           /*  252 */
             || n == SSL_R_WRONG_VERSION_NUMBER                       /*  267 */
             || n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC        /*  281 */
+#ifdef SSL_R_RENEGOTIATE_EXT_TOO_LONG
+            || n == SSL_R_RENEGOTIATE_EXT_TOO_LONG                   /*  335 */
+            || n == SSL_R_RENEGOTIATION_ENCODING_ERR                 /*  336 */
+            || n == SSL_R_RENEGOTIATION_MISMATCH                     /*  337 */
+#endif
+#ifdef SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED
+            || n == SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED       /*  338 */
+#endif
+#ifdef SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING
+            || n == SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING           /*  345 */
+#endif
             || n == 1000 /* SSL_R_SSLV3_ALERT_CLOSE_NOTIFY */
             || n == SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE             /* 1010 */
             || n == SSL_R_SSLV3_ALERT_BAD_RECORD_MAC                 /* 1020 */
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -15,8 +15,6 @@ static ngx_int_t ngx_event_pipe_write_to
 
 static ngx_int_t ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p);
 static ngx_inline void ngx_event_pipe_remove_shadow_links(ngx_buf_t *buf);
-static ngx_inline void ngx_event_pipe_free_shadow_raw_buf(ngx_chain_t **free,
-                                                          ngx_buf_t *buf);
 static ngx_int_t ngx_event_pipe_drain_chains(ngx_event_pipe_t *p);
 
 
@@ -576,17 +574,13 @@ ngx_event_pipe_write_to_downstream(ngx_e
             if (p->out) {
                 cl = p->out;
 
-                if (cl->buf->recycled
-                    && bsize + cl->buf->last - cl->buf->pos > p->busy_size)
-                {
-                    flush = 1;
-                    break;
+                if (cl->buf->recycled) {
+                    ngx_log_error(NGX_LOG_ALERT, p->log, 0,
+                                  "recycled buffer in pipe out chain");
                 }
 
                 p->out = p->out->next;
 
-                ngx_event_pipe_free_shadow_raw_buf(&p->free_raw_bufs, cl->buf);
-
             } else if (!p->cacheable && p->in) {
                 cl = p->in;
 
@@ -596,24 +590,13 @@ ngx_event_pipe_write_to_downstream(ngx_e
                                cl->buf->pos,
                                cl->buf->last - cl->buf->pos);
 
-                if (cl->buf->recycled
-                    && cl->buf->last_shadow
-                    && bsize + cl->buf->last - cl->buf->pos > p->busy_size)
-                {
-                    if (!prev_last_shadow) {
-                        p->in = p->in->next;
-
-                        cl->next = NULL;
-
-                        if (out) {
-                            *ll = cl;
-                        } else {
-                            out = cl;
-                        }
+                if (cl->buf->recycled && prev_last_shadow) {
+                    if (bsize + cl->buf->end - cl->buf->start > p->busy_size) {
+                        flush = 1;
+                        break;
                     }
 
-                    flush = 1;
-                    break;
+                    bsize += cl->buf->end - cl->buf->start;
                 }
 
                 prev_last_shadow = cl->buf->last_shadow;
@@ -624,10 +607,6 @@ ngx_event_pipe_write_to_downstream(ngx_e
                 break;
             }
 
-            if (cl->buf->recycled) {
-                bsize += cl->buf->last - cl->buf->pos;
-            }
-
             cl->next = NULL;
 
             if (out) {
@@ -701,9 +680,10 @@ ngx_event_pipe_write_to_downstream(ngx_e
 static ngx_int_t
 ngx_event_pipe_write_chain_to_temp_file(ngx_event_pipe_t *p)
 {
-    ssize_t       size, bsize;
+    ssize_t       size, bsize, n;
     ngx_buf_t    *b;
-    ngx_chain_t  *cl, *tl, *next, *out, **ll, **last_free, fl;
+    ngx_uint_t    prev_last_shadow;
+    ngx_chain_t  *cl, *tl, *next, *out, **ll, **last_out, **last_free, fl;
 
     if (p->buf_to_file) {
         fl.buf = p->buf_to_file;
@@ -719,6 +699,7 @@ ngx_event_pipe_write_chain_to_temp_file(
         size = 0;
         cl = out;
         ll = NULL;
+        prev_last_shadow = 1;
 
         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0,
                        "pipe offset: %O", p->temp_file->offset);
@@ -726,16 +707,21 @@ ngx_event_pipe_write_chain_to_temp_file(
         do {
             bsize = cl->buf->last - cl->buf->pos;
 
-            ngx_log_debug3(NGX_LOG_DEBUG_EVENT, p->log, 0,
-                           "pipe buf %p, pos %p, size: %z",
-                           cl->buf->start, cl->buf->pos, bsize);
+            ngx_log_debug4(NGX_LOG_DEBUG_EVENT, p->log, 0,
+                           "pipe buf ls:%d %p, pos %p, size: %z",
+                           cl->buf->last_shadow, cl->buf->start,
+                           cl->buf->pos, bsize);
 
-            if ((size + bsize > p->temp_file_write_size)
-               || (p->temp_file->offset + size + bsize > p->max_temp_file_size))
+            if (prev_last_shadow
+                && ((size + bsize > p->temp_file_write_size)
+                    || (p->temp_file->offset + size + bsize
+                        > p->max_temp_file_size)))
             {
                 break;
             }
 
+            prev_last_shadow = cl->buf->last_shadow;
+
             size += bsize;
             ll = &cl->next;
             cl = cl->next;
@@ -762,10 +748,63 @@ ngx_event_pipe_write_chain_to_temp_file(
         p->last_in = &p->in;
     }
 
-    if (ngx_write_chain_to_temp_file(p->temp_file, out) == NGX_ERROR) {
+    n = ngx_write_chain_to_temp_file(p->temp_file, out);
+
+    if (n == NGX_ERROR) {
         return NGX_ABORT;
     }
 
+    if (p->buf_to_file) {
+        p->temp_file->offset = p->buf_to_file->last - p->buf_to_file->pos;
+        n -= p->buf_to_file->last - p->buf_to_file->pos;
+        p->buf_to_file = NULL;
+        out = out->next;
+    }
+
+    if (n > 0) {
+        /* update previous buffer or add new buffer */
+
+        if (p->out) {
+            for (cl = p->out; cl->next; cl = cl->next) { /* void */ }
+
+            b = cl->buf;
+
+            if (b->file_last == p->temp_file->offset) {
+                p->temp_file->offset += n;
+                b->file_last = p->temp_file->offset;
+                goto free;
+            }
+
+            last_out = &cl->next;
+
+        } else {
+            last_out = &p->out;
+        }
+
+        cl = ngx_chain_get_free_buf(p->pool, &p->free);
+        if (cl == NULL) {
+            return NGX_ABORT;
+        }
+
+        b = cl->buf;
+
+        ngx_memzero(b, sizeof(ngx_buf_t));
+
+        b->tag = p->tag;
+
+        b->file = &p->temp_file->file;
+        b->file_pos = p->temp_file->offset;
+        p->temp_file->offset += n;
+        b->file_last = p->temp_file->offset;
+
+        b->in_file = 1;
+        b->temp_file = 1;
+
+        *last_out = cl;
+    }
+
+free:
+
     for (last_free = &p->free_raw_bufs;
          *last_free != NULL;
          last_free = &(*last_free)->next)
@@ -773,31 +812,13 @@ ngx_event_pipe_write_chain_to_temp_file(
         /* void */
     }
 
-    if (p->buf_to_file) {
-        p->temp_file->offset = p->buf_to_file->last - p->buf_to_file->pos;
-        p->buf_to_file = NULL;
-        out = out->next;
-    }
-
     for (cl = out; cl; cl = next) {
         next = cl->next;
-        cl->next = NULL;
+
+        cl->next = p->free;
+        p->free = cl;
 
         b = cl->buf;
-        b->file = &p->temp_file->file;
-        b->file_pos = p->temp_file->offset;
-        p->temp_file->offset += b->last - b->pos;
-        b->file_last = p->temp_file->offset;
-
-        b->in_file = 1;
-        b->temp_file = 1;
-
-        if (p->out) {
-            *p->last_out = cl;
-        } else {
-            p->out = cl;
-        }
-        p->last_out = &cl->next;
 
         if (b->last_shadow) {
 
@@ -913,35 +934,6 @@ ngx_event_pipe_remove_shadow_links(ngx_b
 }
 
 
-static ngx_inline void
-ngx_event_pipe_free_shadow_raw_buf(ngx_chain_t **free, ngx_buf_t *buf)
-{
-    ngx_buf_t    *s;
-    ngx_chain_t  *cl, **ll;
-
-    if (buf->shadow == NULL) {
-        return;
-    }
-
-    for (s = buf->shadow; !s->last_shadow; s = s->shadow) { /* void */ }
-
-    ll = free;
-
-    for (cl = *free; cl; cl = cl->next) {
-        if (cl->buf == s) {
-            *ll = cl->next;
-            break;
-        }
-
-        if (cl->buf->shadow) {
-            break;
-        }
-
-        ll = &cl->next;
-    }
-}
-
-
 ngx_int_t
 ngx_event_pipe_add_free_buf(ngx_event_pipe_t *p, ngx_buf_t *b)
 {
--- a/src/event/ngx_event_pipe.h
+++ b/src/event/ngx_event_pipe.h
@@ -30,8 +30,6 @@ struct ngx_event_pipe_s {
     ngx_chain_t      **last_in;
 
     ngx_chain_t       *out;
-    ngx_chain_t      **last_out;
-
     ngx_chain_t       *free;
     ngx_chain_t       *busy;
 
--- a/src/http/modules/ngx_http_headers_filter_module.c
+++ b/src/http/modules/ngx_http_headers_filter_module.c
@@ -253,7 +253,7 @@ ngx_http_set_expires(ngx_http_request_t 
         return NGX_ERROR;
     }
 
-    if (conf->expires_time == 0) {
+    if (conf->expires_time == 0 && conf->expires != NGX_HTTP_EXPIRES_DAILY) {
         ngx_memcpy(expires->value.data, ngx_cached_http_time.data,
                    ngx_cached_http_time.len + 1);
         ngx_str_set(&cc->value, "max-age=0");
@@ -262,16 +262,16 @@ ngx_http_set_expires(ngx_http_request_t 
 
     now = ngx_time();
 
-    if (conf->expires == NGX_HTTP_EXPIRES_ACCESS
-        || r->headers_out.last_modified_time == -1)
+    if (conf->expires == NGX_HTTP_EXPIRES_DAILY) {
+        expires_time = ngx_next_time(conf->expires_time);
+        max_age = expires_time - now;
+
+    } else if (conf->expires == NGX_HTTP_EXPIRES_ACCESS
+               || r->headers_out.last_modified_time == -1)
     {
         expires_time = now + conf->expires_time;
         max_age = conf->expires_time;
 
-    } else if (conf->expires == NGX_HTTP_EXPIRES_DAILY) {
-        expires_time = ngx_next_time(conf->expires_time);
-        max_age = expires_time - now;
-
     } else {
         expires_time = r->headers_out.last_modified_time + conf->expires_time;
         max_age = expires_time - now;
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -346,7 +346,16 @@ ngx_http_ssl_merge_srv_conf(ngx_conf_t *
 
     ngx_pool_cleanup_t  *cln;
 
-    ngx_conf_merge_value(conf->enable, prev->enable, 0);
+    if (conf->enable == NGX_CONF_UNSET) {
+        if (prev->enable == NGX_CONF_UNSET) {
+            conf->enable = 0;
+
+        } else {
+            conf->enable = prev->enable;
+            conf->file = prev->file;
+            conf->line = prev->line;
+        }
+    }
 
     ngx_conf_merge_value(conf->session_timeout,
                          prev->session_timeout, 300);
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -48,7 +48,7 @@ our @EXPORT = qw(
     HTTP_INSUFFICIENT_STORAGE
 );
 
-our $VERSION = '1.1.6';
+our $VERSION = '1.1.7';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -718,7 +718,7 @@ static ngx_command_t  ngx_http_core_comm
       NULL },
 
     { ngx_string("resolver"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
       ngx_http_core_resolver,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
@@ -3535,7 +3535,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
              * to inherit it in all servers
              */
 
-            prev->resolver = ngx_resolver_create(cf, NULL);
+            prev->resolver = ngx_resolver_create(cf, NULL, 0);
             if (prev->resolver == NULL) {
                 return NGX_CONF_ERROR;
             }
@@ -4540,7 +4540,6 @@ ngx_http_core_resolver(ngx_conf_t *cf, n
 {
     ngx_http_core_loc_conf_t  *clcf = conf;
 
-    ngx_url_t   u;
     ngx_str_t  *value;
 
     if (clcf->resolver) {
@@ -4549,21 +4548,11 @@ ngx_http_core_resolver(ngx_conf_t *cf, n
 
     value = cf->args->elts;
 
-    ngx_memzero(&u, sizeof(ngx_url_t));
-
-    u.host = value[1];
-    u.port = 53;
-
-    if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err);
+    clcf->resolver = ngx_resolver_create(cf, &value[1], cf->args->nelts - 1);
+    if (clcf->resolver == NULL) {
         return NGX_CONF_ERROR;
     }
 
-    clcf->resolver = ngx_resolver_create(cf, &u.addrs[0]);
-    if (clcf->resolver == NULL) {
-        return NGX_OK;
-    }
-
     return NGX_CONF_OK;
 }
 
--- a/src/mail/ngx_mail_auth_http_module.c
+++ b/src/mail/ngx_mail_auth_http_module.c
@@ -783,7 +783,7 @@ ngx_mail_auth_http_process_headers(ngx_m
             sin->sin_family = AF_INET;
 
             port = ngx_atoi(ctx->port.data, ctx->port.len);
-            if (port == NGX_ERROR || port < 1 || port > 65536) {
+            if (port == NGX_ERROR || port < 1 || port > 65535) {
                 ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                               "auth http server %V sent invalid server "
                               "port:\"%V\"",
--- a/src/mail/ngx_mail_core_module.c
+++ b/src/mail/ngx_mail_core_module.c
@@ -69,7 +69,7 @@ static ngx_command_t  ngx_mail_core_comm
       NULL },
 
     { ngx_string("resolver"),
-      NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1,
+      NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_1MORE,
       ngx_mail_core_resolver,
       NGX_MAIL_SRV_CONF_OFFSET,
       0,
@@ -493,7 +493,6 @@ ngx_mail_core_resolver(ngx_conf_t *cf, n
 {
     ngx_mail_core_srv_conf_t  *cscf = conf;
 
-    ngx_url_t   u;
     ngx_str_t  *value;
 
     value = cf->args->elts;
@@ -507,21 +506,11 @@ ngx_mail_core_resolver(ngx_conf_t *cf, n
         return NGX_CONF_OK;
     }
 
-    ngx_memzero(&u, sizeof(ngx_url_t));
-
-    u.host = value[1];
-    u.port = 53;
-
-    if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err);
+    cscf->resolver = ngx_resolver_create(cf, &value[1], cf->args->nelts - 1);
+    if (cscf->resolver == NULL) {
         return NGX_CONF_ERROR;
     }
 
-    cscf->resolver = ngx_resolver_create(cf, &u.addrs[0]);
-    if (cscf->resolver == NULL) {
-        return NGX_CONF_OK;
-    }
-
     return NGX_CONF_OK;
 }
 
--- a/src/os/unix/ngx_darwin.h
+++ b/src/os/unix/ngx_darwin.h
@@ -8,6 +8,7 @@
 #define _NGX_DARWIN_H_INCLUDED_
 
 
+void ngx_debug_init(void);
 ngx_chain_t *ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in,
     off_t limit);
 
@@ -15,5 +16,7 @@ extern int       ngx_darwin_kern_osrelda
 extern int       ngx_darwin_hw_ncpu;
 extern u_long    ngx_darwin_net_inet_tcp_sendspace;
 
+extern ngx_uint_t  ngx_debug_malloc;
+
 
 #endif /* _NGX_DARWIN_H_INCLUDED_ */
--- a/src/os/unix/ngx_darwin_config.h
+++ b/src/os/unix/ngx_darwin_config.h
@@ -87,6 +87,7 @@
 
 
 #define NGX_HAVE_OS_SPECIFIC_INIT    1
+#define NGX_HAVE_DEBUG_MALLOC        1
 
 
 extern char **environ;
--- a/src/os/unix/ngx_darwin_init.c
+++ b/src/os/unix/ngx_darwin_init.c
@@ -14,6 +14,8 @@ int     ngx_darwin_hw_ncpu;
 int     ngx_darwin_kern_ipc_somaxconn;
 u_long  ngx_darwin_net_inet_tcp_sendspace;
 
+ngx_uint_t  ngx_debug_malloc;
+
 
 static ngx_os_io_t ngx_darwin_io = {
     ngx_unix_recv,
@@ -55,10 +57,37 @@ sysctl_t sysctls[] = {
 };
 
 
+void
+ngx_debug_init()
+{
+#if (NGX_DEBUG_MALLOC)
+
+    /*
+     * MacOSX 10.6, 10.7:  MallocScribble fills freed memory with 0x55
+     *                     and fills allocated memory with 0xAA.
+     * MacOSX 10.4, 10.5:  MallocScribble fills freed memory with 0x55,
+     *                     MallocPreScribble fills allocated memory with 0xAA.
+     * MacOSX 10.3:        MallocScribble fills freed memory with 0x55,
+     *                     and no way to fill allocated memory.
+     */
+
+    setenv("MallocScribble", "1", 0);
+
+    ngx_debug_malloc = 1;
+
+#else
+
+    if (getenv("MallocScribble")) {
+        ngx_debug_malloc = 1;
+    }
+
+#endif
+}
+
+
 ngx_int_t
 ngx_os_specific_init(ngx_log_t *log)
 {
-    int         somaxconn;
     size_t      size;
     ngx_err_t   err;
     ngx_uint_t  i;
@@ -125,12 +154,9 @@ ngx_os_specific_init(ngx_log_t *log)
 
     ngx_ncpu = ngx_darwin_hw_ncpu;
 
-    somaxconn = 32676;
-
-    if (ngx_darwin_kern_ipc_somaxconn > somaxconn) {
+    if (ngx_darwin_kern_ipc_somaxconn > 32767) {
         ngx_log_error(NGX_LOG_ALERT, log, 0,
-                      "sysctl kern.ipc.somaxconn must be no more than %d",
-                      somaxconn);
+                      "sysctl kern.ipc.somaxconn must be less than 32768");
         return NGX_ERROR;
     }
 
--- a/src/os/unix/ngx_files.c
+++ b/src/os/unix/ngx_files.c
@@ -153,7 +153,7 @@ ngx_write_chain_to_file(ngx_file_t *file
 {
     u_char        *prev;
     size_t         size;
-    ssize_t        n;
+    ssize_t        total, n;
     ngx_array_t    vec;
     struct iovec  *iov, iovs[NGX_IOVS];
 
@@ -165,6 +165,8 @@ ngx_write_chain_to_file(ngx_file_t *file
                               offset);
     }
 
+    total = 0;
+
     vec.elts = iovs;
     vec.size = sizeof(struct iovec);
     vec.nalloc = NGX_IOVS;
@@ -202,8 +204,15 @@ ngx_write_chain_to_file(ngx_file_t *file
 
         if (vec.nelts == 1) {
             iov = vec.elts;
-            return ngx_write_file(file, (u_char *) iov[0].iov_base,
-                                  iov[0].iov_len, offset);
+
+            n = ngx_write_file(file, (u_char *) iov[0].iov_base,
+                               iov[0].iov_len, offset);
+
+            if (n == NGX_ERROR) {
+                return n;
+            }
+
+            return total + n;
         }
 
         if (file->sys_offset != offset) {
@@ -233,10 +242,11 @@ ngx_write_chain_to_file(ngx_file_t *file
 
         file->sys_offset += n;
         file->offset += n;
+        total += n;
 
     } while (cl);
 
-    return n;
+    return total;
 }
 
 
--- a/src/os/unix/ngx_freebsd.h
+++ b/src/os/unix/ngx_freebsd.h
@@ -8,6 +8,7 @@
 #define _NGX_FREEBSD_H_INCLUDED_
 
 
+void ngx_debug_init(void);
 ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in,
     off_t limit);
 
@@ -17,7 +18,7 @@ extern u_long      ngx_freebsd_net_inet_
 
 extern ngx_uint_t  ngx_freebsd_sendfile_nbytes_bug;
 extern ngx_uint_t  ngx_freebsd_use_tcp_nopush;
-extern ngx_uint_t  ngx_freebsd_debug_malloc;
+extern ngx_uint_t  ngx_debug_malloc;
 
 
 #endif /* _NGX_FREEBSD_H_INCLUDED_ */
--- a/src/os/unix/ngx_freebsd_config.h
+++ b/src/os/unix/ngx_freebsd_config.h
@@ -109,6 +109,7 @@ pid_t rfork_thread(int flags, void *stac
 
 
 #define NGX_HAVE_OS_SPECIFIC_INIT    1
+#define NGX_HAVE_DEBUG_MALLOC        1
 
 
 extern char **environ;
--- a/src/os/unix/ngx_freebsd_init.c
+++ b/src/os/unix/ngx_freebsd_init.c
@@ -22,7 +22,8 @@ int     ngx_freebsd_machdep_hlt_logical_
 
 ngx_uint_t  ngx_freebsd_sendfile_nbytes_bug;
 ngx_uint_t  ngx_freebsd_use_tcp_nopush;
-ngx_uint_t  ngx_freebsd_debug_malloc;
+
+ngx_uint_t  ngx_debug_malloc;
 
 
 static ngx_os_io_t ngx_freebsd_io = {
@@ -80,7 +81,7 @@ ngx_debug_init()
     malloc_options = "J";
 #endif
 
-    ngx_freebsd_debug_malloc = 1;
+    ngx_debug_malloc = 1;
 
 #else
     char  *mo;
@@ -88,7 +89,7 @@ ngx_debug_init()
     mo = getenv("MALLOC_OPTIONS");
 
     if (mo && ngx_strchr(mo, 'J')) {
-        ngx_freebsd_debug_malloc = 1;
+        ngx_debug_malloc = 1;
     }
 #endif
 }
@@ -97,7 +98,7 @@ ngx_debug_init()
 ngx_int_t
 ngx_os_specific_init(ngx_log_t *log)
 {
-    int         version, somaxconn;
+    int         version;
     size_t      size;
     ngx_err_t   err;
     ngx_uint_t  i;
@@ -209,12 +210,9 @@ ngx_os_specific_init(ngx_log_t *log)
         ngx_ncpu = ngx_freebsd_hw_ncpu;
     }
 
-    somaxconn = version < 600008 ? 32676 : 65535;
-
-    if (ngx_freebsd_kern_ipc_somaxconn > somaxconn) {
+    if (version < 600008 && ngx_freebsd_kern_ipc_somaxconn > 32767) {
         ngx_log_error(NGX_LOG_ALERT, log, 0,
-                      "sysctl kern.ipc.somaxconn must be no more than %d",
-                      somaxconn);
+                      "sysctl kern.ipc.somaxconn must be less than 32768");
         return NGX_ERROR;
     }
 
--- a/src/os/unix/ngx_linux_config.h
+++ b/src/os/unix/ngx_linux_config.h
@@ -108,6 +108,7 @@ typedef struct iocb  ngx_aiocb_t;
 
 
 #define NGX_HAVE_OS_SPECIFIC_INIT    1
+#define ngx_debug_init()
 
 
 extern char **environ;
--- a/src/os/unix/ngx_os.h
+++ b/src/os/unix/ngx_os.h
@@ -31,7 +31,6 @@ typedef struct {
 } ngx_os_io_t;
 
 
-void ngx_debug_init(void);
 ngx_int_t ngx_os_init(ngx_log_t *log);
 void ngx_os_status(ngx_log_t *log);
 ngx_int_t ngx_os_specific_init(ngx_log_t *log);
--- a/src/os/unix/ngx_posix_config.h
+++ b/src/os/unix/ngx_posix_config.h
@@ -125,6 +125,8 @@ typedef struct aiocb  ngx_aiocb_t;
 
 #define NGX_LISTEN_BACKLOG  511
 
+#define ngx_debug_init()
+
 
 #if (__FreeBSD__) && (__FreeBSD_version < 400017)
 
--- a/src/os/unix/ngx_solaris_config.h
+++ b/src/os/unix/ngx_solaris_config.h
@@ -98,6 +98,7 @@
 
 
 #define NGX_HAVE_OS_SPECIFIC_INIT    1
+#define ngx_debug_init()
 
 
 extern char **environ;