changeset 356:b743d290eb3b NGINX_0_6_22

nginx 0.6.22 *) Change: now all ngx_http_perl_module methods return values copied to perl's allocated memory. *) Bugfix: if nginx was built with ngx_http_perl_module, the perl before 5.8.6 was used, and perl supported threads, then during reconfiguration the master process aborted; bug appeared in 0.5.9. Thanks to Boris Zhmurov. *) Bugfix: the ngx_http_perl_module methods may get invalid values of the regex captures. *) Bugfix: a segmentation fault occurred in worker process, if the $r->has_request_body() method was called for a request whose small request body was already received. *) Bugfix: large_client_header_buffers did not freed before going to keep-alive state. Thanks to Olexander Shtepa. *) Bugfix: the last address was missed in the $upstream_addr variable; bug appeared in 0.6.18. *) Bugfix: the "fastcgi_catch_stderr" directive did return error code; now it returns 502 code, that can be rerouted to a next server using the "fastcgi_next_upstream invalid_header" directive. *) Bugfix: a segmentation fault occurred in master process if the "fastcgi_catch_stderr" directive was used; bug appeared in 0.6.10. Thanks to Manlio Perillo.
author Igor Sysoev <http://sysoev.ru>
date Wed, 19 Dec 2007 00:00:00 +0300
parents 3ac45897a61c
children 16d557a75356
files CHANGES CHANGES.ru src/core/nginx.c src/core/nginx.h src/core/ngx_conf_file.c src/core/ngx_crc32.c src/core/ngx_crc32.h src/core/ngx_cycle.c src/core/ngx_file.c src/core/ngx_file.h src/core/ngx_open_file_cache.c src/core/ngx_palloc.c src/core/ngx_rbtree.c src/core/ngx_resolver.c src/core/ngx_string.c src/core/ngx_string.h src/event/modules/ngx_select_module.c src/event/ngx_event.c src/event/ngx_event_openssl.c src/event/ngx_event_timer.c src/http/modules/ngx_http_dav_module.c src/http/modules/ngx_http_fastcgi_module.c src/http/modules/ngx_http_flv_module.c src/http/modules/ngx_http_limit_zone_module.c src/http/modules/ngx_http_proxy_module.c src/http/modules/ngx_http_referer_module.c src/http/modules/ngx_http_ssi_filter_module.c src/http/modules/ngx_http_static_module.c src/http/modules/perl/nginx.pm src/http/modules/perl/nginx.xs src/http/modules/perl/ngx_http_perl_module.c src/http/ngx_http.c src/http/ngx_http_core_module.c src/http/ngx_http_parse.c src/http/ngx_http_request.c src/http/ngx_http_upstream.c src/http/ngx_http_upstream.h src/mail/ngx_mail_handler.c src/mail/ngx_mail_imap_handler.c src/mail/ngx_mail_pop3_handler.c src/mail/ngx_mail_smtp_handler.c src/os/unix/ngx_process_cycle.c
diffstat 42 files changed, 642 insertions(+), 555 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,39 @@
 
+Changes with nginx 0.6.22                                        19 Dec 2007
+
+    *) Change: now all ngx_http_perl_module methods return values copied to 
+       perl's allocated memory.
+
+    *) Bugfix: if nginx was built with ngx_http_perl_module, the perl 
+       before 5.8.6 was used, and perl supported threads, then during 
+       reconfiguration the master process aborted; bug appeared in 
+       0.5.9.
+       Thanks to Boris Zhmurov.
+
+    *) Bugfix: the ngx_http_perl_module methods may get invalid values of 
+       the regex captures.
+
+    *) Bugfix: a segmentation fault occurred in worker process, if the 
+       $r->has_request_body() method was called for a request whose small 
+       request body was already received.
+
+    *) Bugfix: large_client_header_buffers did not freed before going to 
+       keep-alive state.
+       Thanks to Olexander Shtepa.
+
+    *) Bugfix: the last address was missed in the $upstream_addr variable; 
+       bug appeared in 0.6.18.
+
+    *) Bugfix: the "fastcgi_catch_stderr" directive did return error code; 
+       now it returns 502 code, that can be rerouted to a next server using 
+       the "fastcgi_next_upstream invalid_header" directive.
+
+    *) Bugfix: a segmentation fault occurred in master process if the 
+       "fastcgi_catch_stderr" directive was used; bug appeared in 
+       0.6.10.
+       Thanks to Manlio Perillo.
+
+
 Changes with nginx 0.6.21                                        03 Dec 2007
 
     *) Change: if variable values used in a "proxy_pass" directive contain 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,39 @@
 
+Изменения в nginx 0.6.22                                          19.12.2007
+
+    *) Изменение: теперь все методы модуля ngx_http_perl_module возвращают 
+       значения, скопированные в память, выделенную perl'ом.
+
+    *) Исправление: если nginx был собран с модулем ngx_http_perl_module, 
+       использовался perl до версии 5.8.6 и perl поддерживал потоки, то во 
+       время переконфигурации основной процесс аварийно выходил; ошибка 
+       появилась в 0.5.9.
+       Спасибо Борису Жмурову.
+
+    *) Исправление: в методы модуля ngx_http_perl_module могли передаваться 
+       неверные результаты выделения в регулярных выражениях.
+
+    *) Исправление: если метод $r->has_request_body() вызывался для 
+       запроса, у которого небольшое тело запроса было уже полностью 
+       получено, то в рабочем процессе происходил segmentation fault.
+
+    *) Исправление: large_client_header_buffers не освобождались перед 
+       переходом в состояние keep-alive.
+       Спасибо Олександру Штепе.
+
+    *) Исправление: в переменной $upstream_addr не записывался последний 
+       адрес; ошибка появилась в 0.6.18.
+
+    *) Исправление: директива fastcgi_catch_stderr не возвращала ошибку; 
+       теперь она возвращает ошибку 502, которую можно направить на 
+       следующий сервер с помощью "fastcgi_next_upstream invalid_header".
+
+    *) Исправление: при использовании директивы fastcgi_catch_stderr в 
+       основном процессе происходил segmentation fault; ошибка появилась в 
+       0.6.10.
+       Спасибо Manlio Perillo.
+
+
 Изменения в nginx 0.6.21                                          03.12.2007
 
     *) Изменение: если в значениях переменных директивы proxy_pass 
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -273,9 +273,11 @@ main(int argc, char *const *argv)
         return 1;
     }
 
-    /* ngx_crc32_init() requires ngx_cacheline_size set in ngx_os_init() */
+    /*
+     * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
+     */
 
-    if (ngx_crc32_init() != NGX_OK) {
+    if (ngx_crc32_table_init() != NGX_OK) {
         return 1;
     }
 
@@ -756,12 +758,6 @@ ngx_core_module_init_conf(ngx_cycle_t *c
 {
     ngx_core_conf_t  *ccf = conf;
 
-#if !(NGX_WIN32)
-    ngx_str_t       lock_file;
-    struct group   *grp;
-    struct passwd  *pwd;
-#endif
-
     ngx_conf_init_value(ccf->daemon, 1);
     ngx_conf_init_value(ccf->master, 1);
     ngx_conf_init_msec_value(ccf->timer_resolution, 0);
@@ -794,6 +790,8 @@ ngx_core_module_init_conf(ngx_cycle_t *c
 #if !(NGX_WIN32)
 
     if (ccf->user == (uid_t) NGX_CONF_UNSET_UINT && geteuid() == 0) {
+        struct group   *grp;
+        struct passwd  *pwd;
 
         ngx_set_errno(0);
         pwd = getpwnam(NGX_USER);
@@ -846,6 +844,9 @@ ngx_core_module_init_conf(ngx_cycle_t *c
         return NGX_CONF_ERROR;
     }
 
+    {
+    ngx_str_t  lock_file;
+
     lock_file = cycle->old_cycle->lock_file;
 
     if (lock_file.len) {
@@ -879,6 +880,7 @@ ngx_core_module_init_conf(ngx_cycle_t *c
                               ccf->lock_file.len),
                    ".accept", sizeof(".accept"));
     }
+    }
 
 #endif
 
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VERSION      "0.6.21"
+#define NGINX_VERSION      "0.6.22"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -934,7 +934,7 @@ ngx_conf_set_str_array_slot(ngx_conf_t *
 
     a = (ngx_array_t **) (p + cmd->offset);
 
-    if (*a == NULL) {
+    if (*a == NGX_CONF_UNSET_PTR) {
         *a = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
         if (*a == NULL) {
             return NGX_CONF_ERROR;
--- a/src/core/ngx_crc32.c
+++ b/src/core/ngx_crc32.c
@@ -102,7 +102,7 @@ uint32_t *ngx_crc32_table_short = ngx_cr
 
 
 ngx_int_t
-ngx_crc32_init(void)
+ngx_crc32_table_init(void)
 {
     void  *p;
 
--- a/src/core/ngx_crc32.h
+++ b/src/core/ngx_crc32.h
@@ -49,7 +49,30 @@ ngx_crc32_long(u_char *p, size_t len)
 }
 
 
-ngx_int_t ngx_crc32_init(void);
+#define ngx_crc32_init(crc)                                                   \
+    crc = 0xffffffff
+
+
+static ngx_inline void
+ngx_crc32_update(uint32_t *crc, u_char *p, size_t len)
+{
+    uint32_t  c;
+
+    c = *crc;
+
+    while (len--) {
+        c = ngx_crc32_table256[(c ^ *p++) & 0xff] ^ (c >> 8);
+    }
+
+    *crc = c;
+}
+
+
+#define ngx_crc32_final(crc)                                                  \
+    crc ^= 0xffffffff
+
+
+ngx_int_t ngx_crc32_table_init(void);
 
 
 #endif /* _NGX_CRC32_H_INCLUDED_ */
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -42,20 +42,21 @@ static ngx_str_t  error_log = ngx_null_s
 ngx_cycle_t *
 ngx_init_cycle(ngx_cycle_t *old_cycle)
 {
-    void               *rv;
-    u_char             *lock_file;
-    ngx_uint_t          i, n;
-    ngx_log_t          *log;
-    ngx_conf_t          conf;
-    ngx_pool_t         *pool;
-    ngx_cycle_t        *cycle, **old;
-    ngx_shm_zone_t     *shm_zone, *oshm_zone;
-    ngx_slab_pool_t    *shpool;
-    ngx_list_part_t    *part, *opart;
-    ngx_open_file_t    *file;
-    ngx_listening_t    *ls, *nls;
-    ngx_core_conf_t    *ccf, *old_ccf;
-    ngx_core_module_t  *module;
+    void                *rv;
+    char               **senv, **env;
+    u_char              *lock_file;
+    ngx_uint_t           i, n;
+    ngx_log_t           *log;
+    ngx_conf_t           conf;
+    ngx_pool_t          *pool;
+    ngx_cycle_t         *cycle, **old;
+    ngx_shm_zone_t      *shm_zone, *oshm_zone;
+    ngx_slab_pool_t     *shpool;
+    ngx_list_part_t     *part, *opart;
+    ngx_open_file_t     *file;
+    ngx_listening_t     *ls, *nls;
+    ngx_core_conf_t     *ccf, *old_ccf;
+    ngx_core_module_t   *module;
 
     log = old_cycle->log;
 
@@ -187,6 +188,9 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
     }
 
 
+    senv = environ;
+
+
     ngx_memzero(&conf, sizeof(ngx_conf_t));
     /* STUB: init array ? */
     conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t));
@@ -694,9 +698,20 @@ old_shm_zone_done:
 
     if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) {
 
+        /*
+         * perl_destruct() frees environ if it is not the same as it was at
+         * perl_construct() time.  So we have saved an previous cycle
+         * environment before ngx_conf_parse() where it will be changed.
+         */
+
+        env = environ;
+        environ = senv;
+
         ngx_destroy_pool(old_cycle->pool);
         cycle->old_cycle = NULL;
 
+        environ = env;
+
         return cycle;
     }
 
@@ -938,9 +953,6 @@ ngx_reopen_files(ngx_cycle_t *cycle, ngx
     ngx_uint_t        i;
     ngx_list_part_t  *part;
     ngx_open_file_t  *file;
-#if !(NGX_WIN32)
-    ngx_file_info_t   fi;
-#endif
 
     part = &cycle->open_files.part;
     file = part->elts;
@@ -996,6 +1008,7 @@ ngx_reopen_files(ngx_cycle_t *cycle, ngx
         }
 #else
         if (user != (ngx_uid_t) NGX_CONF_UNSET_UINT) {
+            ngx_file_info_t  fi;
 
             if (ngx_file_info((const char *) file[i].name.data, &fi) == -1) {
                 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -61,16 +61,19 @@ ngx_create_temp_file(ngx_file_t *file, n
 
     n = (uint32_t) ngx_next_temp_number(0);
 
+    cln = ngx_pool_cleanup_add(pool, sizeof(ngx_pool_cleanup_file_t));
+    if (cln == NULL) {
+        return NGX_ERROR;
+    }
+
     for ( ;; ) {
         (void) ngx_sprintf(file->name.data + path->name.len + 1 + path->len,
                            "%010uD%Z", n);
 
-        ngx_create_hashed_filename(file, path);
+        ngx_create_hashed_filename(path, file->name.data, file->name.len);
 
-        cln = ngx_pool_cleanup_add(pool, sizeof(ngx_pool_cleanup_file_t));
-        if (cln == NULL) {
-            return NGX_ERROR;
-        }
+        ngx_log_debug1(NGX_LOG_DEBUG_CORE, file->log, 0,
+                       "hashed path: %s", file->name.data);
 
         file->fd = ngx_open_tempfile(file->name.data, persistent, access);
 
@@ -117,31 +120,27 @@ ngx_create_temp_file(ngx_file_t *file, n
 
 
 void
-ngx_create_hashed_filename(ngx_file_t *file, ngx_path_t *path)
+ngx_create_hashed_filename(ngx_path_t *path, u_char *file, size_t len)
 {
-    size_t      name, pos, level;
-    ngx_uint_t  i;
+    size_t      i, level;
+    ngx_uint_t  n;
 
-    name = file->name.len;
-    pos = path->name.len + 1;
+    i = path->name.len + 1;
 
-    file->name.data[path->name.len + path->len]  = '/';
+    file[path->name.len + path->len]  = '/';
 
-    for (i = 0; i < 3; i++) {
-        level = path->level[i];
+    for (n = 0; n < 3; n++) {
+        level = path->level[n];
 
         if (level == 0) {
             break;
         }
 
-        name -= level;
-        file->name.data[pos - 1] = '/';
-        ngx_memcpy(&file->name.data[pos], &file->name.data[name], level);
-        pos += level + 1;
+        len -= level;
+        file[i - 1] = '/';
+        ngx_memcpy(&file[i], &file[len], level);
+        i += level + 1;
     }
-
-    ngx_log_debug1(NGX_LOG_DEBUG_CORE, file->log, 0,
-                   "hashed path: %s", file->name.data);
 }
 
 
@@ -425,9 +424,6 @@ ngx_create_pathes(ngx_cycle_t *cycle, ng
     ngx_err_t         err;
     ngx_uint_t        i;
     ngx_path_t      **path;
-#if !(NGX_WIN32)
-    ngx_file_info_t   fi;
-#endif
 
     path = cycle->pathes.elts;
     for (i = 0; i < cycle->pathes.nelts; i++) {
@@ -447,6 +443,8 @@ ngx_create_pathes(ngx_cycle_t *cycle, ng
         }
 
 #if !(NGX_WIN32)
+        {
+        ngx_file_info_t   fi;
 
         if (ngx_file_info((const char *) path[i]->name.data, &fi) == -1) {
             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
@@ -474,7 +472,7 @@ ngx_create_pathes(ngx_cycle_t *cycle, ng
                 return NGX_ERROR;
             }
         }
-
+        }
 #endif
     }
 
@@ -483,6 +481,107 @@ ngx_create_pathes(ngx_cycle_t *cycle, ng
 
 
 ngx_int_t
+ngx_create_path_and_rename_file(ngx_str_t *src, ngx_str_t *to,
+    ngx_uint_t access, ngx_uint_t full_path, ngx_uint_t delete, ngx_log_t *log)
+{
+    ngx_err_t  err;
+
+#if !(NGX_WIN32)
+
+    if (ngx_change_file_access(src->data, access) == NGX_FILE_ERROR) {
+        ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
+                      ngx_change_file_access_n " \"%s\" failed", src->data);
+        err = 0;
+        goto failed;
+    }
+
+#endif
+
+    if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) {
+        return NGX_OK;
+    }
+
+    err = ngx_errno;
+
+    if (err == NGX_ENOENT) {
+
+        if (!full_path) {
+            goto failed;
+        }
+
+        err = ngx_create_full_path(to->data, ngx_dir_access(access));
+
+        if (err) {
+            ngx_log_error(NGX_LOG_CRIT, log, err,
+                          ngx_create_dir_n " \"%s\" failed", to->data);
+            err = 0;
+            goto failed;
+        }
+
+        if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) {
+            return NGX_OK;
+        }
+
+        err = ngx_errno;
+        goto failed;
+    }
+
+#if (NGX_WIN32)
+
+    if (err == NGX_EEXIST) {
+        if (ngx_win32_rename_file(src, to, log) == NGX_OK) {
+
+            if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) {
+                return NGX_OK;
+            }
+
+            err = ngx_errno;
+
+        } else {
+            err = 0;
+        }
+    }
+
+#endif
+
+failed:
+
+    if (delete) {
+        if (ngx_delete_file(src->data) == NGX_FILE_ERROR) {
+            ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
+                          ngx_delete_file_n " \"%s\" failed", src->data);
+        }
+    }
+
+    if (err) {
+        ngx_log_error(NGX_LOG_CRIT, log, err,
+                      ngx_rename_file_n " \"%s\" to \"%s\" failed",
+                      src->data, to->data);
+    }
+
+    return NGX_ERROR;
+}
+
+
+/*
+ * ctx->init_handler() - see ctx->alloc
+ * ctx->file_handler() - file handler
+ * ctx->pre_tree_handler() - handler is called before entering directory
+ * ctx->post_tree_handler() - handler is called after leaving directory
+ * ctx->spec_handler() - special (socket, FIFO, etc.) file handler
+ *
+ * ctx->data - some data structure, it may be the same on all levels, or
+ *     reallocated if ctx->alloc is nonzero
+ *
+ * ctx->alloc - a size of data structure that is allocated at every level
+ *     and is initilialized by ctx->init_handler()
+ *
+ * ctx->log - a log
+ *
+ * on fatal (memory) error handler must return NGX_ABORT to stop walking tree
+ */
+
+ngx_int_t
 ngx_walk_tree(ngx_tree_ctx_t *ctx, ngx_str_t *tree)
 {
     void       *data, *prev;
--- a/src/core/ngx_file.h
+++ b/src/core/ngx_file.h
@@ -84,11 +84,13 @@ ssize_t ngx_write_chain_to_temp_file(ngx
 ngx_int_t ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path,
     ngx_pool_t *pool, ngx_uint_t persistent, ngx_uint_t clean,
     ngx_uint_t access);
-void ngx_create_hashed_filename(ngx_file_t *file, ngx_path_t *path);
+void ngx_create_hashed_filename(ngx_path_t *path, u_char *file, size_t len);
 ngx_int_t ngx_create_path(ngx_file_t *file, ngx_path_t *path);
 ngx_err_t ngx_create_full_path(u_char *dir, ngx_uint_t access);
 ngx_int_t ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot);
 ngx_int_t ngx_create_pathes(ngx_cycle_t *cycle, ngx_uid_t user);
+ngx_int_t ngx_create_path_and_rename_file(ngx_str_t *src, ngx_str_t *to,
+    ngx_uint_t access, ngx_uint_t full_path, ngx_uint_t delete, ngx_log_t *log);
 ngx_int_t ngx_walk_tree(ngx_tree_ctx_t *ctx, ngx_str_t *tree);
 
 void ngx_init_temp_number(void);
--- a/src/core/ngx_open_file_cache.c
+++ b/src/core/ngx_open_file_cache.c
@@ -53,11 +53,8 @@ ngx_open_file_cache_init(ngx_pool_t *poo
         return NULL;
     }
 
-    ngx_rbtree_sentinel_init(sentinel);
-
-    cache->rbtree.root = sentinel;
-    cache->rbtree.sentinel = sentinel;
-    cache->rbtree.insert = ngx_open_file_cache_rbtree_insert_value;
+    ngx_rbtree_init(&cache->rbtree, sentinel,
+                    ngx_open_file_cache_rbtree_insert_value);
 
     cache->current = 0;
     cache->max = max;
--- a/src/core/ngx_palloc.c
+++ b/src/core/ngx_palloc.c
@@ -40,6 +40,8 @@ ngx_destroy_pool(ngx_pool_t *pool)
 
     for (c = pool->cleanup; c; c = c->next) {
         if (c->handler) {
+            ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, pool->log, 0,
+                           "run cleanup: %p", c);
             c->handler(c->data);
         }
     }
@@ -245,8 +247,8 @@ ngx_pool_cleanup_file(void *data)
 {
     ngx_pool_cleanup_file_t  *c = data;
 
-    ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, c->log, 0, "run cleanup: %p, fd:%d",
-                   c, c->fd);
+    ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, c->log, 0, "file cleanup: fd:%d",
+                   c->fd);
 
     if (ngx_close_file(c->fd) == NGX_FILE_ERROR) {
         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
@@ -262,8 +264,8 @@ ngx_pool_delete_file(void *data)
 
     ngx_err_t  err;
 
-    ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, c->log, 0, "run cleanup: %p, fd:%d %s",
-                   c, c->fd, c->name);
+    ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, c->log, 0, "file cleanup: fd:%d %s",
+                   c->fd, c->name);
 
     if (ngx_delete_file(c->name) == NGX_FILE_ERROR) {
         err = ngx_errno;
--- a/src/core/ngx_rbtree.c
+++ b/src/core/ngx_rbtree.c
@@ -97,28 +97,20 @@ void
 ngx_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,
     ngx_rbtree_node_t *sentinel)
 {
+    ngx_rbtree_node_t  **p;
+
     for ( ;; ) {
 
-        if (node->key < temp->key) {
-
-            if (temp->left == sentinel) {
-                temp->left = node;
-                break;
-            }
-
-            temp = temp->left;
+        p = (node->key < temp->key) ? &temp->left : &temp->right;
 
-        } else {
+        if (*p == sentinel) {
+            break;
+        }
 
-            if (temp->right == sentinel) {
-                temp->right = node;
-                break;
-            }
-
-            temp = temp->right;
-        }
+        temp = *p;
     }
 
+    *p = node;
     node->parent = temp;
     node->left = sentinel;
     node->right = sentinel;
@@ -130,6 +122,8 @@ void
 ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,
     ngx_rbtree_node_t *sentinel)
 {
+    ngx_rbtree_node_t  **p;
+
     for ( ;; ) {
 
         /*
@@ -139,29 +133,20 @@ ngx_rbtree_insert_timer_value(ngx_rbtree
          * The comparison takes into account that overflow.
          */
 
-        if ((ngx_rbtree_key_int_t) node->key - (ngx_rbtree_key_int_t) temp->key
-            < 0)
-        {
-            /*  node->key < temp->key */
+        /*  node->key < temp->key */
 
-            if (temp->left == sentinel) {
-                temp->left = node;
-                break;
-            }
+        p = ((ngx_rbtree_key_int_t) node->key - (ngx_rbtree_key_int_t) temp->key
+              < 0)
+            ? &temp->left : &temp->right;
 
-            temp = temp->left;
-
-        } else {
+        if (*p == sentinel) {
+            break;
+        }
 
-            if (temp->right == sentinel) {
-                temp->right = node;
-                break;
-            }
-
-            temp = temp->right;
-        }
+        temp = *p;
     }
 
+    *p = node;
     node->parent = temp;
     node->left = sentinel;
     node->right = sentinel;
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -67,9 +67,9 @@ static void ngx_resolver_read_response(n
 static void ngx_resolver_process_response(ngx_resolver_t *r, u_char *buf,
     size_t n);
 static void ngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t n,
-    ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t i);
+    ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans);
 static void ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
-    ngx_uint_t ident, ngx_uint_t code);
+    ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan);
 static ngx_resolver_node_t *ngx_resolver_lookup_name(ngx_resolver_t *r,
     ngx_str_t *name, uint32_t hash);
 static ngx_resolver_node_t *ngx_resolver_lookup_addr(ngx_resolver_t *r,
@@ -884,11 +884,6 @@ ngx_resolver_process_response(ngx_resolv
         goto done;
     }
 
-    if (code == 0 && nan == 0) {
-        err = "no answers in DNS response";
-        goto done;
-    }
-
     i = sizeof(ngx_resolver_query_t);
 
     while (i < (ngx_uint_t) n) {
@@ -934,13 +929,13 @@ found:
     case NGX_RESOLVE_A:
 
         ngx_resolver_process_a(r, buf, n, ident, code, nan,
-                              i + sizeof(ngx_resolver_qs_t));
+                               i + sizeof(ngx_resolver_qs_t));
 
         break;
 
     case NGX_RESOLVE_PTR:
 
-        ngx_resolver_process_ptr(r, buf, n, ident, code);
+        ngx_resolver_process_ptr(r, buf, n, ident, code, nan);
 
         break;
 
@@ -1006,6 +1001,10 @@ ngx_resolver_process_a(ngx_resolver_t *r
         goto failed;
     }
 
+    if (code == 0 && nan == 0) {
+        code = 3; /* NXDOMAIN */
+    }
+
     if (code) {
         next = rn->waiting;
         rn->waiting = NULL;
@@ -1204,6 +1203,8 @@ ngx_resolver_process_a(ngx_resolver_t *r
         ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
                        "resolver cname:\"%V\"", &name);
 
+        ngx_queue_remove(&rn->queue);
+
         rn->cnlen = (u_short) name.len;
         rn->u.cname = name.data;
         rn->valid = ngx_time() + r->valid;
@@ -1250,7 +1251,7 @@ failed:
 
 static void
 ngx_resolver_process_ptr(ngx_resolver_t *r, u_char *buf, size_t n,
-    ngx_uint_t ident, ngx_uint_t code)
+    ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan)
 {
     char                 *err;
     size_t                len;
@@ -1307,6 +1308,10 @@ ngx_resolver_process_ptr(ngx_resolver_t 
         goto failed;
     }
 
+    if (code == 0 && nan == 0) {
+        code = 3; /* NXDOMAIN */
+    }
+
     if (code) {
         next = rn->waiting;
         rn->waiting = NULL;
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -816,18 +816,17 @@ ngx_hextoi(u_char *line, size_t n)
 }
 
 
-void
-ngx_md5_text(u_char *text, u_char *md5)
+u_char *
+ngx_hex_dump(u_char *dst, u_char *src, size_t len)
 {
-    int            i;
     static u_char  hex[] = "0123456789abcdef";
 
-    for (i = 0; i < 16; i++) {
-        *text++ = hex[md5[i] >> 4];
-        *text++ = hex[md5[i] & 0xf];
+    while (len--) {
+        *dst++ = hex[*src >> 4];
+        *dst++ = hex[*src++ & 0xf];
     }
 
-    *text = '\0';
+    return dst;
 }
 
 
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -141,7 +141,7 @@ off_t ngx_atoof(u_char *line, size_t n);
 time_t ngx_atotm(u_char *line, size_t n);
 ngx_int_t ngx_hextoi(u_char *line, size_t n);
 
-void ngx_md5_text(u_char *text, u_char *md5);
+u_char *ngx_hex_dump(u_char *dst, u_char *src, size_t len);
 
 
 #define ngx_base64_encoded_length(len)  (((len + 2) / 3) * 4)
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -254,9 +254,6 @@ ngx_select_process_events(ngx_cycle_t *c
     ngx_event_t        *ev, **queue;
     ngx_connection_t   *c;
     struct timeval      tv, *tp;
-#if !(NGX_WIN32)
-    ngx_uint_t          level;
-#endif
 
 #if !(NGX_WIN32)
 
@@ -348,6 +345,8 @@ ngx_select_process_events(ngx_cycle_t *c
 #else
 
     if (err) {
+        ngx_uint_t  level;
+
         if (err == NGX_EINTR) {
 
             if (ngx_event_timer_alarm) {
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -428,13 +428,9 @@ ngx_event_module_init(ngx_cycle_t *cycle
     void              ***cf;
     u_char              *shared;
     size_t               size, cl;
-    ngx_event_conf_t    *ecf;
+    ngx_shm_t            shm;
     ngx_core_conf_t     *ccf;
-    ngx_shm_t            shm;
-#if !(NGX_WIN32)
-    ngx_int_t            limit;
-    struct rlimit        rlmt;
-#endif
+    ngx_event_conf_t    *ecf;
 
     cf = ngx_get_conf(cycle->conf_ctx, ngx_events_module);
 
@@ -456,6 +452,9 @@ ngx_event_module_init(ngx_cycle_t *cycle
     ngx_timer_resolution = ccf->timer_resolution;
 
 #if !(NGX_WIN32)
+    {
+    ngx_int_t      limit;
+    struct rlimit  rlmt;
 
     if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
@@ -475,7 +474,7 @@ ngx_event_module_init(ngx_cycle_t *cycle
                           ecf->connections, limit);
         }
     }
-
+    }
 #endif /* !(NGX_WIN32) */
 
 
@@ -573,13 +572,6 @@ ngx_event_process_init(ngx_cycle_t *cycl
     ngx_core_conf_t     *ccf;
     ngx_event_conf_t    *ecf;
     ngx_event_module_t  *module;
-#if (NGX_WIN32)
-    ngx_iocp_conf_t     *iocpcf;
-#else
-    struct rlimit        rlmt;
-    struct sigaction     sa;
-    struct itimerval     itv;
-#endif
 
     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
     ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
@@ -625,6 +617,8 @@ ngx_event_process_init(ngx_cycle_t *cycl
 #if !(NGX_WIN32)
 
     if (ngx_timer_resolution && !(ngx_event_flags & NGX_USE_TIMER_EVENT)) {
+        struct sigaction  sa;
+        struct itimerval  itv;
 
         ngx_memzero(&sa, sizeof(struct sigaction));
         sa.sa_handler = ngx_timer_signal_handler;
@@ -648,6 +642,7 @@ ngx_event_process_init(ngx_cycle_t *cycl
     }
 
     if (ngx_event_flags & NGX_USE_FD_EVENT) {
+        struct rlimit  rlmt;
 
         if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
@@ -774,6 +769,8 @@ ngx_event_process_init(ngx_cycle_t *cycl
 #if (NGX_WIN32)
 
         if (ngx_event_flags & NGX_USE_IOCP_EVENT) {
+            ngx_iocp_conf_t  *iocpcf;
+
             rev->handler = ngx_event_acceptex;
 
             if (ngx_add_event(rev, 0, NGX_IOCP_ACCEPT) == NGX_ERROR) {
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -1241,11 +1241,8 @@ ngx_ssl_session_cache_init(ngx_shm_zone_
         return NGX_ERROR;
     }
 
-    ngx_rbtree_sentinel_init(sentinel);
-
-    cache->session_rbtree->root = sentinel;
-    cache->session_rbtree->sentinel = sentinel;
-    cache->session_rbtree->insert = ngx_ssl_session_rbtree_insert_value;
+    ngx_rbtree_init(cache->session_rbtree, sentinel,
+                    ngx_ssl_session_rbtree_insert_value);
 
     shm_zone->data = cache;
 
@@ -1625,56 +1622,37 @@ static void
 ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp,
     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
 {
-    ngx_ssl_sess_id_t  *sess_id, *sess_id_temp;
+    ngx_rbtree_node_t  **p;
+    ngx_ssl_sess_id_t   *sess_id, *sess_id_temp;
 
     for ( ;; ) {
 
         if (node->key < temp->key) {
 
-            if (temp->left == sentinel) {
-                temp->left = node;
-                break;
-            }
-
-            temp = temp->left;
+            p = &temp->left;
 
         } else if (node->key > temp->key) {
 
-            if (temp->right == sentinel) {
-                temp->right = node;
-                break;
-            }
-
-            temp = temp->right;
+            p = &temp->right;
 
         } else { /* node->key == temp->key */
 
             sess_id = (ngx_ssl_sess_id_t *) node;
             sess_id_temp = (ngx_ssl_sess_id_t *) temp;
 
-            if (ngx_memn2cmp(sess_id->id, sess_id_temp->id,
-                             (size_t) node->data, (size_t) temp->data)
-                < 0)
-            {
-                if (temp->left == sentinel) {
-                    temp->left = node;
-                    break;
-                }
-
-                temp = temp->left;
-
-            } else {
-
-                if (temp->right == sentinel) {
-                    temp->right = node;
-                    break;
-                }
-
-                temp = temp->right;
-            }
+            p = (ngx_memn2cmp(sess_id->id, sess_id_temp->id,
+                              (size_t) node->data, (size_t) temp->data)
+                 < 0) ? &temp->left : &temp->right;
         }
+
+        if (*p == sentinel) {
+            break;
+        }
+
+        temp = *p;
     }
 
+    *p = node;
     node->parent = temp;
     node->left = sentinel;
     node->right = sentinel;
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -26,9 +26,8 @@ static ngx_rbtree_node_t          ngx_ev
 ngx_int_t
 ngx_event_timer_init(ngx_log_t *log)
 {
-    ngx_event_timer_rbtree.root = &ngx_event_timer_sentinel;
-    ngx_event_timer_rbtree.sentinel = &ngx_event_timer_sentinel;
-    ngx_event_timer_rbtree.insert = ngx_rbtree_insert_timer_value;
+    ngx_rbtree_init(&ngx_event_timer_rbtree, &ngx_event_timer_sentinel,
+                    ngx_rbtree_insert_timer_value);
 
 #if (NGX_THREADS)
 
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -295,7 +295,7 @@ ngx_http_dav_put_handler(ngx_http_reques
 #if (NGX_WIN32)
 
     if (err == NGX_EEXIST) {
-        if (ngx_win32_rename_file(temp, &path, r->pool) != NGX_ERROR) {
+        if (ngx_win32_rename_file(temp, &path, r->connection->log) == NGX_OK) {
 
             if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) {
                 goto ok;
@@ -969,7 +969,7 @@ ngx_http_dav_delete_path(ngx_http_reques
         tree.alloc = 0;
         tree.log = r->connection->log;
 
-        /* todo: 207 */
+        /* TODO: 207 */
 
         if (ngx_walk_tree(&tree, path) != NGX_OK) {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -887,7 +887,7 @@ ngx_http_fastcgi_process_header(ngx_http
     if (f == NULL) {
         f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t));
         if (f == NULL) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+            return NGX_ERROR;
         }
 
         ngx_http_set_ctx(r, f, ngx_http_fastcgi_module);
@@ -995,7 +995,7 @@ ngx_http_fastcgi_process_header(ngx_http
 
                     for (i = 0; i < flcf->catch_stderr->nelts; i++) {
                         if (ngx_strstr(line.data, pattern[i].data)) {
-                            return NGX_HTTP_BAD_GATEWAY;
+                            return NGX_HTTP_UPSTREAM_INVALID_HEADER;
                         }
                     }
                 }
@@ -1063,7 +1063,7 @@ ngx_http_fastcgi_process_header(ngx_http
 
                 h = ngx_list_push(&u->headers_in.headers);
                 if (h == NULL) {
-                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                    return NGX_ERROR;
                 }
 
                 if (f->split_parts && f->split_parts->nelts) {
@@ -1077,7 +1077,7 @@ ngx_http_fastcgi_process_header(ngx_http
 
                     p = ngx_palloc(r->pool, size);
                     if (p == NULL) {
-                        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                        return NGX_ERROR;
                     }
 
                     buf.pos = p;
@@ -1105,7 +1105,7 @@ ngx_http_fastcgi_process_header(ngx_http
 
                     h->lowcase_key = ngx_palloc(r->pool, h->key.len);
                     if (h->lowcase_key == NULL) {
-                        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                        return NGX_ERROR;
                     }
 
                 } else {
@@ -1117,7 +1117,7 @@ ngx_http_fastcgi_process_header(ngx_http
                                              h->key.len + 1 + h->value.len + 1
                                              + h->key.len);
                     if (h->key.data == NULL) {
-                        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                        return NGX_ERROR;
                     }
 
                     h->value.data = h->key.data + h->key.len + 1;
@@ -1145,7 +1145,7 @@ ngx_http_fastcgi_process_header(ngx_http
                                    h->lowcase_key, h->key.len);
 
                 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
-                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                    return NGX_ERROR;
                 }
 
                 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -1174,7 +1174,10 @@ ngx_http_fastcgi_process_header(ngx_http
                     status = ngx_atoi(status_line->data, 3);
 
                     if (status == NGX_ERROR) {
-                        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                                      "upstream sent invalid status \"%V\"",
+                                      status_line);
+                        return NGX_HTTP_UPSTREAM_INVALID_HEADER;
                     }
 
                     u->headers_in.status_n = status;
@@ -1235,7 +1238,7 @@ ngx_http_fastcgi_process_header(ngx_http
             f->split_parts = ngx_array_create(r->pool, 1,
                                         sizeof(ngx_http_fastcgi_split_part_t));
             if (f->split_parts == NULL) {
-                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                return NGX_ERROR;
             }
         }
 
@@ -1640,8 +1643,6 @@ ngx_http_fastcgi_create_loc_conf(ngx_con
      *     conf->upstream.next_upstream = 0;
      *     conf->upstream.temp_path = NULL;
      *     conf->upstream.hide_headers_hash = { NULL, 0 };
-     *     conf->upstream.hide_headers = NULL;
-     *     conf->upstream.pass_headers = NULL;
      *     conf->upstream.schema = { 0, NULL };
      *     conf->upstream.uri = { 0, NULL };
      *     conf->upstream.location = NULL;
@@ -1671,6 +1672,9 @@ ngx_http_fastcgi_create_loc_conf(ngx_con
     conf->upstream.pass_request_headers = NGX_CONF_UNSET;
     conf->upstream.pass_request_body = NGX_CONF_UNSET;
 
+    conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
+    conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
+
     conf->upstream.intercept_errors = NGX_CONF_UNSET;
 
     /* "fastcgi_cyclic_temp_file" is disabled */
@@ -1691,11 +1695,8 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf
     u_char                       *p;
     size_t                        size;
     uintptr_t                    *code;
-    ngx_str_t                    *header;
-    ngx_uint_t                    i, j;
-    ngx_array_t                   hide_headers;
+    ngx_uint_t                    i;
     ngx_keyval_t                 *src;
-    ngx_hash_key_t               *hk;
     ngx_hash_init_t               hash;
     ngx_http_script_compile_t     sc;
     ngx_http_script_copy_code_t  *copy;
@@ -1857,108 +1858,19 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf
 
     ngx_conf_merge_str_value(conf->index, prev->index, "");
 
-    if (conf->upstream.hide_headers == NULL
-        && conf->upstream.pass_headers == NULL)
-    {
-        conf->upstream.hide_headers = prev->upstream.hide_headers;
-        conf->upstream.pass_headers = prev->upstream.pass_headers;
-        conf->upstream.hide_headers_hash = prev->upstream.hide_headers_hash;
-
-        if (conf->upstream.hide_headers_hash.buckets) {
-            goto peers;
-        }
-
-    } else {
-        if (conf->upstream.hide_headers == NULL) {
-            conf->upstream.hide_headers = prev->upstream.hide_headers;
-        }
-
-        if (conf->upstream.pass_headers == NULL) {
-            conf->upstream.pass_headers = prev->upstream.pass_headers;
-        }
-    }
-
-    if (ngx_array_init(&hide_headers, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
+    hash.max_size = 512;
+    hash.bucket_size = ngx_align(64, ngx_cacheline_size);
+    hash.name = "fastcgi_hide_headers_hash";
+
+    if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
+                                            &prev->upstream,
+                                            ngx_http_fastcgi_hide_headers,
+                                            &hash)
         != NGX_OK)
     {
         return NGX_CONF_ERROR;
     }
 
-    for (header = ngx_http_fastcgi_hide_headers; header->len; header++) {
-        hk = ngx_array_push(&hide_headers);
-        if (hk == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        hk->key = *header;
-        hk->key_hash = ngx_hash_key_lc(header->data, header->len);
-        hk->value = (void *) 1;
-    }
-
-    if (conf->upstream.hide_headers) {
-
-        header = conf->upstream.hide_headers->elts;
-
-        for (i = 0; i < conf->upstream.hide_headers->nelts; i++) {
-
-            hk = hide_headers.elts;
-
-            for (j = 0; j < hide_headers.nelts; j++) {
-                if (ngx_strcasecmp(header[i].data, hk[j].key.data) == 0) {
-                    goto exist;
-                }
-            }
-
-            hk = ngx_array_push(&hide_headers);
-            if (hk == NULL) {
-                return NGX_CONF_ERROR;
-            }
-
-            hk->key = header[i];
-            hk->key_hash = ngx_hash_key_lc(header[i].data, header[i].len);
-            hk->value = (void *) 1;
-
-        exist:
-
-            continue;
-        }
-    }
-
-    if (conf->upstream.pass_headers) {
-
-        hk = hide_headers.elts;
-        header = conf->upstream.pass_headers->elts;
-
-        for (i = 0; i < conf->upstream.pass_headers->nelts; i++) {
-
-            for (j = 0; j < hide_headers.nelts; j++) {
-
-                if (hk[j].key.data == NULL) {
-                    continue;
-                }
-
-                if (ngx_strcasecmp(header[i].data, hk[j].key.data) == 0) {
-                    hk[j].key.data = NULL;
-                    break;
-                }
-            }
-        }
-    }
-
-    hash.hash = &conf->upstream.hide_headers_hash;
-    hash.key = ngx_hash_key_lc;
-    hash.max_size = 512;
-    hash.bucket_size = ngx_align(64, ngx_cacheline_size);
-    hash.name = "fastcgi_hide_headers_hash";
-    hash.pool = cf->pool;
-    hash.temp_pool = NULL;
-
-    if (ngx_hash_init(&hash, hide_headers.elts, hide_headers.nelts) != NGX_OK) {
-        return NGX_CONF_ERROR;
-    }
-
-peers:
-
     if (conf->upstream.upstream == NULL) {
         conf->upstream.upstream = prev->upstream.upstream;
         conf->upstream.schema = prev->upstream.schema;
--- a/src/http/modules/ngx_http_flv_module.c
+++ b/src/http/modules/ngx_http_flv_module.c
@@ -63,7 +63,6 @@ ngx_http_flv_handler(ngx_http_request_t 
     u_char                    *p, *last;
     off_t                      start, len;
     size_t                     root;
-    ngx_fd_t                   fd;
     ngx_int_t                  rc;
     ngx_uint_t                 level, i;
     ngx_str_t                  path;
@@ -149,11 +148,9 @@ ngx_http_flv_handler(ngx_http_request_t 
         return rc;
     }
 
-    fd = of.fd;
-
     if (!of.is_file) {
 
-        if (ngx_close_file(fd) == NGX_FILE_ERROR) {
+        if (ngx_close_file(of.fd) == NGX_FILE_ERROR) {
             ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
                           ngx_close_file_n " \"%s\" failed", path.data);
         }
@@ -235,7 +232,7 @@ ngx_http_flv_handler(ngx_http_request_t 
     b->last_buf = 1;
     b->last_in_chain = 1;
 
-    b->file->fd = fd;
+    b->file->fd = of.fd;
     b->file->name = path;
     b->file->log = log;
 
--- a/src/http/modules/ngx_http_limit_zone_module.c
+++ b/src/http/modules/ngx_http_limit_zone_module.c
@@ -239,54 +239,36 @@ static void
 ngx_http_limit_zone_rbtree_insert_value(ngx_rbtree_node_t *temp,
     ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
 {
-    ngx_http_limit_zone_node_t  *lzn, *lznt;
+    ngx_rbtree_node_t           **p;
+    ngx_http_limit_zone_node_t   *lzn, *lznt;
 
     for ( ;; ) {
 
         if (node->key < temp->key) {
 
-            if (temp->left == sentinel) {
-                temp->left = node;
-                break;
-            }
-
-            temp = temp->left;
+            p = &temp->left;
 
         } else if (node->key > temp->key) {
 
-            if (temp->right == sentinel) {
-                temp->right = node;
-                break;
-            }
-
-            temp = temp->right;
+            p = &temp->right;
 
         } else { /* node->key == temp->key */
 
             lzn = (ngx_http_limit_zone_node_t *) &node->color;
             lznt = (ngx_http_limit_zone_node_t *) &temp->color;
 
-            if (ngx_memn2cmp(lzn->data, lznt->data, lzn->len, lznt->len) < 0) {
-
-                if (temp->left == sentinel) {
-                    temp->left = node;
-                    break;
-                }
-
-                temp = temp->left;
+            p = (ngx_memn2cmp(lzn->data, lznt->data, lzn->len, lznt->len) < 0)
+                ? &temp->left : &temp->right;
+        }
 
-            } else {
+        if (*p == sentinel) {
+            break;
+        }
 
-                if (temp->right == sentinel) {
-                    temp->right = node;
-                    break;
-                }
-
-                temp = temp->right;
-            }
-        }
+        temp = *p;
     }
 
+    *p = node;
     node->parent = temp;
     node->left = sentinel;
     node->right = sentinel;
@@ -362,11 +344,8 @@ ngx_http_limit_zone_init_zone(ngx_shm_zo
         return NGX_ERROR;
     }
 
-    ngx_rbtree_sentinel_init(sentinel);
-
-    ctx->rbtree->root = sentinel;
-    ctx->rbtree->sentinel = sentinel;
-    ctx->rbtree->insert = ngx_http_limit_zone_rbtree_insert_value;
+    ngx_rbtree_init(ctx->rbtree, sentinel,
+                    ngx_http_limit_zone_rbtree_insert_value);
 
     return NGX_OK;
 }
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -959,7 +959,7 @@ ngx_http_proxy_process_status_line(ngx_h
     ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
 
     if (ctx == NULL) {
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        return NGX_ERROR;
     }
 
     rc = ngx_http_proxy_parse_status_line(r, ctx);
@@ -994,7 +994,7 @@ ngx_http_proxy_process_status_line(ngx_h
     u->headers_in.status_line.data = ngx_palloc(r->pool,
                                                 u->headers_in.status_line.len);
     if (u->headers_in.status_line.data == NULL) {
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        return NGX_ERROR;
     }
 
     ngx_memcpy(u->headers_in.status_line.data, ctx->status_start,
@@ -1239,7 +1239,7 @@ ngx_http_proxy_process_header(ngx_http_r
 
             h = ngx_list_push(&r->upstream->headers_in.headers);
             if (h == NULL) {
-                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                return NGX_ERROR;
             }
 
             h->hash = r->header_hash;
@@ -1250,7 +1250,7 @@ ngx_http_proxy_process_header(ngx_http_r
             h->key.data = ngx_palloc(r->pool,
                                h->key.len + 1 + h->value.len + 1 + h->key.len);
             if (h->key.data == NULL) {
-                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                return NGX_ERROR;
             }
 
             h->value.data = h->key.data + h->key.len + 1;
@@ -1272,7 +1272,7 @@ ngx_http_proxy_process_header(ngx_http_r
                                h->lowcase_key, h->key.len);
 
             if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
-                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                return NGX_ERROR;
             }
 
             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -1297,7 +1297,7 @@ ngx_http_proxy_process_header(ngx_http_r
             if (r->upstream->headers_in.server == NULL) {
                 h = ngx_list_push(&r->upstream->headers_in.headers);
                 if (h == NULL) {
-                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                    return NGX_ERROR;
                 }
 
                 h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash(
@@ -1313,7 +1313,7 @@ ngx_http_proxy_process_header(ngx_http_r
             if (r->upstream->headers_in.date == NULL) {
                 h = ngx_list_push(&r->upstream->headers_in.headers);
                 if (h == NULL) {
-                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                    return NGX_ERROR;
                 }
 
                 h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e');
@@ -1634,8 +1634,6 @@ ngx_http_proxy_create_loc_conf(ngx_conf_
      *     conf->upstream.next_upstream = 0;
      *     conf->upstream.temp_path = NULL;
      *     conf->upstream.hide_headers_hash = { NULL, 0 };
-     *     conf->upstream.hide_headers = NULL;
-     *     conf->upstream.pass_headers = NULL;
      *     conf->upstream.schema = { 0, NULL };
      *     conf->upstream.uri = { 0, NULL };
      *     conf->upstream.location = NULL;
@@ -1672,6 +1670,9 @@ ngx_http_proxy_create_loc_conf(ngx_conf_
     conf->upstream.pass_request_headers = NGX_CONF_UNSET;
     conf->upstream.pass_request_body = NGX_CONF_UNSET;
 
+    conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
+    conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
+
     conf->upstream.intercept_errors = NGX_CONF_UNSET;
 
     /* "proxy_cyclic_temp_file" is disabled */
@@ -1696,9 +1697,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t
     u_char                       *p;
     size_t                        size;
     uintptr_t                    *code;
-    ngx_str_t                    *header;
-    ngx_uint_t                    i, j;
-    ngx_array_t                   hide_headers;
+    ngx_uint_t                    i;
     ngx_keyval_t                 *src, *s, *h;
     ngx_hash_key_t               *hk;
     ngx_hash_init_t               hash;
@@ -1913,107 +1912,18 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t
     conf->headers_hash_bucket_size = ngx_align(conf->headers_hash_bucket_size,
                                                ngx_cacheline_size);
 
-    if (conf->upstream.hide_headers == NULL
-        && conf->upstream.pass_headers == NULL)
-    {
-        conf->upstream.hide_headers = prev->upstream.hide_headers;
-        conf->upstream.pass_headers = prev->upstream.pass_headers;
-        conf->upstream.hide_headers_hash = prev->upstream.hide_headers_hash;
-
-        if (conf->upstream.hide_headers_hash.buckets) {
-            goto peers;
-        }
-
-    } else {
-        if (conf->upstream.hide_headers == NULL) {
-            conf->upstream.hide_headers = prev->upstream.hide_headers;
-        }
-
-        if (conf->upstream.pass_headers == NULL) {
-            conf->upstream.pass_headers = prev->upstream.pass_headers;
-        }
-    }
-
-    if (ngx_array_init(&hide_headers, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
+    hash.max_size = conf->headers_hash_max_size;
+    hash.bucket_size = conf->headers_hash_bucket_size;
+    hash.name = "proxy_headers_hash";
+
+    if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
+                                            &prev->upstream,
+                                            ngx_http_proxy_hide_headers, &hash)
         != NGX_OK)
     {
         return NGX_CONF_ERROR;
     }
 
-    for (header = ngx_http_proxy_hide_headers; header->len; header++) {
-        hk = ngx_array_push(&hide_headers);
-        if (hk == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        hk->key = *header;
-        hk->key_hash = ngx_hash_key_lc(header->data, header->len);
-        hk->value = (void *) 1;
-    }
-
-    if (conf->upstream.hide_headers) {
-
-        header = conf->upstream.hide_headers->elts;
-
-        for (i = 0; i < conf->upstream.hide_headers->nelts; i++) {
-
-            hk = hide_headers.elts;
-
-            for (j = 0; j < hide_headers.nelts; j++) {
-                if (ngx_strcasecmp(header[i].data, hk[j].key.data) == 0) {
-                    goto exist;
-                }
-            }
-
-            hk = ngx_array_push(&hide_headers);
-            if (hk == NULL) {
-                return NGX_CONF_ERROR;
-            }
-
-            hk->key = header[i];
-            hk->key_hash = ngx_hash_key_lc(header[i].data, header[i].len);
-            hk->value = (void *) 1;
-
-        exist:
-
-            continue;
-        }
-    }
-
-    if (conf->upstream.pass_headers) {
-
-        hk = hide_headers.elts;
-        header = conf->upstream.pass_headers->elts;
-
-        for (i = 0; i < conf->upstream.pass_headers->nelts; i++) {
-            for (j = 0; j < hide_headers.nelts; j++) {
-
-                if (hk[j].key.data == NULL) {
-                    continue;
-                }
-
-                if (ngx_strcasecmp(header[i].data, hk[j].key.data) == 0) {
-                    hk[j].key.data = NULL;
-                    break;
-                }
-            }
-        }
-    }
-
-    hash.hash = &conf->upstream.hide_headers_hash;
-    hash.key = ngx_hash_key_lc;
-    hash.max_size = conf->headers_hash_max_size;
-    hash.bucket_size = conf->headers_hash_bucket_size;
-    hash.name = "proxy_headers_hash";
-    hash.pool = cf->pool;
-    hash.temp_pool = NULL;
-
-    if (ngx_hash_init(&hash, hide_headers.elts, hide_headers.nelts) != NGX_OK) {
-        return NGX_CONF_ERROR;
-    }
-
-peers:
-
     if (conf->upstream.upstream == NULL) {
         conf->upstream.upstream = prev->upstream.upstream;
 
--- a/src/http/modules/ngx_http_referer_module.c
+++ b/src/http/modules/ngx_http_referer_module.c
@@ -106,11 +106,6 @@ ngx_http_referer_variable(ngx_http_reque
     ngx_uint_t                 i, key;
     ngx_http_referer_conf_t   *rlcf;
     u_char                     buf[256];
-#if (NGX_PCRE)
-    ngx_int_t                  n;
-    ngx_str_t                  referer;
-    ngx_http_referer_regex_t  *regex;
-#endif
 
     rlcf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module);
 
@@ -173,6 +168,9 @@ ngx_http_referer_variable(ngx_http_reque
 #if (NGX_PCRE)
 
     if (rlcf->regex) {
+        ngx_int_t                  n;
+        ngx_str_t                  referer;
+        ngx_http_referer_regex_t  *regex;
 
         referer.len = len - 7;
         referer.data = ref;
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -2373,11 +2373,6 @@ ngx_http_ssi_if(ngx_http_request_t *r, n
     ngx_str_t    *expr, left, right;
     ngx_int_t     rc;
     ngx_uint_t    negative, noregex, flags;
-#if (NGX_PCRE)
-    ngx_str_t     err;
-    ngx_regex_t  *regex;
-    u_char        errstr[NGX_MAX_CONF_ERRSTR];
-#endif
 
     if (ctx->command.len == 2) {
         if (ctx->conditional) {
@@ -2511,6 +2506,10 @@ ngx_http_ssi_if(ngx_http_request_t *r, n
 
     } else {
 #if (NGX_PCRE)
+        ngx_str_t     err;
+        ngx_regex_t  *regex;
+        u_char        errstr[NGX_MAX_CONF_ERRSTR];
+
         err.len = NGX_MAX_CONF_ERRSTR;
         err.data = errstr;
 
--- a/src/http/modules/ngx_http_static_module.c
+++ b/src/http/modules/ngx_http_static_module.c
@@ -49,7 +49,6 @@ ngx_http_static_handler(ngx_http_request
 {
     u_char                    *last, *location;
     size_t                     root;
-    ngx_fd_t                   fd;
     ngx_str_t                  path;
     ngx_int_t                  rc;
     ngx_uint_t                 level;
@@ -140,9 +139,7 @@ ngx_http_static_handler(ngx_http_request
         return rc;
     }
 
-    fd = of.fd;
-
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", fd);
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd);
 
     if (of.is_dir) {
 
@@ -230,7 +227,7 @@ ngx_http_static_handler(ngx_http_request
     b->last_buf = (r == r->main) ? 1: 0;
     b->last_in_chain = 1;
 
-    b->file->fd = fd;
+    b->file->fd = of.fd;
     b->file->name = path;
     b->file->log = log;
 
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw(
     HTTP_INSUFFICIENT_STORAGE
 );
 
-our $VERSION = '0.6.21';
+our $VERSION = '0.6.22';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -13,19 +13,16 @@
 
 #include "XSUB.h"
 
+
 #define ngx_http_perl_set_request(r)                                          \
     r = INT2PTR(ngx_http_request_t *, SvIV((SV *) SvRV(ST(0))))
 
 
-#define ngx_http_perl_set_targ(p, len, z)                                     \
+#define ngx_http_perl_set_targ(p, len)                                        \
                                                                               \
-    sv_upgrade(TARG, SVt_PV);                                                 \
+    SvUPGRADE(TARG, SVt_PV);                                                  \
     SvPOK_on(TARG);                                                           \
-    SvPV_set(TARG, (char *) p);                                               \
-    SvLEN_set(TARG, len + z);                                                 \
-    SvCUR_set(TARG, len);                                                     \
-    SvFAKE_on(TARG);                                                          \
-    SvREADONLY_on(TARG);                                                      \
+    sv_setpvn(TARG, (char *) p, len)
 
 
 static ngx_int_t
@@ -42,8 +39,12 @@ ngx_http_perl_sv2str(pTHX_ ngx_http_requ
 
     s->len = len;
 
-    if (SvREADONLY(sv)) {
+    if (SvREADONLY(sv) && SvPOK(sv)) {
         s->data = p;
+
+        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "perl sv2str: %08XD \"%V\"", sv->sv_flags, s);
+
         return NGX_OK;
     }
 
@@ -54,6 +55,9 @@ ngx_http_perl_sv2str(pTHX_ ngx_http_requ
 
     ngx_memcpy(s->data, p, len);
 
+    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "perl sv2str: %08XD \"%V\"", sv->sv_flags, s);
+
     return NGX_OK;
 }
 
@@ -165,7 +169,7 @@ uri(r)
     ngx_http_request_t  *r;
 
     ngx_http_perl_set_request(r);
-    ngx_http_perl_set_targ(r->uri.data, r->uri.len, 0);
+    ngx_http_perl_set_targ(r->uri.data, r->uri.len);
 
     ST(0) = TARG;
 
@@ -178,7 +182,7 @@ args(r)
     ngx_http_request_t  *r;
 
     ngx_http_perl_set_request(r);
-    ngx_http_perl_set_targ(r->args.data, r->args.len, 0);
+    ngx_http_perl_set_targ(r->args.data, r->args.len);
 
     ST(0) = TARG;
 
@@ -191,7 +195,7 @@ request_method(r)
     ngx_http_request_t  *r;
 
     ngx_http_perl_set_request(r);
-    ngx_http_perl_set_targ(r->method_name.data, r->method_name.len, 0);
+    ngx_http_perl_set_targ(r->method_name.data, r->method_name.len);
 
     ST(0) = TARG;
 
@@ -205,7 +209,7 @@ remote_addr(r)
 
     ngx_http_perl_set_request(r);
     ngx_http_perl_set_targ(r->connection->addr_text.data,
-                           r->connection->addr_text.len, 1);
+                           r->connection->addr_text.len);
 
     ST(0) = TARG;
 
@@ -259,7 +263,7 @@ header_in(r, key)
             ph = (ngx_table_elt_t **) ((char *) &r->headers_in + hh->offset);
 
             if (*ph) {
-                ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len, 0);
+                ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len);
 
                 goto done;
             }
@@ -278,7 +282,7 @@ header_in(r, key)
         ph = r->headers_in.cookies.elts;
 
         if (n == 1) {
-            ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len, 0);
+            ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len);
 
             goto done;
         }
@@ -306,7 +310,7 @@ header_in(r, key)
             *p++ = ';'; *p++ = ' ';
         }
 
-        ngx_http_perl_set_targ(cookie, size, 0);
+        ngx_http_perl_set_targ(cookie, size);
 
         goto done;
     }
@@ -334,7 +338,7 @@ header_in(r, key)
             continue;
         }
 
-        ngx_http_perl_set_targ(h[i].value.data, h[i].value.len, 0);
+        ngx_http_perl_set_targ(h[i].value.data, h[i].value.len);
 
         goto done;
     }
@@ -402,7 +406,7 @@ request_body(r)
         XSRETURN_UNDEF;
     }
 
-    ngx_http_perl_set_targ(r->request_body->bufs->buf->pos, len, 0);
+    ngx_http_perl_set_targ(r->request_body->bufs->buf->pos, len);
 
     ST(0) = TARG;
 
@@ -421,7 +425,7 @@ request_body_file(r)
     }
 
     ngx_http_perl_set_targ(r->request_body->temp_file->file.name.data,
-                           r->request_body->temp_file->file.name.len, 1);
+                           r->request_body->temp_file->file.name.len);
 
     ST(0) = TARG;
 
@@ -500,7 +504,7 @@ filename(r)
 
     done:
 
-    ngx_http_perl_set_targ(ctx->filename.data, ctx->filename.len, 1);
+    ngx_http_perl_set_targ(ctx->filename.data, ctx->filename.len);
 
     ST(0) = TARG;
 
@@ -532,7 +536,7 @@ print(r, ...)
             sv = SvRV(sv);
         }
 
-        if (SvREADONLY(sv)) {
+        if (SvREADONLY(sv) && SvPOK(sv)) {
 
             p = (u_char *) SvPV(sv, len);
 
@@ -778,7 +782,7 @@ unescape(r, text, type = 0)
     ngx_unescape_uri(&dst, &src, len, (ngx_uint_t) type);
     *dst = '\0';
 
-    ngx_http_perl_set_targ(p, dst - p, 1);
+    ngx_http_perl_set_targ(p, dst - p);
 
     ST(0) = TARG;
 
@@ -875,7 +879,7 @@ variable(r, name, value = NULL)
                     XSRETURN_UNDEF;
                 }
 
-                ngx_http_perl_set_targ(v[i].value.data, v[i].value.len, 0);
+                ngx_http_perl_set_targ(v[i].value.data, v[i].value.len);
 
                 goto done;
             }
@@ -919,7 +923,7 @@ variable(r, name, value = NULL)
         XSRETURN_UNDEF;
     }
 
-    ngx_http_perl_set_targ(vv->data, vv->len, 0);
+    ngx_http_perl_set_targ(vv->data, vv->len);
 
     done:
 
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -230,6 +230,10 @@ ngx_http_perl_handle_request(ngx_http_re
 
     }
 
+    if (rc == NGX_DONE) {
+        return;
+    }
+
     if (rc > 600) {
         rc = NGX_OK;
     }
@@ -627,12 +631,13 @@ static ngx_int_t
 ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, HV *nginx, SV *sub,
     ngx_str_t **args, ngx_str_t *handler, ngx_str_t *rv)
 {
-    SV          *sv;
-    int          n, status;
-    char        *line;
-    STRLEN       len, n_a;
-    ngx_str_t    err;
-    ngx_uint_t   i;
+    SV                *sv;
+    int                n, status;
+    char              *line;
+    STRLEN             len, n_a;
+    ngx_str_t          err;
+    ngx_uint_t         i;
+    ngx_connection_t  *c;
 
     dSP;
 
@@ -658,15 +663,26 @@ ngx_http_perl_call_handler(pTHX_ ngx_htt
 
     PUTBACK;
 
+    c = r->connection;
+
     n = call_sv(sub, G_EVAL);
 
     SPAGAIN;
 
+    if (c->destroyed) {
+        PUTBACK;
+
+        FREETMPS;
+        LEAVE;
+
+        return NGX_DONE;
+    }
+
     if (n) {
         if (rv == NULL) {
             status = POPi;
 
-            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
                            "call_sv: %d", status);
 
         } else {
@@ -697,9 +713,8 @@ ngx_http_perl_call_handler(pTHX_ ngx_htt
         }
         err.len = len + 1;
 
-        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                      "call_sv(\"%V\") failed: \"%V\"",
-                      handler, &err);
+        ngx_log_error(NGX_LOG_ERR, c->log, 0,
+                      "call_sv(\"%V\") failed: \"%V\"", handler, &err);
 
         if (rv) {
             return NGX_ERROR;
@@ -709,7 +724,7 @@ ngx_http_perl_call_handler(pTHX_ ngx_htt
     }
 
     if (n != 1) {
-        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+        ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                       "call_sv(\"%V\") returned %d results", handler, n);
         status = NGX_OK;
     }
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -101,9 +101,6 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
 #if (NGX_PCRE)
     ngx_uint_t                   regex;
 #endif
-#if (NGX_WIN32)
-    ngx_iocp_conf_t             *iocpcf;
-#endif
 
     /* the main http context */
 
@@ -821,10 +818,14 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
             ls->log.handler = ngx_accept_log_error;
 
 #if (NGX_WIN32)
+            {
+            ngx_iocp_conf_t  *iocpcf;
+
             iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
             if (iocpcf->acceptex_read) {
                 ls->post_accept_buffer_size = cscf->client_header_buffer_size;
             }
+            }
 #endif
 
             ls->backlog = in_addr[a].listen_conf->backlog;
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1803,10 +1803,6 @@ ngx_http_core_location(ngx_conf_t *cf, n
     ngx_http_conf_ctx_t       *ctx, *pctx;
     ngx_http_core_srv_conf_t  *cscf;
     ngx_http_core_loc_conf_t  *clcf, *pclcf, **clcfp;
-#if (NGX_PCRE)
-    ngx_str_t                  err;
-    u_char                     errstr[NGX_MAX_CONF_ERRSTR];
-#endif
 
     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
     if (ctx == NULL) {
@@ -1861,6 +1857,9 @@ ngx_http_core_location(ngx_conf_t *cf, n
                        && value[1].data[1] == '*'))
         {
 #if (NGX_PCRE)
+            ngx_str_t  err;
+            u_char     errstr[NGX_MAX_CONF_ERRSTR];
+
             err.len = NGX_MAX_CONF_ERRSTR;
             err.data = errstr;
 
@@ -2803,10 +2802,6 @@ ngx_http_core_server_name(ngx_conf_t *cf
     ngx_str_t               *value, name;
     ngx_uint_t               i;
     ngx_http_server_name_t  *sn;
-#if (NGX_PCRE)
-    ngx_str_t                err;
-    u_char                   errstr[NGX_MAX_CONF_ERRSTR];
-#endif
 
     value = cf->args->elts;
 
@@ -2882,6 +2877,10 @@ ngx_http_core_server_name(ngx_conf_t *cf
         }
 
 #if (NGX_PCRE)
+        {
+        ngx_str_t  err;
+        u_char     errstr[NGX_MAX_CONF_ERRSTR];
+
         err.len = NGX_MAX_CONF_ERRSTR;
         err.data = errstr;
 
@@ -2898,7 +2897,7 @@ ngx_http_core_server_name(ngx_conf_t *cf
 
         sn->name.len = value[i].len;
         sn->name.data = value[i].data;
-
+        }
 #else
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "the using of the regex \"%V\" "
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -1039,7 +1039,7 @@ ngx_http_parse_complex_uri(ngx_http_requ
                 break;
 #endif
             case '/':
-                if (merge_slashes) {
+                if (!merge_slashes) {
                     *u++ = ch;
                 }
                 break;
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -232,9 +232,6 @@ ngx_http_init_request(ngx_event_t *rev)
     ngx_http_core_srv_conf_t   *cscf;
     ngx_http_core_loc_conf_t   *clcf;
     ngx_http_core_main_conf_t  *cmcf;
-#if (NGX_HTTP_SSL)
-    ngx_http_ssl_srv_conf_t    *sscf;
-#endif
 
 #if (NGX_STAT_STUB)
     ngx_atomic_fetch_add(ngx_stat_reading, -1);
@@ -354,6 +351,9 @@ ngx_http_init_request(ngx_event_t *rev)
 
 #if (NGX_HTTP_SSL)
 
+    {
+    ngx_http_ssl_srv_conf_t  *sscf;
+
     sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
     if (sscf->enable) {
 
@@ -370,6 +370,7 @@ ngx_http_init_request(ngx_event_t *rev)
 
         r->main_filter_need_in_memory = 1;
     }
+    }
 
 #endif
 
@@ -1398,11 +1399,7 @@ ngx_http_process_request_header(ngx_http
 static void
 ngx_http_process_request(ngx_http_request_t *r)
 {
-    ngx_connection_t         *c;
-#if (NGX_HTTP_SSL)
-    long                      rc;
-    ngx_http_ssl_srv_conf_t  *sscf;
-#endif
+    ngx_connection_t  *c;
 
     c = r->connection;
 
@@ -1416,6 +1413,9 @@ ngx_http_process_request(ngx_http_reques
 #if (NGX_HTTP_SSL)
 
     if (c->ssl) {
+        long                      rc;
+        ngx_http_ssl_srv_conf_t  *sscf;
+
         sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
 
         if (sscf->verify) {
@@ -1469,12 +1469,6 @@ ngx_http_find_virtual_server(ngx_http_re
 {
     ngx_http_core_loc_conf_t  *clcf;
     ngx_http_core_srv_conf_t  *cscf;
-#if (NGX_PCRE)
-    ngx_int_t                  n;
-    ngx_uint_t                 i;
-    ngx_str_t                  name;
-    ngx_http_server_name_t    *sn;
-#endif
 
     cscf = ngx_hash_find_combined(&r->virtual_names->names, hash, host, len);
 
@@ -1485,6 +1479,10 @@ ngx_http_find_virtual_server(ngx_http_re
 #if (NGX_PCRE)
 
     if (r->virtual_names->nregex) {
+        ngx_int_t                n;
+        ngx_uint_t               i;
+        ngx_str_t                name;
+        ngx_http_server_name_t  *sn;
 
         name.len = len;
         name.data = host;
@@ -2095,7 +2093,7 @@ ngx_http_set_keepalive(ngx_http_request_
 
     if (hc->free) {
         for (i = 0; i < hc->nfree; i++) {
-            ngx_pfree(c->pool, hc->free[i]);
+            ngx_pfree(c->pool, hc->free[i]->start);
             hc->free[i] = NULL;
         }
 
@@ -2107,7 +2105,7 @@ ngx_http_set_keepalive(ngx_http_request_
 
     if (hc->busy) {
         for (i = 0; i < hc->nbusy; i++) {
-            ngx_pfree(c->pool, hc->busy[i]);
+            ngx_pfree(c->pool, hc->busy[i]->start);
             hc->busy[i] = NULL;
         }
 
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -381,7 +381,7 @@ ngx_http_upstream_init(ngx_http_request_
 
     } else {
 
-        host = &r->upstream->resolved->host;
+        host = &u->resolved->host;
 
         umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
 
@@ -665,7 +665,6 @@ ngx_http_upstream_connect(ngx_http_reque
     tp = ngx_timeofday();
     u->state->response_sec = tp->sec;
     u->state->response_msec = tp->msec;
-    u->state->peer = u->peer.name;
 
     rc = ngx_event_connect_peer(&u->peer);
 
@@ -678,6 +677,8 @@ ngx_http_upstream_connect(ngx_http_reque
         return;
     }
 
+    u->state->peer = u->peer.name;
+
     if (rc == NGX_BUSY) {
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams");
         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_NOLIVE);
@@ -840,10 +841,9 @@ ngx_http_upstream_reinit(ngx_http_reques
         return NGX_ERROR;
     }
 
-    ngx_memzero(&r->upstream->headers_in,
-                sizeof(ngx_http_upstream_headers_in_t));
-
-    if (ngx_list_init(&r->upstream->headers_in.headers, r->pool, 8,
+    ngx_memzero(&u->headers_in, sizeof(ngx_http_upstream_headers_in_t));
+
+    if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
                       sizeof(ngx_table_elt_t))
         != NGX_OK)
     {
@@ -1078,7 +1078,7 @@ ngx_http_upstream_process_header(ngx_eve
 
         u->buffer.tag = u->output.tag;
 
-        if (ngx_list_init(&r->upstream->headers_in.headers, r->pool, 8,
+        if (ngx_list_init(&u->headers_in.headers, r->pool, 8,
                           sizeof(ngx_table_elt_t))
             != NGX_OK)
         {
@@ -1158,7 +1158,7 @@ ngx_http_upstream_process_header(ngx_eve
         return;
     }
 
-    if (rc == NGX_ERROR || rc == NGX_HTTP_INTERNAL_SERVER_ERROR) {
+    if (rc == NGX_ERROR) {
         ngx_http_upstream_finalize_request(r, u,
                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
@@ -1247,11 +1247,11 @@ ngx_http_upstream_process_header(ngx_eve
 
     umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
 
-    if (r->upstream->headers_in.x_accel_redirect) {
+    if (u->headers_in.x_accel_redirect) {
 
         ngx_http_upstream_finalize_request(r, u, NGX_DECLINED);
 
-        part = &r->upstream->headers_in.headers.part;
+        part = &u->headers_in.headers.part;
         h = part->elts;
 
         for (i = 0; /* void */; i++) {
@@ -1278,7 +1278,7 @@ ngx_http_upstream_process_header(ngx_eve
             }
         }
 
-        uri = &r->upstream->headers_in.x_accel_redirect->value;
+        uri = &u->headers_in.x_accel_redirect->value;
         args.len = 0;
         args.data = NULL;
         flags = 0;
@@ -1300,7 +1300,7 @@ ngx_http_upstream_process_header(ngx_eve
         return;
     }
 
-    part = &r->upstream->headers_in.headers.part;
+    part = &u->headers_in.headers.part;
     h = part->elts;
 
     for (i = 0; /* void */; i++) {
@@ -2164,9 +2164,9 @@ ngx_http_upstream_store(ngx_http_request
 
 #endif
 
-    if (r->upstream->headers_in.last_modified) {
-
-        last_modified = &r->upstream->headers_in.last_modified->value;
+    if (u->headers_in.last_modified) {
+
+        last_modified = &u->headers_in.last_modified->value;
 
         lm = ngx_http_parse_time(last_modified->data, last_modified->len);
 
@@ -2224,7 +2224,7 @@ ngx_http_upstream_store(ngx_http_request
 #if (NGX_WIN32)
 
     if (err == NGX_EEXIST) {
-        if (ngx_win32_rename_file(temp, &path, r->pool) != NGX_ERROR) {
+        if (ngx_win32_rename_file(temp, &path, r->connection->log) == NGX_OK) {
 
             if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) {
                 return;
@@ -2372,14 +2372,18 @@ ngx_http_upstream_cleanup(void *data)
 {
     ngx_http_request_t *r = data;
 
+    ngx_http_upstream_t  *u;
+
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "cleanup http upstream request: \"%V\"", &r->uri);
 
-    if (r->upstream->resolved && r->upstream->resolved->ctx) {
-        ngx_resolve_name_done(r->upstream->resolved->ctx);
+    u = r->upstream;
+
+    if (u->resolved && u->resolved->ctx) {
+        ngx_resolve_name_done(u->resolved->ctx);
     }
 
-    ngx_http_upstream_finalize_request(r, r->upstream, NGX_DONE);
+    ngx_http_upstream_finalize_request(r, u, NGX_DONE);
 }
 
 
@@ -3408,6 +3412,113 @@ ngx_http_upstream_add(ngx_conf_t *cf, ng
 }
 
 
+ngx_int_t
+ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
+    ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
+    ngx_str_t *default_hide_headers, ngx_hash_init_t *hash)
+{
+    ngx_str_t       *h;
+    ngx_uint_t       i, j;
+    ngx_array_t      hide_headers;
+    ngx_hash_key_t  *hk;
+
+    if (conf->hide_headers == NGX_CONF_UNSET_PTR
+        && conf->pass_headers == NGX_CONF_UNSET_PTR)
+    {
+        conf->hide_headers_hash = prev->hide_headers_hash;
+
+        if (conf->hide_headers_hash.buckets) {
+            return NGX_OK;
+        }
+
+        conf->hide_headers = prev->hide_headers;
+        conf->pass_headers = prev->pass_headers;
+
+    } else {
+        if (conf->hide_headers == NGX_CONF_UNSET_PTR) {
+            conf->hide_headers = prev->hide_headers;
+        }
+
+        if (conf->pass_headers == NGX_CONF_UNSET_PTR) {
+            conf->pass_headers = prev->pass_headers;
+        }
+    }
+
+    if (ngx_array_init(&hide_headers, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
+    for (h = default_hide_headers; h->len; h++) {
+        hk = ngx_array_push(&hide_headers);
+        if (hk == NULL) {
+            return NGX_ERROR;
+        }
+
+        hk->key = *h;
+        hk->key_hash = ngx_hash_key_lc(h->data, h->len);
+        hk->value = (void *) 1;
+    }
+
+    if (conf->hide_headers != NGX_CONF_UNSET_PTR) {
+
+        h = conf->hide_headers->elts;
+
+        for (i = 0; i < conf->hide_headers->nelts; i++) {
+
+            hk = hide_headers.elts;
+
+            for (j = 0; j < hide_headers.nelts; j++) {
+                if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) {
+                    goto exist;
+                }
+            }
+
+            hk = ngx_array_push(&hide_headers);
+            if (hk == NULL) {
+                return NGX_ERROR;
+            }
+
+            hk->key = h[i];
+            hk->key_hash = ngx_hash_key_lc(h[i].data, h[i].len);
+            hk->value = (void *) 1;
+
+        exist:
+
+            continue;
+        }
+    }
+
+    if (conf->pass_headers != NGX_CONF_UNSET_PTR) {
+
+        h = conf->pass_headers->elts;
+        hk = hide_headers.elts;
+
+        for (i = 0; i < conf->pass_headers->nelts; i++) {
+            for (j = 0; j < hide_headers.nelts; j++) {
+
+                if (hk[j].key.data == NULL) {
+                    continue;
+                }
+
+                if (ngx_strcasecmp(h[i].data, hk[j].key.data) == 0) {
+                    hk[j].key.data = NULL;
+                    break;
+                }
+            }
+        }
+    }
+
+    hash->hash = &conf->hide_headers_hash;
+    hash->key = ngx_hash_key_lc;
+    hash->pool = cf->pool;
+    hash->temp_pool = NULL;
+
+    return ngx_hash_init(hash, hide_headers.elts, hide_headers.nelts);
+}
+
+
 static void *
 ngx_http_upstream_create_main_conf(ngx_conf_t *cf)
 {
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -269,6 +269,9 @@ ngx_int_t ngx_http_upstream_header_varia
 void ngx_http_upstream_init(ngx_http_request_t *r);
 ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf,
     ngx_url_t *u, ngx_uint_t flags);
+ngx_int_t ngx_http_upstream_hide_headers_hash(ngx_conf_t *cf,
+    ngx_http_upstream_conf_t *conf, ngx_http_upstream_conf_t *prev,
+    ngx_str_t *default_hide_headers, ngx_hash_init_t *hash);
 
 
 #define ngx_http_conf_upstream_srv_conf(uscf, module)                         \
--- a/src/mail/ngx_mail_handler.c
+++ b/src/mail/ngx_mail_handler.c
@@ -29,10 +29,6 @@ ngx_mail_init_connection(ngx_connection_
     ngx_mail_in_port_t   *imip;
     ngx_mail_in_addr_t   *imia;
     ngx_mail_session_t   *s;
-#if (NGX_MAIL_SSL)
-    ngx_mail_ssl_conf_t  *sslcf;
-#endif
-
 
     /* find the server configuration for the address:port */
 
@@ -116,6 +112,8 @@ ngx_mail_init_connection(ngx_connection_
     c->log_error = NGX_ERROR_INFO;
 
 #if (NGX_MAIL_SSL)
+    {
+    ngx_mail_ssl_conf_t  *sslcf;
 
     sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
 
@@ -123,7 +121,7 @@ ngx_mail_init_connection(ngx_connection_
         ngx_mail_ssl_init_connection(&sslcf->ssl, c);
         return;
     }
-
+    }
 #endif
 
     ngx_mail_init_session(c);
--- a/src/mail/ngx_mail_imap_handler.c
+++ b/src/mail/ngx_mail_imap_handler.c
@@ -302,7 +302,7 @@ ngx_mail_imap_auth_state(ngx_event_t *re
 static ngx_int_t
 ngx_mail_imap_login(ngx_mail_session_t *s, ngx_connection_t *c)
 {
-    ngx_str_t            *arg;
+    ngx_str_t  *arg;
 
 #if (NGX_MAIL_SSL)
     if (ngx_mail_starttls_only(s, c)) {
@@ -410,15 +410,14 @@ static ngx_int_t
 ngx_mail_imap_capability(ngx_mail_session_t *s, ngx_connection_t *c)
 {
     ngx_mail_imap_srv_conf_t  *iscf;
-#if (NGX_MAIL_SSL)
-    ngx_mail_ssl_conf_t       *sslcf;
-#endif
 
     iscf = ngx_mail_get_module_srv_conf(s, ngx_mail_imap_module);
 
 #if (NGX_MAIL_SSL)
 
     if (c->ssl == NULL) {
+        ngx_mail_ssl_conf_t  *sslcf;
+
         sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
 
         if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) {
--- a/src/mail/ngx_mail_pop3_handler.c
+++ b/src/mail/ngx_mail_pop3_handler.c
@@ -283,7 +283,7 @@ ngx_mail_pop3_auth_state(ngx_event_t *re
 static ngx_int_t
 ngx_mail_pop3_user(ngx_mail_session_t *s, ngx_connection_t *c)
 {
-    ngx_str_t            *arg;
+    ngx_str_t  *arg;
 
 #if (NGX_MAIL_SSL)
     if (ngx_mail_starttls_only(s, c)) {
@@ -344,15 +344,14 @@ static ngx_int_t
 ngx_mail_pop3_capa(ngx_mail_session_t *s, ngx_connection_t *c, ngx_int_t stls)
 {
     ngx_mail_pop3_srv_conf_t  *pscf;
-#if (NGX_MAIL_SSL)
-    ngx_mail_ssl_conf_t       *sslcf;
-#endif
 
     pscf = ngx_mail_get_module_srv_conf(s, ngx_mail_pop3_module);
 
 #if (NGX_MAIL_SSL)
 
     if (stls && c->ssl == NULL) {
+        ngx_mail_ssl_conf_t  *sslcf;
+
         sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
 
         if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) {
--- a/src/mail/ngx_mail_smtp_handler.c
+++ b/src/mail/ngx_mail_smtp_handler.c
@@ -319,9 +319,6 @@ ngx_mail_smtp_helo(ngx_mail_session_t *s
 {
     ngx_str_t                 *arg;
     ngx_mail_smtp_srv_conf_t  *sscf;
-#if (NGX_MAIL_SSL)
-    ngx_mail_ssl_conf_t       *sslcf;
-#endif
 
     if (s->args.nelts != 1) {
         s->out.len = sizeof(smtp_invalid_argument) - 1;
@@ -352,6 +349,8 @@ ngx_mail_smtp_helo(ngx_mail_session_t *s
 #if (NGX_MAIL_SSL)
 
         if (c->ssl == NULL) {
+            ngx_mail_ssl_conf_t  *sslcf;
+
             sslcf = ngx_mail_get_module_srv_conf(s, ngx_mail_ssl_module);
 
             if (sslcf->starttls == NGX_MAIL_STARTTLS_ON) {
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -687,17 +687,16 @@ ngx_worker_process_cycle(ngx_cycle_t *cy
 {
     ngx_uint_t         i;
     ngx_connection_t  *c;
-#if (NGX_THREADS)
-    ngx_int_t          n;
-    ngx_err_t          err;
-    ngx_core_conf_t   *ccf;
-#endif
 
     ngx_worker_process_init(cycle, 1);
 
     ngx_setproctitle("worker process");
 
 #if (NGX_THREADS)
+    {
+    ngx_int_t         n;
+    ngx_err_t         err;
+    ngx_core_conf_t  *ccf;
 
     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
 
@@ -736,7 +735,7 @@ ngx_worker_process_cycle(ngx_cycle_t *cy
             }
         }
     }
-
+    }
 #endif
 
     for ( ;; ) {