changeset 480:549994537f15 NGINX_0_7_52

nginx 0.7.52 *) Feature: the first native Windows binary release. *) Bugfix: in processing HEAD method while caching. *) Bugfix: in processing the "If-Modified-Since", "If-Range", etc. client request header lines while caching. *) Bugfix: now the "Set-Cookie" and "P3P" header lines are hidden in cacheable responses. *) Bugfix: if nginx was built with the ngx_http_perl_module and with a perl which supports threads, then during a master process exit the message "panic: MUTEX_LOCK" might be issued. *) Bugfix: nginx could not be built --without-http-cache; the bug had appeared in 0.7.48. *) Bugfix: nginx could not be built on platforms different from i386, amd64, sparc, and ppc; the bug had appeared in 0.7.42.
author Igor Sysoev <http://sysoev.ru>
date Mon, 20 Apr 2009 00:00:00 +0400
parents eb4fdebda673
children 0c98173187ac
files CHANGES CHANGES.ru auto/cc/bcc auto/cc/msvc auto/cc/owc auto/lib/md5/conf auto/lib/openssl/conf auto/lib/openssl/make auto/sources src/core/nginx.c src/core/nginx.h src/core/ngx_connection.c src/core/ngx_cycle.c src/core/ngx_cycle.h src/core/ngx_log.c src/core/ngx_log.h src/core/ngx_slab.c src/core/ngx_slab.h src/event/ngx_event.c src/event/ngx_event_accept.c src/event/ngx_event_openssl.c src/http/modules/ngx_http_autoindex_module.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_gzip_static_module.c src/http/modules/ngx_http_index_module.c src/http/modules/ngx_http_limit_req_module.c src/http/modules/ngx_http_limit_zone_module.c src/http/modules/ngx_http_not_modified_filter_module.c src/http/modules/ngx_http_proxy_module.c src/http/modules/ngx_http_random_index_module.c src/http/modules/ngx_http_ssl_module.c src/http/modules/ngx_http_static_module.c src/http/modules/perl/nginx.pm src/http/modules/perl/ngx_http_perl_module.c src/http/ngx_http_cache.h src/http/ngx_http_config.h src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_file_cache.c src/http/ngx_http_header_filter_module.c src/http/ngx_http_upstream.c src/os/unix/ngx_send.c src/os/unix/ngx_shmem.h
diffstat 45 files changed, 598 insertions(+), 337 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,27 @@
 
+Changes with nginx 0.7.52                                        20 Apr 2009
+
+    *) Feature: the first native Windows binary release.
+
+    *) Bugfix: in processing HEAD method while caching.
+
+    *) Bugfix: in processing the "If-Modified-Since", "If-Range", etc. 
+       client request header lines while caching.
+
+    *) Bugfix: now the "Set-Cookie" and "P3P" header lines are hidden in 
+       cacheable responses.
+
+    *) Bugfix: if nginx was built with the ngx_http_perl_module and with a 
+       perl which supports threads, then during a master process exit the 
+       message "panic: MUTEX_LOCK" might be issued.
+
+    *) Bugfix: nginx could not be built --without-http-cache; the bug had 
+       appeared in 0.7.48.
+
+    *) Bugfix: nginx could not be built on platforms different from i386, 
+       amd64, sparc, and ppc; the bug had appeared in 0.7.42.
+
+
 Changes with nginx 0.7.51                                        12 Apr 2009
 
     *) Feature: the "try_files" directive supports a response code in the 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,27 @@
 
+Изменения в nginx 0.7.52                                          20.04.2009
+
+    *) Добавление: первая бинарная версия под Windows.
+
+    *) Исправление: корректная обработка метода HEAD при кэшировании.
+
+    *) Исправление: корректная обработка строк "If-Modified-Since", 
+       "If-Range" и им подобных в заголовке запроса клиента при кэшировании.
+
+    *) Исправление: теперь строки "Set-Cookie" и "P3P" скрываются в 
+       заголовке ответа для закэшированных ответов.
+
+    *) Исправление: если nginx был собран с модулем ngx_http_perl_module и 
+       perl поддерживал потоки, то при выходе основного процесса могла 
+       выдаваться ошибка "panic: MUTEX_LOCK".
+
+    *) Исправление: nginx не собирался с параметром --without-http-cache; 
+       ошибка появилась в 0.7.48.
+
+    *) Исправление: nginx не собирался на платформах, отличных от i386, 
+       amd64, sparc и ppc; ошибка появилась в 0.7.42.
+
+
 Изменения в nginx 0.7.51                                          12.04.2009
 
     *) Добавление: директива try_files поддерживает код ответа в последнем 
--- a/auto/cc/bcc
+++ b/auto/cc/bcc
@@ -24,7 +24,7 @@ esac
 # __stdcall
 #CPU_OPT="$CPU_OPT -ps"
 # __fastcall
-CPU_OPT="$CPU_OPT -pr"
+#CPU_OPT="$CPU_OPT -pr"
 
 CFLAGS="$CFLAGS $CPU_OPT"
 
@@ -46,7 +46,7 @@ NGX_USE_PCH="-Hu -H=$NGX_OBJS/ngx_config
 
 
 # Win32 GUI mode application
-LINK="\$(CC) -laa"
+#LINK="\$(CC) -laa"
 
 
 # the resource file
--- a/auto/cc/msvc
+++ b/auto/cc/msvc
@@ -51,12 +51,12 @@ case $CPU in
     ;;
 esac
 
-# __cdecl, use with OpenSSL, md5 asm, and sha1 asm
+# __cdecl, default, must be used with OpenSSL, md5 asm, and sha1 asm
 #CPU_OPT="$CPU_OPT -Gd"
 # __stdcall
 #CPU_OPT="$CPU_OPT -Gz"
 # __fastcall
-CPU_OPT="$CPU_OPT -Gr"
+#CPU_OPT="$CPU_OPT -Gr"
 
 
 CFLAGS="$CFLAGS $CPU_OPT"
@@ -86,17 +86,26 @@ LIBC="-MT"
 
 CFLAGS="$CFLAGS $LIBC"
 
+CORE_LIBS="$CORE_LIBS kernel32.lib user32.lib"
+
 # Win32 GUI mode application
-CORE_LIBS="$CORE_LIBS kernel32.lib user32.lib"
-CORE_LINK="$CORE_LINK -subsystem:windows -entry:mainCRTStartup"
+#CORE_LINK="$CORE_LINK -subsystem:windows -entry:mainCRTStartup"
 
 # debug
+# msvc8 under Wine issues
+#     Program database manager mismatch; please check your installation
 if [ $NGX_CC_NAME != msvc8 ]; then
    CFLAGS="$CFLAGS -Zi"
    CORE_LINK="$CORE_LINK -debug"
 fi
 
 
+# MSVC 2005 supports C99 variadic macros
+if [ $NGX_CC_NAME = msvc8 ]; then
+   have=NGX_HAVE_C99_VARIADIC_MACROS . auto/have
+fi
+
+
 # precompiled headers
 CORE_DEPS="$CORE_DEPS $NGX_OBJS/ngx_config.pch"
 NGX_PCH="$NGX_OBJS/ngx_config.pch"
--- a/auto/cc/owc
+++ b/auto/cc/owc
@@ -71,7 +71,7 @@ NGX_USE_PCH="-fh=$NGX_OBJS/ngx_config.pc
 
 
 # the link flags, built target is NT GUI mode application
-CORE_LINK="$CORE_LINK -l=nt_win"
+#CORE_LINK="$CORE_LINK -l=nt_win"
 
 
 # the resource file
--- a/auto/lib/md5/conf
+++ b/auto/lib/md5/conf
@@ -4,7 +4,7 @@
 
 if [ $MD5 != NONE ]; then
 
-    if grep MD5_Init $MD5/md5.h >/dev/null; then
+    if grep MD5_Init $MD5/md5.h 2>&1 >/dev/null; then
         # OpenSSL md5
         OPENSSL_MD5=YES
         have=NGX_HAVE_OPENSSL_MD5 . auto/have
--- a/auto/lib/openssl/conf
+++ b/auto/lib/openssl/conf
@@ -6,6 +6,21 @@ if [ $OPENSSL != NONE ]; then
     CORE_INCS="$CORE_INCS $OPENSSL/include"
 
     case "$CC" in
+
+        cl|bcc32)
+            have=NGX_OPENSSL . auto/have
+            have=NGX_SSL . auto/have
+
+            LINK_DEPS="$LINK_DEPS $OPENSSL/out32/ssleay32.lib"
+            CORE_LIBS="$CORE_LIBS $OPENSSL/out32/ssleay32.lib"
+
+            LINK_DEPS="$LINK_DEPS $OPENSSL/out32/libeay32.lib"
+            CORE_LIBS="$CORE_LIBS $OPENSSL/out32/libeay32.lib"
+
+            # libeay32.lib requires gdi32.lib and advapi32.lib
+            CORE_LIBS="$CORE_LIBS gdi32.lib advapi32.lib"
+        ;;
+
         *)
             have=NGX_OPENSSL . auto/have
             have=NGX_SSL . auto/have
@@ -34,10 +49,8 @@ else
             CORE_LIBS="$CORE_LIBS c:/openssl/ssleay32.lib"
             CORE_LIBS="$CORE_LIBS c:/openssl/libeay32.lib"
 
-            # libeay32.lib requires gdi32.lib
-            CORE_LIBS="$CORE_LIBS gdi32.lib"
-            # OpenSSL 0.8's libeay32.lib requires advapi32.lib
-            CORE_LIBS="$CORE_LIBS advapi32.lib"
+            # libeay32.lib requires gdi32.lib and advapi32.lib
+            CORE_LIBS="$CORE_LIBS gdi32.lib advapi32.lib"
         ;;
 
         *)
--- a/auto/lib/openssl/make
+++ b/auto/lib/openssl/make
@@ -13,7 +13,38 @@ case $USE_THREADS in
     *)  NGX_OPENSSL_CONFIG="$NGX_OPENSSL_CONFIG threads" ;;
 esac
 
-case "$NGX_PLATFORM" in
+case "$CC" in
+    cl)
+        cat << END                                            >> $NGX_MAKEFILE
+
+$OPENSSL/out32/ssleay32.lib:
+	cd $OPENSSL
+	perl Configure VC-WIN32 no-shared
+	ms\\do_ms
+	\$(MAKE) -f ms\\nt.mak
+	cd ..\\..\\..
+
+END
+
+    ;;
+
+    bcc32)
+        cat << END                                            >> $NGX_MAKEFILE
+
+`echo "$OPENSSL\\out32\\libeay32.lib:	$OPENSSL\\out32\\ssleay32.lib" \
+	| sed -e "s/\//$ngx_regex_dirsep/g"`
+
+`echo "$OPENSSL\\out32\\ssleay32.lib:" | sed -e "s/\//$ngx_regex_dirsep/g"`
+	cd `echo "$OPENSSL" | sed -e "s/\//$ngx_regex_dirsep/g"`
+	perl Configure BC-32 no-shared
+	ms\\do_nasm
+	\$(MAKE) -f ms\\bcb.mak
+	cd ..\\..\\..
+
+END
+
+    ;;
+
     *)
         cat << END                                            >> $NGX_MAKEFILE
 
--- a/auto/sources
+++ b/auto/sources
@@ -215,8 +215,6 @@ WIN32_DEPS="$CORE_DEPS $EVENT_DEPS \
             src/os/win32/ngx_socket.h \
             src/os/win32/ngx_os.h \
             src/os/win32/ngx_user.h \
-            src/os/win32/ngx_gui.h \
-            src/os/win32/ngx_gui_resources.h \
             src/os/win32/ngx_process_cycle.h"
 
 WIN32_CONFIG=src/os/win32/ngx_win32_config.h
@@ -233,14 +231,15 @@ WIN32_SRCS="$CORE_SRCS $EVENT_SRCS \
             src/os/win32/ngx_wsarecv.c \
             src/os/win32/ngx_wsarecv_chain.c \
             src/os/win32/ngx_udp_wsarecv.c \
+            src/os/win32/ngx_wsasend.c \
             src/os/win32/ngx_wsasend_chain.c \
             src/os/win32/ngx_win32_init.c \
             src/os/win32/ngx_user.c \
-            src/os/win32/ngx_gui.c \
+            src/os/win32/ngx_event_log.c \
             src/os/win32/ngx_process_cycle.c \
             src/event/ngx_event_acceptex.c"
 
-NGX_WIN32_ICONS="src/os/win32/nginx.ico src/os/win32/nginx_tray.ico"
+NGX_WIN32_ICONS="src/os/win32/nginx.ico"
 NGX_WIN32_RC="src/os/win32/nginx.rc"
 
 
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -180,10 +180,14 @@ ngx_module_t  ngx_core_module = {
 };
 
 
-ngx_uint_t  ngx_max_module;
+ngx_uint_t          ngx_max_module;
 
-static ngx_uint_t  ngx_show_version;
-static ngx_uint_t  ngx_show_configure;
+static ngx_uint_t   ngx_show_version;
+static ngx_uint_t   ngx_show_configure;
+#if (NGX_WIN32)
+static char        *ngx_signal;
+#endif
+
 
 static char **ngx_os_environ;
 
@@ -191,8 +195,6 @@ static char **ngx_os_environ;
 int ngx_cdecl
 main(int argc, char *const *argv)
 {
-    char             *p;
-    ssize_t           n;
     ngx_int_t         i;
     ngx_log_t        *log;
     ngx_cycle_t      *cycle, init_cycle;
@@ -243,29 +245,14 @@ main(int argc, char *const *argv)
 
     if (ngx_show_version) {
 
-        p = "nginx version: " NGINX_VER CRLF;
-        n = sizeof("nginx version: " NGINX_VER CRLF) - 1;
-
-        if (ngx_write_fd(ngx_stderr_fileno, p, n) != n) {
-            return 1;
-        }
+        ngx_log_stderr("nginx version: " NGINX_VER);
 
         if (ngx_show_configure) {
 #ifdef NGX_COMPILER
-            p = "built by " NGX_COMPILER CRLF;
-            n = sizeof("built by " NGX_COMPILER CRLF) - 1;
-
-            if (ngx_write_fd(ngx_stderr_fileno, p, n) != n) {
-                return 1;
-            }
+            ngx_log_stderr("built by " NGX_COMPILER);
 #endif
 
-            p = "configure arguments: " NGX_CONFIGURE CRLF;
-            n = sizeof("configure arguments :" NGX_CONFIGURE CRLF) - 1;
-
-            if (ngx_write_fd(ngx_stderr_fileno, p, n) != n) {
-                return 1;
-            }
+            ngx_log_stderr("configure arguments: " NGX_CONFIGURE);
         }
 
         if (!ngx_test_config) {
@@ -301,18 +288,16 @@ main(int argc, char *const *argv)
     cycle = ngx_init_cycle(&init_cycle);
     if (cycle == NULL) {
         if (ngx_test_config) {
-            ngx_log_error(NGX_LOG_EMERG, log, 0,
-                          "the configuration file %s test failed",
-                          init_cycle.conf_file.data);
+            ngx_log_stderr("the configuration file %s test failed",
+                           init_cycle.conf_file.data);
         }
 
         return 1;
     }
 
     if (ngx_test_config) {
-        ngx_log_error(NGX_LOG_INFO, log, 0,
-                      "the configuration file %s was tested successfully",
-                      cycle->conf_file.data);
+        ngx_log_stderr("the configuration file %s was tested successfully",
+                       cycle->conf_file.data);
         return 0;
     }
 
@@ -322,22 +307,15 @@ main(int argc, char *const *argv)
 
     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
 
-    ngx_process = ccf->master ? NGX_PROCESS_MASTER : NGX_PROCESS_SINGLE;
+    if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
+        ngx_process = NGX_PROCESS_MASTER;
+    }
 
 #if (NGX_WIN32)
 
-#if 0
-
-    TODO:
-
-    if (ccf->run_as_service) {
-        if (ngx_service(cycle->log) != NGX_OK) {
-            return 1;
-        }
-
-        return 0;
+    if (ngx_signal) {
+        return ngx_signal_process(cycle, ngx_signal);
     }
-#endif
 
 #else
 
@@ -353,17 +331,17 @@ main(int argc, char *const *argv)
         ngx_daemonized = 1;
     }
 
+#endif
+
     if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
         return 1;
     }
 
-#endif
-
-    if (ngx_process == NGX_PROCESS_MASTER) {
-        ngx_master_process_cycle(cycle);
+    if (ngx_process == NGX_PROCESS_SINGLE) {
+        ngx_single_process_cycle(cycle);
 
     } else {
-        ngx_single_process_cycle(cycle);
+        ngx_master_process_cycle(cycle);
     }
 
     return 0;
@@ -664,6 +642,29 @@ ngx_getopt(ngx_cycle_t *cycle, int argc,
             cycle->conf_param.len = ngx_strlen(cycle->conf_param.data);
             break;
 
+#if (NGX_WIN32)
+        case 's':
+            if (argv[++i] == NULL) {
+                ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
+                              "the option \"-s\" requires parameter");
+                return NGX_ERROR;
+            }
+
+            if (ngx_strcmp(argv[i], "stop") == 0
+                || ngx_strcmp(argv[i], "quit") == 0
+                || ngx_strcmp(argv[i], "reopen") == 0
+                || ngx_strcmp(argv[i], "reload") == 0)
+            {
+                ngx_process = NGX_PROCESS_SIGNALLER;
+                ngx_signal = argv[i];
+                break;
+            }
+
+            ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
+                          "invalid option: \"-s %s\"", argv[i]);
+            return NGX_ERROR;
+#endif
+
         default:
             ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
                           "invalid option: \"%s\"", argv[i]);
@@ -805,6 +806,27 @@ ngx_core_module_init_conf(ngx_cycle_t *c
 
 #endif
 
+
+    if (ccf->pid.len == 0) {
+        ccf->pid.len = sizeof(NGX_PID_PATH) - 1;
+        ccf->pid.data = (u_char *) NGX_PID_PATH;
+    }
+
+    if (ngx_conf_full_name(cycle, &ccf->pid, 0) != NGX_OK) {
+        return NGX_CONF_ERROR;
+    }
+
+    ccf->oldpid.len = ccf->pid.len + sizeof(NGX_OLDPID_EXT);
+
+    ccf->oldpid.data = ngx_pnalloc(cycle->pool, ccf->oldpid.len);
+    if (ccf->oldpid.data == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    ngx_memcpy(ngx_cpymem(ccf->oldpid.data, ccf->pid.data, ccf->pid.len),
+               NGX_OLDPID_EXT, sizeof(NGX_OLDPID_EXT));
+
+
 #if !(NGX_WIN32)
 
     if (ccf->user == (uid_t) NGX_CONF_UNSET_UINT && geteuid() == 0) {
@@ -833,25 +855,6 @@ ngx_core_module_init_conf(ngx_cycle_t *c
         ccf->group = grp->gr_gid;
     }
 
-    if (ccf->pid.len == 0) {
-        ccf->pid.len = sizeof(NGX_PID_PATH) - 1;
-        ccf->pid.data = (u_char *) NGX_PID_PATH;
-    }
-
-    if (ngx_conf_full_name(cycle, &ccf->pid, 0) != NGX_OK) {
-        return NGX_CONF_ERROR;
-    }
-
-    ccf->oldpid.len = ccf->pid.len + sizeof(NGX_OLDPID_EXT);
-
-    ccf->oldpid.data = ngx_pnalloc(cycle->pool, ccf->oldpid.len);
-    if (ccf->oldpid.data == NULL) {
-        return NGX_CONF_ERROR;
-    }
-
-    ngx_memcpy(ngx_cpymem(ccf->oldpid.data, ccf->pid.data, ccf->pid.len),
-               NGX_OLDPID_EXT, sizeof(NGX_OLDPID_EXT));
-
 
     if (ccf->lock_file.len == 0) {
         ccf->lock_file.len = sizeof(NGX_LOCK_PATH) - 1;
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version       007051
-#define NGINX_VERSION      "0.7.51"
+#define nginx_version         7052
+#define NGINX_VERSION      "0.7.52"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -557,29 +557,31 @@ ngx_close_listening_sockets(ngx_cycle_t 
 
         c = ls[i].connection;
 
-        if (c->read->active) {
-            if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
-                ngx_del_conn(c, NGX_CLOSE_EVENT);
+        if (c) {
+            if (c->read->active) {
+                if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {
+                    ngx_del_conn(c, NGX_CLOSE_EVENT);
 
-            } else if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
+                } else if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
 
-                /*
-                 * it seems that Linux-2.6.x OpenVZ sends events
-                 * for closed shared listening sockets unless
-                 * the events was explicity deleted
-                 */
+                    /*
+                     * it seems that Linux-2.6.x OpenVZ sends events
+                     * for closed shared listening sockets unless
+                     * the events was explicity deleted
+                     */
 
-                ngx_del_event(c->read, NGX_READ_EVENT, 0);
+                    ngx_del_event(c->read, NGX_READ_EVENT, 0);
 
-            } else {
-                ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
+                } else {
+                    ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
+                }
             }
+
+            ngx_free_connection(c);
+
+            c->fd = (ngx_socket_t) -1;
         }
 
-        ngx_free_connection(c);
-
-        c->fd = (ngx_socket_t) -1;
-
         ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
                        "close listening %V #%d ", &ls[i].addr_text, ls[i].fd);
 
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -9,9 +9,11 @@
 #include <ngx_event.h>
 
 
-static ngx_int_t ngx_test_lockfile(u_char *file, ngx_log_t *log);
 static void ngx_destroy_cycle_pools(ngx_conf_t *conf);
 static ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, struct sockaddr *sa2);
+static ngx_int_t ngx_init_zone_pool(ngx_cycle_t *cycle,
+    ngx_shm_zone_t *shm_zone);
+static ngx_int_t ngx_test_lockfile(u_char *file, ngx_log_t *log);
 static void ngx_clean_old_cycles(ngx_event_t *ev);
 
 
@@ -44,7 +46,6 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
 {
     void                *rv;
     char               **senv, **env;
-    u_char              *lock_file;
     ngx_uint_t           i, n;
     ngx_log_t           *log;
     ngx_time_t          *tp;
@@ -52,7 +53,6 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
     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;
@@ -270,9 +270,8 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
     }
 
     if (ngx_test_config) {
-        ngx_log_error(NGX_LOG_INFO, log, 0,
-                      "the configuration file %s syntax is ok",
-                      cycle->conf_file.data);
+        ngx_log_stderr("the configuration file %s syntax is ok",
+                       cycle->conf_file.data);
     }
 
 
@@ -296,8 +295,6 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
 
     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
 
-#if !(NGX_WIN32)
-
     if (ngx_test_config) {
 
         if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) {
@@ -326,8 +323,6 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
         }
     }
 
-#endif
-
 
     if (ngx_test_lockfile(cycle->lock_file.data, log) != NGX_OK) {
         goto failed;
@@ -412,7 +407,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
         if (shm_zone[i].shm.size == 0) {
             ngx_log_error(NGX_LOG_EMERG, log, 0,
                           "zero size shared memory zone \"%V\"",
-                          &shm_zone[i].name);
+                          &shm_zone[i].shm.name);
             goto failed;
         }
 
@@ -437,12 +432,13 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
                 n = 0;
             }
 
-            if (shm_zone[i].name.len != oshm_zone[n].name.len) {
+            if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) {
                 continue;
             }
 
-            if (ngx_strncmp(shm_zone[i].name.data, oshm_zone[n].name.data,
-                            shm_zone[i].name.len)
+            if (ngx_strncmp(shm_zone[i].shm.name.data,
+                            oshm_zone[n].shm.name.data,
+                            shm_zone[i].shm.name.len)
                 != 0)
             {
                 continue;
@@ -469,38 +465,13 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
             goto failed;
         }
 
-        shpool = (ngx_slab_pool_t *) shm_zone[i].shm.addr;
-
-        shpool->end = shm_zone[i].shm.addr + shm_zone[i].shm.size;
-        shpool->min_shift = 3;
-
-#if (NGX_HAVE_ATOMIC_OPS)
-
-        lock_file = NULL;
-
-#else
-
-        lock_file = ngx_pnalloc(cycle->pool,
-                                cycle->lock_file.len + shm_zone[i].name.len);
+        if (!shm_zone[i].shm.exists) {
 
-        if (lock_file == NULL) {
-            goto failed;
+	    if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) {
+		goto failed;
+	    }
         }
 
-        (void) ngx_cpystrn(ngx_cpymem(lock_file, cycle->lock_file.data,
-                                      cycle->lock_file.len),
-                           shm_zone[i].name.data, shm_zone[i].name.len + 1);
-
-#endif
-
-        if (ngx_shmtx_create(&shpool->mutex, (void *) &shpool->lock, lock_file)
-            != NGX_OK)
-        {
-            goto failed;
-        }
-
-        ngx_slab_init(shpool);
-
         if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) {
             goto failed;
         }
@@ -672,10 +643,10 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
                 n = 0;
             }
 
-            if (oshm_zone[i].name.len == shm_zone[n].name.len
-                && ngx_strncmp(oshm_zone[i].name.data,
-                               shm_zone[n].name.data,
-                               oshm_zone[i].name.len)
+            if (oshm_zone[i].shm.name.len == shm_zone[n].shm.name.len
+                && ngx_strncmp(oshm_zone[i].shm.name.data,
+                               shm_zone[n].shm.name.data,
+                               oshm_zone[i].shm.name.len)
                 == 0)
             {
                 goto live_shm_zone;
@@ -917,7 +888,41 @@ ngx_cmp_sockaddr(struct sockaddr *sa1, s
 }
 
 
-#if !(NGX_WIN32)
+static ngx_int_t
+ngx_init_zone_pool(ngx_cycle_t *cycle, ngx_shm_zone_t *zn)
+{
+    u_char           *file;
+    ngx_slab_pool_t  *sp;
+
+    sp = (ngx_slab_pool_t *) zn->shm.addr;
+
+    sp->end = zn->shm.addr + zn->shm.size;
+    sp->min_shift = 3;
+
+#if (NGX_HAVE_ATOMIC_OPS)
+
+    file = NULL;
+
+#else
+
+    file = ngx_pnalloc(cycle->pool, cycle->lock_file.len + zn->shm.name.len);
+    if (file == NULL) {
+	return NGX_ERROR;
+    }
+
+    (void) ngx_sprintf(file, "%V%V%Z", &cycle->lock_file, &zn->shm.name);
+
+#endif
+
+    if (ngx_shmtx_create(&sp->mutex, (void *) &sp->lock, file) != NGX_OK) {
+	return NGX_ERROR;
+    }
+
+    ngx_slab_init(sp);
+
+    return NGX_OK;
+}
+
 
 ngx_int_t
 ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log)
@@ -927,6 +932,10 @@ ngx_create_pidfile(ngx_str_t *name, ngx_
     ngx_file_t  file;
     u_char      pid[NGX_INT64_LEN + 2];
 
+    if (ngx_process > NGX_PROCESS_MASTER) {
+        return NGX_OK;
+    }
+
     ngx_memzero(&file, sizeof(ngx_file_t));
 
     file.name = *name;
@@ -976,8 +985,6 @@ ngx_delete_pidfile(ngx_cycle_t *cycle)
     }
 }
 
-#endif
-
 
 static ngx_int_t
 ngx_test_lockfile(u_char *file, ngx_log_t *log)
@@ -1175,27 +1182,29 @@ ngx_shared_memory_add(ngx_conf_t *cf, ng
             i = 0;
         }
 
-        if (name->len != shm_zone[i].name.len) {
+        if (name->len != shm_zone[i].shm.name.len) {
             continue;
         }
 
-        if (ngx_strncmp(name->data, shm_zone[i].name.data, name->len) != 0) {
+        if (ngx_strncmp(name->data, shm_zone[i].shm.name.data, name->len)
+            != 0)
+        {
             continue;
         }
 
         if (size && size != shm_zone[i].shm.size) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "the size %uz of shared memory zone \"%V\" "
-                               "conflicts with already declared size %uz",
-                               size, &shm_zone[i].name, shm_zone[i].shm.size);
+                            "the size %uz of shared memory zone \"%V\" "
+                            "conflicts with already declared size %uz",
+                            size, &shm_zone[i].shm.name, shm_zone[i].shm.size);
             return NULL;
         }
 
         if (tag != shm_zone[i].tag) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "the shared memory zone \"%V\" is "
-                               "already declared for a different use",
-                               &shm_zone[i].name);
+                            "the shared memory zone \"%V\" is "
+                            "already declared for a different use",
+                            &shm_zone[i].shm.name);
             return NULL;
         }
 
@@ -1211,8 +1220,9 @@ ngx_shared_memory_add(ngx_conf_t *cf, ng
     shm_zone->data = NULL;
     shm_zone->shm.log = cf->cycle->log;
     shm_zone->shm.size = size;
+    shm_zone->shm.name = *name;
+    shm_zone->shm.exists = 0;
     shm_zone->init = NULL;
-    shm_zone->name = *name;
     shm_zone->tag = tag;
 
     return shm_zone;
--- a/src/core/ngx_cycle.h
+++ b/src/core/ngx_cycle.h
@@ -29,7 +29,6 @@ struct ngx_shm_zone_s {
     void                     *data;
     ngx_shm_t                 shm;
     ngx_shm_zone_init_pt      init;
-    ngx_str_t                 name;
     void                     *tag;
 };
 
--- a/src/core/ngx_log.c
+++ b/src/core/ngx_log.c
@@ -184,9 +184,30 @@ ngx_log_debug_core(ngx_log_t *log, ngx_e
 
 
 void
-ngx_log_abort(ngx_err_t err, const char *text)
+ngx_log_abort(ngx_err_t err, const char *text, void *param)
+{
+    ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err, text, param);
+}
+
+
+void ngx_cdecl
+ngx_log_stderr(const char *fmt, ...)
 {
-    ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err, text);
+    u_char   *p;
+    va_list   args;
+    u_char    errstr[NGX_MAX_ERROR_STR];
+
+    va_start(args, fmt);
+    p = ngx_vsnprintf(errstr, NGX_MAX_ERROR_STR, fmt, args);
+    va_end(args);
+
+    if (p > errstr + NGX_MAX_ERROR_STR - NGX_LINEFEED_SIZE) {
+        p = errstr + NGX_MAX_ERROR_STR - NGX_LINEFEED_SIZE;
+    }
+
+    ngx_linefeed(p);
+
+    (void) ngx_write_fd(ngx_stderr_fileno, errstr, p - errstr);
 }
 
 
@@ -206,9 +227,9 @@ ngx_log_init(void)
                                   NGX_FILE_DEFAULT_ACCESS);
 
     if (ngx_stderr.fd == NGX_INVALID_FILE) {
-        ngx_message_box("nginx", MB_OK, ngx_errno,
-                        "Could not open error log file: "
-                        ngx_open_file_n " \"" NGX_ERROR_LOG_PATH "\" failed");
+        ngx_event_log(ngx_errno, 
+                      "Could not open error log file: "
+                      ngx_open_file_n " \"" NGX_ERROR_LOG_PATH "\" failed");
         return NULL;
     }
 
--- a/src/core/ngx_log.h
+++ b/src/core/ngx_log.h
@@ -198,7 +198,8 @@ void ngx_cdecl ngx_log_debug_core(ngx_lo
 ngx_log_t *ngx_log_init(void);
 ngx_log_t *ngx_log_create_errlog(ngx_cycle_t *cycle, ngx_array_t *args);
 char *ngx_set_error_log_levels(ngx_conf_t *cf, ngx_log_t *log);
-void ngx_log_abort(ngx_err_t err, const char *text);
+void ngx_log_abort(ngx_err_t err, const char *text, void *param);
+void ngx_cdecl ngx_log_stderr(const char *fmt, ...);
 
 
 extern ngx_module_t  ngx_errlog_module;
--- a/src/core/ngx_slab.c
+++ b/src/core/ngx_slab.c
@@ -584,9 +584,9 @@ ngx_slab_free_locked(ngx_slab_pool_t *po
 
         ngx_slab_free_pages(pool, &pool->pages[n], size);
 
-        size <<= ngx_pagesize_shift;
+        ngx_slab_junk(p, size << ngx_pagesize_shift);
 
-        goto done;
+        return;
     }
 
     /* not reached */
--- a/src/core/ngx_slab.h
+++ b/src/core/ngx_slab.h
@@ -37,6 +37,8 @@ typedef struct {
 
     u_char           *log_ctx;
     u_char            zero;
+
+    void             *data;
 } ngx_slab_pool_t;
 
 
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -442,7 +442,7 @@ ngx_event_module_init(ngx_cycle_t *cycle
 
     ecf = (*cf)[ngx_event_core_module.ctx_index];
 
-    if (!ngx_test_config) {
+    if (!ngx_test_config && ngx_process <= NGX_PROCESS_MASTER) {
         ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
                       "using the \"%s\" event method", ecf->name);
     }
@@ -506,6 +506,8 @@ ngx_event_module_init(ngx_cycle_t *cycle
 #endif
 
     shm.size = size;
+    shm.name.len = sizeof("nginx_shared_zone");
+    shm.name.data = (u_char *) "nginx_shared_zone";
     shm.log = cycle->log;
 
     if (ngx_shm_alloc(&shm) != NGX_OK) {
@@ -535,7 +537,7 @@ ngx_event_module_init(ngx_cycle_t *cycle
 
 #endif
 
-    *ngx_connection_counter = 1;
+    (void) ngx_atomic_cmp_set(ngx_connection_counter, 0, 1);
 
     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    "counter: %p, %d",
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -57,8 +57,8 @@ ngx_event_accept(ngx_event_t *ev)
                 return;
             }
 
-            ngx_log_error((err == NGX_ECONNABORTED) ? NGX_LOG_ERR:
-                                                      NGX_LOG_ALERT,
+            ngx_log_error((ngx_uint_t) ((err == NGX_ECONNABORTED) ?
+                                             NGX_LOG_ERR : NGX_LOG_ALERT),
                           ev->log, err, "accept() failed");
 
             if (err == NGX_ECONNABORTED) {
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -1387,7 +1387,7 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng
         }
     }
 
-    SSL_CTX_set_timeout(ssl->ctx, timeout);
+    SSL_CTX_set_timeout(ssl->ctx, (long) timeout);
 
     if (shm_zone) {
         shm_zone->init = ngx_ssl_session_cache_init;
@@ -1421,6 +1421,11 @@ ngx_ssl_session_cache_init(ngx_shm_zone_
         return NGX_OK;
     }
 
+    if (shm_zone->shm.exists) {
+        shm_zone->data = data;
+        return NGX_OK;
+    }
+
     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
 
     cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_session_cache_t));
@@ -1428,12 +1433,15 @@ ngx_ssl_session_cache_init(ngx_shm_zone_
         return NGX_ERROR;
     }
 
+    shpool->data = cache;
+    shm_zone->data = cache;
+
     ngx_rbtree_init(&cache->session_rbtree, &cache->sentinel,
                     ngx_ssl_session_rbtree_insert_value);
 
     ngx_queue_init(&cache->expire_queue);
 
-    len = sizeof(" in SSL session shared cache \"\"") + shm_zone->name.len;
+    len = sizeof(" in SSL session shared cache \"\"") + shm_zone->shm.name.len;
 
     shpool->log_ctx = ngx_slab_alloc(shpool, len);
     if (shpool->log_ctx == NULL) {
@@ -1441,9 +1449,7 @@ ngx_ssl_session_cache_init(ngx_shm_zone_
     }
 
     ngx_sprintf(shpool->log_ctx, " in SSL session shared cache \"%V\"%Z",
-                &shm_zone->name);
-
-    shm_zone->data = cache;
+                &shm_zone->shm.name);
 
     return NGX_OK;
 }
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -157,7 +157,6 @@ ngx_http_autoindex_handler(ngx_http_requ
         return NGX_DECLINED;
     }
 
-    /* TODO: Win32 */
     if (r->zero_in_uri) {
         return NGX_DECLINED;
     }
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -148,7 +148,6 @@ ngx_http_dav_handler(ngx_http_request_t 
     ngx_int_t                 rc;
     ngx_http_dav_loc_conf_t  *dlcf;
 
-    /* TODO: Win32 */
     if (r->zero_in_uri) {
         return NGX_DECLINED;
     }
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -2043,7 +2043,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf
 
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "\"fastcgi_cache\" zone \"%V\" is unknown",
-                           &shm_zone->name);
+                           &shm_zone->shm.name);
 
         return NGX_CONF_ERROR;
     }
--- a/src/http/modules/ngx_http_flv_module.c
+++ b/src/http/modules/ngx_http_flv_module.c
@@ -80,7 +80,6 @@ ngx_http_flv_handler(ngx_http_request_t 
         return NGX_DECLINED;
     }
 
-    /* TODO: Win32 */
     if (r->zero_in_uri) {
         return NGX_DECLINED;
     }
--- a/src/http/modules/ngx_http_gzip_static_module.c
+++ b/src/http/modules/ngx_http_gzip_static_module.c
@@ -89,7 +89,6 @@ ngx_http_gzip_static_handler(ngx_http_re
         return NGX_DECLINED;
     }
 
-    /* TODO: Win32 */
     if (r->zero_in_uri) {
         return NGX_DECLINED;
     }
--- a/src/http/modules/ngx_http_index_module.c
+++ b/src/http/modules/ngx_http_index_module.c
@@ -116,7 +116,6 @@ ngx_http_index_handler(ngx_http_request_
         return NGX_DECLINED;
     }
 
-    /* TODO: Win32 */
     if (r->zero_in_uri) {
         return NGX_DECLINED;
     }
--- a/src/http/modules/ngx_http_limit_req_module.c
+++ b/src/http/modules/ngx_http_limit_req_module.c
@@ -10,30 +10,39 @@
 
 
 typedef struct {
-    u_char              color;
-    u_char              dummy;
-    u_short             len;
-    ngx_queue_t         queue;
-    ngx_msec_t          last;
-    ngx_uint_t          excess; /* integer value, 1 corresponds to 0.001 r/s */
-    u_char              data[1];
+    u_char                       color;
+    u_char                       dummy;
+    u_short                      len;
+    ngx_queue_t                  queue;
+    ngx_msec_t                   last;
+    /* integer value, 1 corresponds to 0.001 r/s */
+    ngx_uint_t                   excess;
+    u_char                       data[1];
 } ngx_http_limit_req_node_t;
 
 
 typedef struct {
-    ngx_rbtree_t       *rbtree;
-    ngx_queue_t        *queue;
-    ngx_slab_pool_t    *shpool;
-    ngx_uint_t          rate;   /* integer value, 1 corresponds to 0.001 r/s */
-    ngx_int_t           index;
-    ngx_str_t           var;
+    ngx_rbtree_t                  rbtree;
+    ngx_rbtree_node_t             sentinel;
+    ngx_queue_t                   queue;
+} ngx_http_limit_req_shctx_t;
+
+
+typedef struct {
+    ngx_http_limit_req_shctx_t  *sh;
+    ngx_slab_pool_t             *shpool;
+    /* integer value, 1 corresponds to 0.001 r/s */
+    ngx_uint_t                   rate;
+    ngx_int_t                    index;
+    ngx_str_t                    var;
 } ngx_http_limit_req_ctx_t;
 
 
 typedef struct {
-    ngx_shm_zone_t     *shm_zone;
-    ngx_uint_t          burst;  /* integer value, 1 corresponds to 0.001 r/s */
-    ngx_uint_t          nodelay;/* unsigned  nodelay:1 */
+    ngx_shm_zone_t              *shm_zone;
+    /* integer value, 1 corresponds to 0.001 r/s */
+    ngx_uint_t                   burst;
+    ngx_uint_t                   nodelay;/* unsigned  nodelay:1 */
 } ngx_http_limit_req_conf_t;
 
 
@@ -163,7 +172,7 @@ ngx_http_limit_req_handler(ngx_http_requ
     if (lr) {
         ngx_queue_remove(&lr->queue);
 
-        ngx_queue_insert_head(ctx->queue, &lr->queue);
+        ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
 
         excess = lr->excess;
 
@@ -179,7 +188,7 @@ ngx_http_limit_req_handler(ngx_http_requ
 
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                       "limiting requests, excess: %ui.%03ui by zone \"%V\"",
-                      excess / 1000, excess % 1000, &lrcf->shm_zone->name);
+                      excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name);
 
         return NGX_HTTP_SERVICE_UNAVAILABLE;
     }
@@ -193,7 +202,7 @@ ngx_http_limit_req_handler(ngx_http_requ
 
         ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
                       "delaying request, excess: %ui.%03ui, by zone \"%V\"",
-                      excess / 1000, excess % 1000, &lrcf->shm_zone->name);
+                      excess / 1000, excess % 1000, &lrcf->shm_zone->shm.name);
 
         if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
@@ -239,9 +248,9 @@ ngx_http_limit_req_handler(ngx_http_requ
     lr->excess = 0;
     ngx_memcpy(lr->data, vv->data, len);
 
-    ngx_rbtree_insert(ctx->rbtree, node);
+    ngx_rbtree_insert(&ctx->sh->rbtree, node);
 
-    ngx_queue_insert_head(ctx->queue, &lr->queue);
+    ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
 
 done:
 
@@ -324,8 +333,8 @@ ngx_http_limit_req_lookup(ngx_http_limit
 
     ctx = lrcf->shm_zone->data;
 
-    node = ctx->rbtree->root;
-    sentinel = ctx->rbtree->sentinel;
+    node = ctx->sh->rbtree.root;
+    sentinel = ctx->sh->rbtree.sentinel;
 
     while (node != sentinel) {
 
@@ -411,11 +420,11 @@ ngx_http_limit_req_expire(ngx_http_limit
 
     while (n < 3) {
 
-        if (ngx_queue_empty(ctx->queue)) {
+        if (ngx_queue_empty(&ctx->sh->queue)) {
             return;
         }
 
-        q = ngx_queue_last(ctx->queue);
+        q = ngx_queue_last(&ctx->sh->queue);
 
         lr = ngx_queue_data(q, ngx_http_limit_req_node_t, queue);
 
@@ -440,7 +449,7 @@ ngx_http_limit_req_expire(ngx_http_limit
         node = (ngx_rbtree_node_t *)
                    ((u_char *) lr - offsetof(ngx_rbtree_node_t, color));
 
-        ngx_rbtree_delete(ctx->rbtree, node);
+        ngx_rbtree_delete(&ctx->sh->rbtree, node);
 
         ngx_slab_free_locked(ctx->shpool, node);
     }
@@ -453,7 +462,6 @@ ngx_http_limit_req_init_zone(ngx_shm_zon
     ngx_http_limit_req_ctx_t  *octx = data;
 
     size_t                     len;
-    ngx_rbtree_node_t         *sentinel;
     ngx_http_limit_req_ctx_t  *ctx;
 
     ctx = shm_zone->data;
@@ -463,12 +471,11 @@ ngx_http_limit_req_init_zone(ngx_shm_zon
             ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0,
                           "limit_req \"%V\" uses the \"%V\" variable "
                           "while previously it used the \"%V\" variable",
-                          &shm_zone->name, &ctx->var, &octx->var);
+                          &shm_zone->shm.name, &ctx->var, &octx->var);
             return NGX_ERROR;
         }
 
-        ctx->rbtree = octx->rbtree;
-        ctx->queue = octx->queue;
+        ctx->sh = octx->sh;
         ctx->shpool = octx->shpool;
 
         return NGX_OK;
@@ -476,27 +483,25 @@ ngx_http_limit_req_init_zone(ngx_shm_zon
 
     ctx->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
 
-    ctx->rbtree = ngx_slab_alloc(ctx->shpool, sizeof(ngx_rbtree_t));
-    if (ctx->rbtree == NULL) {
-        return NGX_ERROR;
+    if (shm_zone->shm.exists) {
+        ctx->sh = ctx->shpool->data;
+
+        return NGX_OK;
     }
 
-    sentinel = ngx_slab_alloc(ctx->shpool, sizeof(ngx_rbtree_node_t));
-    if (sentinel == NULL) {
+    ctx->sh = ngx_slab_alloc(ctx->shpool, sizeof(ngx_http_limit_req_shctx_t));
+    if (ctx->sh == NULL) {
         return NGX_ERROR;
     }
 
-    ngx_rbtree_init(ctx->rbtree, sentinel,
+    ctx->shpool->data = ctx->sh;
+
+    ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel,
                     ngx_http_limit_req_rbtree_insert_value);
 
-    ctx->queue = ngx_slab_alloc(ctx->shpool, sizeof(ngx_queue_t));
-    if (ctx->queue == NULL) {
-        return NGX_ERROR;
-    }
+    ngx_queue_init(&ctx->sh->queue);
 
-    ngx_queue_init(ctx->queue);
-
-    len = sizeof(" in limit_req zone \"\"") + shm_zone->name.len;
+    len = sizeof(" in limit_req zone \"\"") + shm_zone->shm.name.len;
 
     ctx->shpool->log_ctx = ngx_slab_alloc(ctx->shpool, len);
     if (ctx->shpool->log_ctx == NULL) {
@@ -504,7 +509,7 @@ ngx_http_limit_req_init_zone(ngx_shm_zon
     }
 
     ngx_sprintf(ctx->shpool->log_ctx, " in limit_req zone \"%V\"%Z",
-                &shm_zone->name);
+                &shm_zone->shm.name);
 
     return NGX_OK;
 }
@@ -574,6 +579,8 @@ ngx_http_limit_req_zone(ngx_conf_t *cf, 
             p = (u_char *) ngx_strchr(name.data, ':');
 
             if (p) {
+                *p = '\0';
+
                 name.len = p - name.data;
 
                 p++;
@@ -744,7 +751,7 @@ ngx_http_limit_req(ngx_conf_t *cf, ngx_c
     if (lrcf->shm_zone->data == NULL) {
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "unknown limit_req_zone \"%V\"",
-                           &lrcf->shm_zone->name);
+                           &lrcf->shm_zone->shm.name);
         return NGX_CONF_ERROR;
     }
 
--- a/src/http/modules/ngx_http_limit_zone_module.c
+++ b/src/http/modules/ngx_http_limit_zone_module.c
@@ -191,7 +191,7 @@ ngx_http_limit_zone_handler(ngx_http_req
 
                 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                               "limiting connections by zone \"%V\"",
-                              &lzcf->shm_zone->name);
+                              &lzcf->shm_zone->shm.name);
 
                 return NGX_HTTP_SERVICE_UNAVAILABLE;
             }
@@ -328,7 +328,7 @@ ngx_http_limit_zone_init_zone(ngx_shm_zo
             ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0,
                           "limit_zone \"%V\" uses the \"%V\" variable "
                           "while previously it used the \"%V\" variable",
-                          &shm_zone->name, &ctx->var, &octx->var);
+                          &shm_zone->shm.name, &ctx->var, &octx->var);
             return NGX_ERROR;
         }
 
@@ -339,11 +339,19 @@ ngx_http_limit_zone_init_zone(ngx_shm_zo
 
     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
 
+    if (shm_zone->shm.exists) {
+        ctx->rbtree = shpool->data;
+
+        return NGX_OK;
+    }
+
     ctx->rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t));
     if (ctx->rbtree == NULL) {
         return NGX_ERROR;
     }
 
+    shpool->data = ctx->rbtree;
+
     sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t));
     if (sentinel == NULL) {
         return NGX_ERROR;
@@ -352,14 +360,15 @@ ngx_http_limit_zone_init_zone(ngx_shm_zo
     ngx_rbtree_init(ctx->rbtree, sentinel,
                     ngx_http_limit_zone_rbtree_insert_value);
 
-    len = sizeof(" in limit_zone \"\"") + shm_zone->name.len;
+    len = sizeof(" in limit_zone \"\"") + shm_zone->shm.name.len;
 
     shpool->log_ctx = ngx_slab_alloc(shpool, len);
     if (shpool->log_ctx == NULL) {
         return NGX_ERROR;
     }
 
-    ngx_sprintf(shpool->log_ctx, " in limit_zone \"%V\"%Z", &shm_zone->name);
+    ngx_sprintf(shpool->log_ctx, " in limit_zone \"%V\"%Z",
+                &shm_zone->shm.name);
 
     return NGX_OK;
 }
--- a/src/http/modules/ngx_http_not_modified_filter_module.c
+++ b/src/http/modules/ngx_http_not_modified_filter_module.c
@@ -47,8 +47,8 @@ ngx_module_t  ngx_http_not_modified_filt
 static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
 
 
-static
-ngx_int_t ngx_http_not_modified_header_filter(ngx_http_request_t *r)
+static ngx_int_t
+ngx_http_not_modified_header_filter(ngx_http_request_t *r)
 {
     time_t                     ims;
     ngx_http_core_loc_conf_t  *clcf;
@@ -92,8 +92,8 @@ ngx_int_t ngx_http_not_modified_header_f
 }
 
 
-static
-ngx_int_t ngx_http_not_modified_filter_init(ngx_conf_t *cf)
+static ngx_int_t
+ngx_http_not_modified_filter_init(ngx_conf_t *cf)
 {
     ngx_http_next_header_filter = ngx_http_top_header_filter;
     ngx_http_top_header_filter = ngx_http_not_modified_header_filter;
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -497,6 +497,40 @@ static ngx_str_t  ngx_http_proxy_hide_he
 };
 
 
+#if (NGX_HTTP_CACHE)
+
+static ngx_keyval_t  ngx_http_proxy_cache_headers[] = {
+    { ngx_string("Host"), ngx_string("$proxy_host") },
+    { ngx_string("Connection"), ngx_string("close") },
+    { ngx_string("Keep-Alive"), ngx_string("") },
+    { ngx_string("Expect"), ngx_string("") },
+    { ngx_string("If-Modified-Since"), ngx_string("") },
+    { ngx_string("If-Unmodified-Since"), ngx_string("") },
+    { ngx_string("If-Match-None"), ngx_string("") },
+    { ngx_string("If-Match"), ngx_string("") },
+    { ngx_string("Range"), ngx_string("") },
+    { ngx_string("If-Range"), ngx_string("") },
+    { ngx_null_string, ngx_null_string }
+};
+
+
+static ngx_str_t  ngx_http_proxy_hide_cache_headers[] = {
+    ngx_string("Date"),
+    ngx_string("Server"),
+    ngx_string("X-Pad"),
+    ngx_string("X-Accel-Expires"),
+    ngx_string("X-Accel-Redirect"),
+    ngx_string("X-Accel-Limit-Rate"),
+    ngx_string("X-Accel-Buffering"),
+    ngx_string("X-Accel-Charset"),
+    ngx_string("Set-Cookie"),
+    ngx_string("P3P"),
+    ngx_null_string
+};
+
+#endif
+
+
 static ngx_http_variable_t  ngx_http_proxy_vars[] = {
 
     { ngx_string("proxy_host"), NULL, ngx_http_proxy_host_variable, 0,
@@ -1906,6 +1940,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t
     ngx_http_proxy_loc_conf_t *conf = child;
 
     size_t                      size;
+    ngx_str_t                  *h;
     ngx_keyval_t               *s;
     ngx_hash_init_t             hash;
     ngx_http_proxy_redirect_t  *pr;
@@ -2069,7 +2104,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t
 
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "\"proxy_cache\" zone \"%V\" is unknown",
-                           &shm_zone->name);
+                           &shm_zone->shm.name);
 
         return NGX_CONF_ERROR;
     }
@@ -2170,9 +2205,18 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t
     hash.bucket_size = conf->headers_hash_bucket_size;
     hash.name = "proxy_headers_hash";
 
+#if (NGX_HTTP_CACHE)
+
+    h = conf->upstream.cache ? ngx_http_proxy_hide_cache_headers:
+                               ngx_http_proxy_hide_headers;
+#else
+
+    h = ngx_http_proxy_hide_headers;
+
+#endif
+
     if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
-                                            &prev->upstream,
-                                            ngx_http_proxy_hide_headers, &hash)
+                                            &prev->upstream, h, &hash)
         != NGX_OK)
     {
         return NGX_CONF_ERROR;
@@ -2286,7 +2330,17 @@ ngx_http_proxy_merge_headers(ngx_conf_t 
 
     src = conf->headers_source->elts;
 
-    for (h = ngx_http_proxy_headers; h->key.len; h++) {
+#if (NGX_HTTP_CACHE)
+
+    h = conf->upstream.cache ? ngx_http_proxy_cache_headers:
+                               ngx_http_proxy_headers;
+#else
+
+    h = ngx_http_proxy_headers;
+
+#endif
+
+    while (h->key.len) {
 
         for (i = 0; i < conf->headers_source->nelts; i++) {
             if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
@@ -2305,7 +2359,7 @@ ngx_http_proxy_merge_headers(ngx_conf_t 
 
     next:
 
-        continue;
+        h++;
     }
 
 
--- a/src/http/modules/ngx_http_random_index_module.c
+++ b/src/http/modules/ngx_http_random_index_module.c
@@ -86,7 +86,6 @@ ngx_http_random_index_handler(ngx_http_r
         return NGX_DECLINED;
     }
 
-    /* TODO: Win32 */
     if (r->zero_in_uri) {
         return NGX_DECLINED;
     }
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -320,8 +320,8 @@ ngx_http_ssl_create_srv_conf(ngx_conf_t 
 
     sscf->enable = NGX_CONF_UNSET;
     sscf->prefer_server_ciphers = NGX_CONF_UNSET;
-    sscf->verify = NGX_CONF_UNSET;
-    sscf->verify_depth = NGX_CONF_UNSET;
+    sscf->verify = NGX_CONF_UNSET_UINT;
+    sscf->verify_depth = NGX_CONF_UNSET_UINT;
     sscf->builtin_session_cache = NGX_CONF_UNSET;
     sscf->session_timeout = NGX_CONF_UNSET;
 
@@ -564,6 +564,7 @@ ngx_http_ssl_session_cache(ngx_conf_t *c
 
             for (j = sizeof("shared:") - 1; j < value[i].len; j++) {
                 if (value[i].data[j] == ':') {
+                    value[i].data[j] = '\0';
                     break;
                 }
 
--- a/src/http/modules/ngx_http_static_module.c
+++ b/src/http/modules/ngx_http_static_module.c
@@ -66,7 +66,6 @@ ngx_http_static_handler(ngx_http_request
         return NGX_DECLINED;
     }
 
-    /* TODO: Win32 */
     if (r->zero_in_uri) {
         return NGX_DECLINED;
     }
--- 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.7.51';
+our $VERSION = '0.7.52';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -154,10 +154,14 @@ static ngx_http_ssi_command_t  ngx_http_
 #endif
 
 
-static ngx_str_t  ngx_null_name = ngx_null_string;
+static ngx_str_t    ngx_null_name = ngx_null_string;
+
+static HV          *nginx_stash;
 
+#if (NGX_HAVE_PERL_MULTIPLICITY)
+static ngx_uint_t   ngx_perl_term;
+#endif
 
-static HV  *nginx_stash;
 
 static void
 ngx_http_perl_xs_init(pTHX)
@@ -171,7 +175,6 @@ ngx_http_perl_xs_init(pTHX)
 static ngx_int_t
 ngx_http_perl_handler(ngx_http_request_t *r)
 {
-    /* TODO: Win32 */
     if (r->zero_in_uri) {
         return NGX_HTTP_NOT_FOUND;
     }
@@ -821,6 +824,12 @@ ngx_http_perl_cleanup_perl(void *data)
     (void) perl_destruct(perl);
 
     perl_free(perl);
+
+    if (ngx_perl_term) {
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "perl term");
+
+        PERL_SYS_TERM();
+    }
 }
 
 #endif
@@ -1041,15 +1050,13 @@ ngx_http_perl_init_worker(ngx_cycle_t *c
 
     pmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_perl_module);
 
-    {
-
-    dTHXa(pmcf->perl);
-    PERL_SET_CONTEXT(pmcf->perl);
+    if (pmcf) {
+        dTHXa(pmcf->perl);
+        PERL_SET_CONTEXT(pmcf->perl);
 
-    /* set worker's $$ */
+        /* set worker's $$ */
 
-    sv_setiv(GvSV(gv_fetchpv("$", TRUE, SVt_PV)), (I32) ngx_pid);
-
+        sv_setiv(GvSV(gv_fetchpv("$", TRUE, SVt_PV)), (I32) ngx_pid);
     }
 
     return NGX_OK;
@@ -1059,16 +1066,24 @@ ngx_http_perl_init_worker(ngx_cycle_t *c
 static void
 ngx_http_perl_exit(ngx_cycle_t *cycle)
 {
+#if (NGX_HAVE_PERL_MULTIPLICITY)
+
+    ngx_perl_term = 1;
+
+#else
     ngx_http_perl_main_conf_t  *pmcf;
 
     pmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_perl_module);
 
-    {
+    if (pmcf && nginx_stash) {
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cycle->log, 0, "perl term");
 
-    dTHXa(pmcf->perl);
-    PERL_SET_CONTEXT(pmcf->perl);
+        (void) perl_destruct(pmcf->perl);
 
-    PERL_SYS_TERM();
+        perl_free(pmcf->perl);
 
+        PERL_SYS_TERM();
     }
+
+#endif
 }
--- a/src/http/ngx_http_cache.h
+++ b/src/http/ngx_http_cache.h
@@ -94,16 +94,21 @@ typedef struct {
 } ngx_http_file_cache_header_t;
 
 
+typedef struct {
+    ngx_rbtree_t                     rbtree;
+    ngx_rbtree_node_t                sentinel;
+    ngx_queue_t                      queue;
+    ngx_atomic_t                     cold;
+    off_t                            size;
+} ngx_http_file_cache_sh_t;
+
+
 struct ngx_http_file_cache_s {
-    ngx_rbtree_t                    *rbtree;
-    ngx_queue_t                     *queue;
+    ngx_http_file_cache_sh_t        *sh;
     ngx_slab_pool_t                 *shpool;
 
     ngx_path_t                      *path;
 
-    ngx_atomic_t                    *cold;
-    off_t                           *size;
-
     off_t                            max_size;
     size_t                           bsize;
 
--- a/src/http/ngx_http_config.h
+++ b/src/http/ngx_http_config.h
@@ -69,8 +69,10 @@ typedef struct {
     ((ngx_http_conf_ctx_t *) cf->ctx)->loc_conf[module.ctx_index]
 
 #define ngx_http_cycle_get_module_main_conf(cycle, module)                    \
-    ((ngx_http_conf_ctx_t *)                                                  \
-         cycle->conf_ctx[ngx_http_module.index])->main_conf[module.ctx_index]
+    (cycle->conf_ctx[ngx_http_module.index] ?                                 \
+        ((ngx_http_conf_ctx_t *) cycle->conf_ctx[ngx_http_module.index])      \
+            ->main_conf[module.ctx_index]:                                    \
+        NULL)
 
 
 #endif /* _NGX_HTTP_CONFIG_H_INCLUDED_ */
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -691,7 +691,7 @@ ngx_module_t  ngx_http_core_module = {
 };
 
 
-static ngx_str_t  ngx_http_core_get_method = { 3, (u_char *) "GET " };
+ngx_str_t  ngx_http_core_get_method = { 3, (u_char *) "GET " };
 
 
 void
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -468,6 +468,8 @@ extern ngx_module_t  ngx_http_core_modul
 
 extern ngx_uint_t ngx_http_max_module;
 
+extern ngx_str_t  ngx_http_core_get_method;
+
 
 #define ngx_http_clear_content_length(r)                                      \
                                                                               \
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -44,7 +44,6 @@ ngx_http_file_cache_init(ngx_shm_zone_t 
     ngx_http_file_cache_t  *ocache = data;
 
     size_t                  len;
-    ngx_rbtree_node_t      *sentinel;
     ngx_http_file_cache_t  *cache;
 
     cache = shm_zone->data;
@@ -54,17 +53,15 @@ ngx_http_file_cache_init(ngx_shm_zone_t 
             ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0,
                           "cache \"%V\" uses the \"%V\" cache path "
                           "while previously it used the \"%V\" cache path",
-                          &shm_zone->name, &cache->path->name,
+                          &shm_zone->shm.name, &cache->path->name,
                           &ocache->path->name);
 
             return NGX_ERROR;
         }
 
-        cache->rbtree = ocache->rbtree;
-        cache->queue = ocache->queue;
+        cache->sh = ocache->sh;
+
         cache->shpool = ocache->shpool;
-        cache->cold = ocache->cold;
-        cache->size = ocache->size;
         cache->bsize = ocache->bsize;
 
         cache->max_size /= cache->bsize;
@@ -74,45 +71,33 @@ ngx_http_file_cache_init(ngx_shm_zone_t 
 
     cache->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
 
-    cache->rbtree = ngx_slab_alloc(cache->shpool, sizeof(ngx_rbtree_t));
-    if (cache->rbtree == NULL) {
-        return NGX_ERROR;
+    if (shm_zone->shm.exists) {
+        cache->sh = cache->shpool->data;
+        cache->bsize = ngx_fs_bsize(cache->path->name.data);
+
+        return NGX_OK;
     }
 
-    sentinel = ngx_slab_alloc(cache->shpool, sizeof(ngx_rbtree_node_t));
-    if (sentinel == NULL) {
+    cache->sh = ngx_slab_alloc(cache->shpool, sizeof(ngx_http_file_cache_sh_t));
+    if (cache->sh == NULL) {
         return NGX_ERROR;
     }
 
-    ngx_rbtree_init(cache->rbtree, sentinel,
+    cache->shpool->data = cache->sh;
+
+    ngx_rbtree_init(&cache->sh->rbtree, &cache->sh->sentinel,
                     ngx_http_file_cache_rbtree_insert_value);
 
-    cache->queue = ngx_slab_alloc(cache->shpool, sizeof(ngx_queue_t));
-    if (cache->queue == NULL) {
-        return NGX_ERROR;
-    }
-
-    ngx_queue_init(cache->queue);
+    ngx_queue_init(&cache->sh->queue);
 
-    cache->cold = ngx_slab_alloc(cache->shpool, sizeof(ngx_atomic_t));
-    if (cache->cold == NULL) {
-        return NGX_ERROR;
-    }
-
-    *cache->cold = 1;
-
-    cache->size = ngx_slab_alloc(cache->shpool, sizeof(off_t));
-    if (cache->size == NULL) {
-        return NGX_ERROR;
-    }
-
-    *cache->size = 0;
+    cache->sh->cold = 1;
+    cache->sh->size = 0;
 
     cache->bsize = ngx_fs_bsize(cache->path->name.data);
 
     cache->max_size /= cache->bsize;
 
-    len = sizeof(" in cache keys zone \"\"") + shm_zone->name.len;
+    len = sizeof(" in cache keys zone \"\"") + shm_zone->shm.name.len;
 
     cache->shpool->log_ctx = ngx_slab_alloc(cache->shpool, len);
     if (cache->shpool->log_ctx == NULL) {
@@ -120,7 +105,7 @@ ngx_http_file_cache_init(ngx_shm_zone_t 
     }
 
     ngx_sprintf(cache->shpool->log_ctx, " in cache keys zone \"%V\"%Z",
-                &shm_zone->name);
+                &shm_zone->shm.name);
 
     return NGX_OK;
 }
@@ -202,7 +187,7 @@ ngx_http_file_cache_open(ngx_http_reques
         return rc;
     }
 
-    cold = *cache->cold;
+    cold = cache->sh->cold;
 
     if (rc == NGX_OK) {
 
@@ -337,7 +322,7 @@ ngx_http_file_cache_open(ngx_http_reques
             c->node->body_start = c->body_start;
             c->node->exists = 1;
 
-            *cache->size += (c->length + cache->bsize - 1) / cache->bsize;
+            cache->sh->size += (c->length + cache->bsize - 1) / cache->bsize;
         }
 
         ngx_shmtx_unlock(&cache->shpool->mutex);
@@ -434,7 +419,7 @@ ngx_http_file_cache_exists(ngx_http_file
     ngx_memcpy(fcn->key, &c->key[sizeof(ngx_rbtree_key_t)],
                NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t));
 
-    ngx_rbtree_insert(cache->rbtree, &fcn->node);
+    ngx_rbtree_insert(&cache->sh->rbtree, &fcn->node);
 
 renew:
 
@@ -454,7 +439,7 @@ done:
 
     fcn->expire = ngx_time() + cache->inactive;
 
-    ngx_queue_insert_head(cache->queue, &fcn->queue);
+    ngx_queue_insert_head(&cache->sh->queue, &fcn->queue);
 
     c->uniq = fcn->uniq;
     c->uses = fcn->uses;
@@ -479,8 +464,8 @@ ngx_http_file_cache_lookup(ngx_http_file
 
     ngx_memcpy((u_char *) &node_key, key, sizeof(ngx_rbtree_key_t));
 
-    node = cache->rbtree->root;
-    sentinel = cache->rbtree->sentinel;
+    node = cache->sh->rbtree.root;
+    sentinel = cache->sh->rbtree.sentinel;
 
     while (node != sentinel) {
 
@@ -663,7 +648,7 @@ ngx_http_file_cache_update(ngx_http_requ
 
     c->node->length = c->length;
 
-    *cache->size += size;
+    cache->sh->size += size;
 
     if (rc == NGX_OK) {
         c->node->exists = 1;
@@ -828,8 +813,8 @@ ngx_http_file_cache_forced_expire(ngx_ht
 
     ngx_shmtx_lock(&cache->shpool->mutex);
 
-    for (q = ngx_queue_last(cache->queue);
-         q != ngx_queue_sentinel(cache->queue);
+    for (q = ngx_queue_last(&cache->sh->queue);
+         q != ngx_queue_sentinel(&cache->sh->queue);
          q = ngx_queue_prev(q))
     {
         fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue);
@@ -853,7 +838,7 @@ ngx_http_file_cache_forced_expire(ngx_ht
         if (!fcn->exists) {
 
             ngx_queue_remove(q);
-            ngx_rbtree_delete(cache->rbtree, &fcn->node);
+            ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
             ngx_slab_free_locked(cache->shpool, fcn);
 
             break;
@@ -902,12 +887,12 @@ ngx_http_file_cache_expire(ngx_http_file
 
     for ( ;; ) {
 
-        if (ngx_queue_empty(cache->queue)) {
+        if (ngx_queue_empty(&cache->sh->queue)) {
             wait = 10;
             break;
         }
 
-        q = ngx_queue_last(cache->queue);
+        q = ngx_queue_last(&cache->sh->queue);
 
         fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue);
 
@@ -939,7 +924,7 @@ ngx_http_file_cache_expire(ngx_http_file
              */
 
             ngx_queue_remove(q);
-            ngx_rbtree_delete(cache->rbtree, &fcn->node);
+            ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
 
             ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
                        "ignore long locked inactive cache entry %*s, count:%d",
@@ -951,7 +936,7 @@ ngx_http_file_cache_expire(ngx_http_file
         if (!fcn->exists) {
 
             ngx_queue_remove(q);
-            ngx_rbtree_delete(cache->rbtree, &fcn->node);
+            ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
             ngx_slab_free_locked(cache->shpool, fcn);
 
             continue;
@@ -979,7 +964,7 @@ ngx_http_file_cache_delete(ngx_http_file
 
     fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue);
 
-    *cache->size -= (fcn->length + cache->bsize - 1) / cache->bsize;
+    cache->sh->size -= (fcn->length + cache->bsize - 1) / cache->bsize;
 
     path = cache->path;
 
@@ -993,7 +978,7 @@ ngx_http_file_cache_delete(ngx_http_file
 
     ngx_queue_remove(q);
 
-    ngx_rbtree_delete(cache->rbtree, &fcn->node);
+    ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
 
     ngx_slab_free_locked(cache->shpool, fcn);
 
@@ -1024,7 +1009,7 @@ ngx_http_file_cache_manager(void *data)
     time_t          next;
     ngx_tree_ctx_t  tree;
 
-    if (*cache->cold) {
+    if (cache->sh->cold) {
 
         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
                        "http file cache manager update");
@@ -1045,12 +1030,12 @@ ngx_http_file_cache_manager(void *data)
             return 10;
         }
 
-        *cache->cold = 0;
+        cache->sh->cold = 0;
 
         ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
                       "http file cache: %V %.3fM, bsize: %uz",
                       &cache->path->name,
-                      ((double) *cache->size * cache->bsize) / (1024 * 1024),
+                      ((double) cache->sh->size * cache->bsize) / (1024 * 1024),
                       cache->bsize);
     }
 
@@ -1062,7 +1047,7 @@ ngx_http_file_cache_manager(void *data)
     for ( ;; ) {
         ngx_shmtx_lock(&cache->shpool->mutex);
 
-        size = *cache->size;
+        size = cache->sh->size;
 
         ngx_shmtx_unlock(&cache->shpool->mutex);
 
@@ -1245,7 +1230,7 @@ ngx_http_file_cache_add(ngx_http_file_ca
         ngx_memcpy(fcn->key, &c->key[sizeof(ngx_rbtree_key_t)],
                    NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t));
 
-        ngx_rbtree_insert(cache->rbtree, &fcn->node);
+        ngx_rbtree_insert(&cache->sh->rbtree, &fcn->node);
 
         fcn->uses = 1;
         fcn->count = 0;
@@ -1257,7 +1242,7 @@ ngx_http_file_cache_add(ngx_http_file_ca
         fcn->body_start = c->body_start;
         fcn->length = c->length;
 
-        *cache->size += (c->length + cache->bsize - 1) / cache->bsize;
+        cache->sh->size += (c->length + cache->bsize - 1) / cache->bsize;
 
     } else {
         ngx_queue_remove(&fcn->queue);
@@ -1265,7 +1250,7 @@ ngx_http_file_cache_add(ngx_http_file_ca
 
     fcn->expire = ngx_time() + cache->inactive;
 
-    ngx_queue_insert_head(cache->queue, &fcn->queue);
+    ngx_queue_insert_head(&cache->sh->queue, &fcn->queue);
 
     ngx_shmtx_unlock(&cache->shpool->mutex);
 
@@ -1399,6 +1384,8 @@ ngx_http_file_cache_set_slot(ngx_conf_t 
             p = (u_char *) ngx_strchr(name.data, ':');
 
             if (p) {
+                *p = '\0';
+
                 name.len = p - name.data;
 
                 p++;
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -247,7 +247,7 @@ ngx_http_header_filter(ngx_http_request_
             len += ngx_http_status_lines[status].len;
 
         } else if (status >= NGX_HTTP_BAD_REQUEST
-                   && status < NGX_HTTP_LAST_LEVEL_400) 
+                   && status < NGX_HTTP_LAST_LEVEL_400)
         {
             /* 4XX */
             status = status - NGX_HTTP_BAD_REQUEST
@@ -586,7 +586,7 @@ ngx_http_header_filter(ngx_http_request_
     }
 
     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "%*s\n", (size_t) (b->last - b->pos), b->pos);
+                   "%*s", (size_t) (b->last - b->pos), b->pos);
 
     /* the end of HTTP header */
     *b->last++ = CR; *b->last++ = LF;
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -532,10 +532,14 @@ ngx_http_upstream_cache(ngx_http_request
     ngx_int_t          rc;
     ngx_http_cache_t  *c;
 
-    if (!(r->method & NGX_HTTP_GET)) {
+    if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
         return NGX_DECLINED;
     }
 
+    if (r->method & NGX_HTTP_HEAD) {
+        u->method = ngx_http_core_get_method;
+    }
+
     c = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t));
     if (c == NULL) {
         return NGX_ERROR;
@@ -1821,11 +1825,32 @@ ngx_http_upstream_send_response(ngx_http
 
     rc = ngx_http_send_header(r);
 
-    if (rc == NGX_ERROR || rc > NGX_OK || r->post_action || r->header_only) {
+    if (rc == NGX_ERROR || rc > NGX_OK || r->post_action) {
         ngx_http_upstream_finalize_request(r, u, rc);
         return;
     }
 
+    c = r->connection;
+
+    if (r->header_only) {
+
+        if (u->cacheable || u->store) {
+
+            if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
+                ngx_connection_error(c, ngx_socket_errno,
+                                     ngx_shutdown_socket_n " failed");
+            }
+
+            r->read_event_handler = ngx_http_request_empty_handler;
+            r->write_event_handler = ngx_http_request_empty_handler;
+            c->error = 1;
+
+        } else {
+            ngx_http_upstream_finalize_request(r, u, rc);
+            return;
+        }
+    }
+
     u->header_sent = 1;
 
     if (r->request_body && r->request_body->temp_file) {
@@ -1833,8 +1858,6 @@ ngx_http_upstream_send_response(ngx_http
         r->request_body->temp_file->file.fd = NGX_INVALID_FILE;
     }
 
-    c = r->connection;
-
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
     if (!u->buffering) {
@@ -1942,6 +1965,7 @@ ngx_http_upstream_send_response(ngx_http
 
         } else {
             u->cacheable = 0;
+            r->headers_out.last_modified_time = -1;
         }
     }
 
@@ -2819,8 +2843,6 @@ static ngx_int_t
 ngx_http_upstream_process_cache_control(ngx_http_request_t *r,
     ngx_table_elt_t *h, ngx_uint_t offset)
 {
-    u_char            *p, *last;
-    ngx_int_t          n;
     ngx_array_t       *pa;
     ngx_table_elt_t  **ph;
 
@@ -2840,6 +2862,11 @@ ngx_http_upstream_process_cache_control(
 
     *ph = h;
 
+#if (NGX_HTTP_CACHE)
+    {
+    u_char     *p, *last;
+    ngx_int_t   n;
+
     if (r->cache == NULL) {
         return NGX_OK;
     }
@@ -2885,6 +2912,9 @@ ngx_http_upstream_process_cache_control(
     }
 
     r->cache->valid_sec = ngx_time() + n;
+    }
+#endif
+
     return NGX_OK;
 }
 
@@ -2893,10 +2923,12 @@ static ngx_int_t
 ngx_http_upstream_process_expires(ngx_http_request_t *r, ngx_table_elt_t *h,
     ngx_uint_t offset)
 {
+    r->upstream->headers_in.expires = h;
+
+#if (NGX_HTTP_CACHE)
+    {
     time_t  expires;
 
-    r->upstream->headers_in.expires = h;
-
     if (r->cache == NULL) {
         return NGX_OK;
     }
@@ -2913,6 +2945,8 @@ ngx_http_upstream_process_expires(ngx_ht
     }
 
     r->cache->valid_sec = expires;
+    }
+#endif
 
     return NGX_OK;
 }
@@ -2922,12 +2956,14 @@ static ngx_int_t
 ngx_http_upstream_process_accel_expires(ngx_http_request_t *r,
     ngx_table_elt_t *h, ngx_uint_t offset)
 {
+    r->upstream->headers_in.x_accel_expires = h;
+
+#if (NGX_HTTP_CACHE)
+    {
     u_char     *p;
     size_t      len;
     ngx_int_t   n;
 
-    r->upstream->headers_in.x_accel_expires = h;
-
     if (r->cache == NULL) {
         return NGX_OK;
     }
@@ -2958,6 +2994,8 @@ ngx_http_upstream_process_accel_expires(
     if (n != NGX_ERROR) {
         r->cache->valid_sec = n;
     }
+    }
+#endif
 
     return NGX_OK;
 }
@@ -3163,7 +3201,7 @@ ngx_http_upstream_copy_last_modified(ngx
 
 #if (NGX_HTTP_CACHE)
 
-    if (r->cached) {
+    if (r->cached || r->upstream->cacheable) {
         r->headers_out.last_modified = ho;
         r->headers_out.last_modified_time = ngx_http_parse_time(h->value.data,
                                                                 h->value.len);
--- a/src/os/unix/ngx_send.c
+++ b/src/os/unix/ngx_send.c
@@ -40,6 +40,8 @@ ngx_unix_send(ngx_connection_t *c, u_cha
                 wev->ready = 0;
             }
 
+            c->sent += n;
+
             return n;
         }
 
--- a/src/os/unix/ngx_shmem.h
+++ b/src/os/unix/ngx_shmem.h
@@ -15,7 +15,9 @@
 typedef struct {
     u_char      *addr;
     size_t       size;
+    ngx_str_t    name;
     ngx_log_t   *log;
+    ngx_uint_t   exists;   /* unsigned  exists:1;  */
 } ngx_shm_t;