changeset 668:9fbf3ad94cbf NGINX_1_1_18

nginx 1.1.18 *) Change: keepalive connections are no longer disabled for Safari by default. *) Feature: the $connection_requests variable. *) Feature: $tcpinfo_rtt, $tcpinfo_rttvar, $tcpinfo_snd_cwnd and $tcpinfo_rcv_space variables. *) Feature: the "worker_cpu_affinity" directive now works on FreeBSD. *) Feature: the "xslt_param" and "xslt_string_param" directives. Thanks to Samuel Behan. *) Bugfix: in configure tests. Thanks to Piotr Sikora. *) Bugfix: in the ngx_http_xslt_filter_module. *) Bugfix: nginx could not be built on Debian GNU/Hurd.
author Igor Sysoev <http://sysoev.ru>
date Wed, 28 Mar 2012 00:00:00 +0400
parents e0eabdb2bad1
children 3f5d0be5ee74
files CHANGES CHANGES.ru auto/lib/pcre/conf auto/os/freebsd auto/os/linux auto/os/solaris auto/sources auto/types/sizeof auto/types/typedef auto/types/uintptr_t auto/unix src/core/nginx.c src/core/nginx.h src/core/ngx_cycle.h src/core/ngx_resolver.c src/http/modules/ngx_http_headers_filter_module.c src/http/modules/ngx_http_log_module.c src/http/modules/ngx_http_realip_module.c src/http/modules/ngx_http_split_clients_module.c src/http/modules/ngx_http_xslt_filter_module.c src/http/modules/perl/nginx.pm src/http/ngx_http_copy_filter_module.c src/http/ngx_http_core_module.c src/http/ngx_http_parse.c src/http/ngx_http_postpone_filter_module.c src/http/ngx_http_request.c src/http/ngx_http_upstream.c src/http/ngx_http_variables.c src/os/unix/ngx_files.h src/os/unix/ngx_freebsd_config.h src/os/unix/ngx_posix_config.h src/os/unix/ngx_process.h src/os/unix/ngx_process_cycle.c src/os/unix/ngx_setaffinity.c src/os/unix/ngx_setaffinity.h src/os/unix/ngx_solaris_config.h
diffstat 36 files changed, 597 insertions(+), 160 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES	Thu Mar 15 00:00:00 2012 +0400
+++ b/CHANGES	Wed Mar 28 00:00:00 2012 +0400
@@ -1,4 +1,27 @@
 
+Changes with nginx 1.1.18                                        28 Mar 2012
+
+    *) Change: keepalive connections are no longer disabled for Safari by
+       default.
+
+    *) Feature: the $connection_requests variable.
+
+    *) Feature: $tcpinfo_rtt, $tcpinfo_rttvar, $tcpinfo_snd_cwnd and
+       $tcpinfo_rcv_space variables.
+
+    *) Feature: the "worker_cpu_affinity" directive now works on FreeBSD.
+
+    *) Feature: the "xslt_param" and "xslt_string_param" directives.
+       Thanks to Samuel Behan.
+
+    *) Bugfix: in configure tests.
+       Thanks to Piotr Sikora.
+
+    *) Bugfix: in the ngx_http_xslt_filter_module.
+
+    *) Bugfix: nginx could not be built on Debian GNU/Hurd.
+
+
 Changes with nginx 1.1.17                                        15 Mar 2012
 
     *) Security: content of previously freed memory might be sent to a
--- a/CHANGES.ru	Thu Mar 15 00:00:00 2012 +0400
+++ b/CHANGES.ru	Wed Mar 28 00:00:00 2012 +0400
@@ -1,4 +1,27 @@
 
+Изменения в nginx 1.1.18                                          28.03.2012
+
+    *) Изменение: теперь keepalive соединения не запрещены для Safari по
+       умолчанию.
+
+    *) Добавление: переменная $connection_requests.
+
+    *) Добавление: переменные $tcpinfo_rtt, $tcpinfo_rttvar,
+       $tcpinfo_snd_cwnd и $tcpinfo_rcv_space.
+
+    *) Добавление: директива worker_cpu_affinity теперь работает на FreeBSD.
+
+    *) Добавление: директивы xslt_param и xslt_string_param.
+       Спасибо Samuel Behan.
+
+    *) Исправление: в configure.
+       Спасибо Piotr Sikora.
+
+    *) Исправление: в модуле ngx_http_xslt_filter_module.
+
+    *) Исправление: nginx не собирался на Debian GNU/Hurd.
+
+
 Изменения в nginx 1.1.17                                          15.03.2012
 
     *) Безопасность: содержимое ранее освобождённой памяти могло быть
--- a/auto/lib/pcre/conf	Thu Mar 15 00:00:00 2012 +0400
+++ b/auto/lib/pcre/conf	Wed Mar 28 00:00:00 2012 +0400
@@ -98,7 +98,9 @@
         ngx_feature_incs="#include <pcre.h>"
         ngx_feature_path=
         ngx_feature_libs="-lpcre"
-        ngx_feature_test="pcre *re; re = pcre_compile(NULL, 0, NULL, 0, NULL)"
+        ngx_feature_test="pcre *re;
+                          re = pcre_compile(NULL, 0, NULL, 0, NULL);
+                          if (re == NULL) return 1"
         . auto/feature
 
         if [ $ngx_found = no ]; then
--- a/auto/os/freebsd	Thu Mar 15 00:00:00 2012 +0400
+++ b/auto/os/freebsd	Wed Mar 28 00:00:00 2012 +0400
@@ -134,3 +134,11 @@
         exit 1
     fi
 fi
+
+
+# cpuset_setaffinity()
+
+if [ $version -ge 701000 ]; then
+    echo " + cpuset_setaffinity() found"
+    have=NGX_HAVE_CPUSET_SETAFFINITY . auto/have
+fi
--- a/auto/os/linux	Thu Mar 15 00:00:00 2012 +0400
+++ b/auto/os/linux	Wed Mar 28 00:00:00 2012 +0400
@@ -52,7 +52,7 @@
 ngx_feature_incs="#include <sys/epoll.h>"
 ngx_feature_path=
 ngx_feature_libs=
-ngx_feature_test="int efd = 0, fd = 1, n;
+ngx_feature_test="int efd = 0;
                   struct epoll_event ee;
                   ee.events = EPOLLIN|EPOLLOUT|EPOLLET;
                   ee.data.ptr = NULL;
@@ -128,8 +128,9 @@
 ngx_feature_incs="#include <sched.h>"
 ngx_feature_path=
 ngx_feature_libs=
-ngx_feature_test="long mask = 0;
-                  sched_setaffinity(0, 32, (cpu_set_t *) &mask)"
+ngx_feature_test="cpu_set_t mask;
+                  CPU_ZERO(&mask);
+                  sched_setaffinity(0, sizeof(cpu_set_t), &mask)"
 . auto/feature
 
 
@@ -142,7 +143,7 @@
 ngx_feature_path=
 ngx_feature_libs=-lcrypt
 ngx_feature_test="struct crypt_data  cd;
-                  crypt_r(NULL, NULL, &cd);"
+                  crypt_r(\"key\", \"salt\", &cd);"
 . auto/feature
 
 
--- a/auto/os/solaris	Thu Mar 15 00:00:00 2012 +0400
+++ b/auto/os/solaris	Wed Mar 28 00:00:00 2012 +0400
@@ -35,7 +35,8 @@
 ngx_feature_libs="-lsendfile"
 ngx_feature_test="int fd = 1; sendfilevec_t vec[1];
                   size_t sent; ssize_t n;
-                  n = sendfilev(fd, vec, 1, &sent)"
+                  n = sendfilev(fd, vec, 1, &sent);
+                  if (n == -1) return 1"
 . auto/feature
 
 
--- a/auto/sources	Thu Mar 15 00:00:00 2012 +0400
+++ b/auto/sources	Wed Mar 28 00:00:00 2012 +0400
@@ -145,6 +145,7 @@
             src/os/unix/ngx_channel.h \
             src/os/unix/ngx_shmem.h \
             src/os/unix/ngx_process.h \
+            src/os/unix/ngx_setaffinity.h \
             src/os/unix/ngx_setproctitle.h \
             src/os/unix/ngx_atomic.h \
             src/os/unix/ngx_gcc_atomic_x86.h \
@@ -179,6 +180,7 @@
             src/os/unix/ngx_shmem.c \
             src/os/unix/ngx_process.c \
             src/os/unix/ngx_daemon.c \
+            src/os/unix/ngx_setaffinity.c \
             src/os/unix/ngx_setproctitle.c \
             src/os/unix/ngx_posix_init.c \
             src/os/unix/ngx_user.c \
--- a/auto/types/sizeof	Thu Mar 15 00:00:00 2012 +0400
+++ b/auto/types/sizeof	Wed Mar 28 00:00:00 2012 +0400
@@ -20,12 +20,13 @@
 #include <sys/time.h>
 $NGX_INCLUDE_UNISTD_H
 #include <signal.h>
+#include <stdio.h>
 #include <sys/resource.h>
 $NGX_INCLUDE_INTTYPES_H
 $NGX_INCLUDE_AUTO_CONFIG_H
 
 int main() {
-    printf("%d", sizeof($ngx_type));
+    printf("%d", (int) sizeof($ngx_type));
     return 0;
 }
 
--- a/auto/types/typedef	Thu Mar 15 00:00:00 2012 +0400
+++ b/auto/types/typedef	Wed Mar 28 00:00:00 2012 +0400
@@ -29,7 +29,7 @@
 
 int main() {
     $ngx_try i = 0;
-    return 0;
+    return (int) i;
 }
 
 END
--- a/auto/types/uintptr_t	Thu Mar 15 00:00:00 2012 +0400
+++ b/auto/types/uintptr_t	Wed Mar 28 00:00:00 2012 +0400
@@ -4,8 +4,8 @@
 
 
 echo $ngx_n "checking for uintptr_t ...$ngx_c"
-echo >> $NGX_ERR
-echo "checking for uintptr_t" >> $NGX_ERR
+echo >> $NGX_AUTOCONF_ERR
+echo "checking for uintptr_t" >> $NGX_AUTOCONF_ERR
 
 found=no
 
@@ -16,12 +16,15 @@
 
 int main() {
     uintptr_t i = 0;
-    return 0;
+    return (int) i;
 }
 
 END
 
-eval "$CC -o $NGX_AUTOTEST $NGX_AUTOTEST.c >> $NGX_ERR 2>&1"
+ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS \
+          -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_LD_OPT"
+
+eval "$ngx_test >> $NGX_AUTOCONF_ERR 2>&1"
 
 if [ -x $NGX_AUTOTEST ]; then
     echo " uintptr_t found"
--- a/auto/unix	Thu Mar 15 00:00:00 2012 +0400
+++ b/auto/unix	Wed Mar 28 00:00:00 2012 +0400
@@ -33,12 +33,12 @@
 ngx_feature_incs="#include <poll.h>"
 ngx_feature_path=
 ngx_feature_libs=
-ngx_feature_test="int  n, dp; struct pollfd  pl;
-                  dp = 0;
+ngx_feature_test="int  n; struct pollfd  pl;
                   pl.fd = 0;
                   pl.events = 0;
                   pl.revents = 0;
-                  n = poll(&pl, 1, 0)"
+                  n = poll(&pl, 1, 0);
+                  if (n == -1) return 1"
 . auto/feature
 
 if [ $ngx_found = no ]; then
@@ -57,7 +57,8 @@
                   dvp.dp_fds = NULL;
                   dvp.dp_nfds = 0;
                   dvp.dp_timeout = 0;
-                  n = ioctl(dp, DP_POLL, &dvp)"
+                  n = ioctl(dp, DP_POLL, &dvp);
+                  if (n == -1) return 1"
 . auto/feature
 
 if [ $ngx_found = yes ]; then
@@ -237,7 +238,7 @@
 ngx_feature_path=
 ngx_feature_libs=
 ngx_feature_test="struct statfs  fs;
-                  statfs(NULL, &fs);"
+                  statfs(\".\", &fs);"
 . auto/feature
 
 
@@ -249,7 +250,7 @@
 ngx_feature_path=
 ngx_feature_libs=
 ngx_feature_test="struct statvfs  fs;
-                  statvfs(NULL, &fs);"
+                  statvfs(\".\", &fs);"
 . auto/feature
 
 
@@ -343,6 +344,24 @@
 . auto/feature
 
 
+ngx_feature="TCP_INFO"
+ngx_feature_name="NGX_HAVE_TCP_INFO"
+ngx_feature_run=no
+ngx_feature_incs="#include <sys/socket.h>
+                  #include <netinet/in.h>
+                  #include <netinet/tcp.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="socklen_t optlen = sizeof(struct tcp_info);
+                  struct tcp_info ti;
+                  ti.tcpi_rtt = 0;
+                  ti.tcpi_rttvar = 0;
+                  ti.tcpi_snd_cwnd = 0;
+                  ti.tcpi_rcv_space = 0;
+                  getsockopt(0, IPPROTO_TCP, TCP_INFO, &ti, &optlen)"
+. auto/feature
+
+
 ngx_feature="accept4()"
 ngx_feature_name="NGX_HAVE_ACCEPT4"
 ngx_feature_run=no
@@ -481,7 +500,7 @@
 ngx_feature="setproctitle()"
 ngx_feature_name="NGX_HAVE_SETPROCTITLE"
 ngx_feature_run=no
-ngx_feature_incs=
+ngx_feature_incs="#include <stdlib.h>"
 ngx_feature_path=
 ngx_feature_libs=$NGX_SETPROCTITLE_LIB
 ngx_feature_test="setproctitle(\"test\");"
@@ -494,7 +513,8 @@
 ngx_feature_incs=
 ngx_feature_path=
 ngx_feature_libs=
-ngx_feature_test="char buf[1]; ssize_t n; n = pread(0, buf, 1, 0)"
+ngx_feature_test="char buf[1]; ssize_t n; n = pread(0, buf, 1, 0);
+                  if (n == -1) return 1"
 . auto/feature
 
 
@@ -504,7 +524,8 @@
 ngx_feature_incs=
 ngx_feature_path=
 ngx_feature_libs=
-ngx_feature_test="char buf[1]; ssize_t n; n = pwrite(1, buf, 1, 0)"
+ngx_feature_test="char buf[1]; ssize_t n; n = pwrite(1, buf, 1, 0);
+                  if (n == -1) return 1"
 . auto/feature
 
 
@@ -578,17 +599,20 @@
 ngx_feature_incs="#include <stdlib.h>"
 ngx_feature_path=
 ngx_feature_libs=
-ngx_feature_test="void *p; int n; n = posix_memalign(&p, 4096, 4096)"
+ngx_feature_test="void *p; int n; n = posix_memalign(&p, 4096, 4096);
+                  if (n != 0) return 1"
 . auto/feature
 
 
 ngx_feature="memalign()"
 ngx_feature_name="NGX_HAVE_MEMALIGN"
 ngx_feature_run=no
-ngx_feature_incs="#include <stdlib.h>"
+ngx_feature_incs="#include <stdlib.h>
+                  #include <malloc.h>"
 ngx_feature_path=
 ngx_feature_libs=
-ngx_feature_test="void *p; p = memalign(4096, 4096)"
+ngx_feature_test="void *p; p = memalign(4096, 4096);
+                  if (p == NULL) return 1"
 . auto/feature
 
 
@@ -675,10 +699,12 @@
 ngx_feature="struct msghdr.msg_control"
 ngx_feature_name="NGX_HAVE_MSGHDR_MSG_CONTROL"
 ngx_feature_run=no
-ngx_feature_incs="#include <sys/socket.h>"
+ngx_feature_incs="#include <sys/socket.h>
+                  #include <stdio.h>"
 ngx_feature_path=
 ngx_feature_libs=
-ngx_feature_test="struct msghdr  msg; msg.msg_control = NULL"
+ngx_feature_test="struct msghdr  msg;
+                  printf(\"%d\", (int) sizeof(msg.msg_control))"
 . auto/feature
 
 
@@ -686,40 +712,47 @@
 ngx_feature_name="NGX_HAVE_FIONBIO"
 ngx_feature_run=no
 ngx_feature_incs="#include <sys/ioctl.h>
+                  #include <stdio.h>
                   $NGX_INCLUDE_SYS_FILIO_H"
 ngx_feature_path=
 ngx_feature_libs=
-ngx_feature_test="int i; i = FIONBIO"
+ngx_feature_test="int i = FIONBIO; printf(\"%d\", i)"
 . auto/feature
 
 
 ngx_feature="struct tm.tm_gmtoff"
 ngx_feature_name="NGX_HAVE_GMTOFF"
 ngx_feature_run=no
-ngx_feature_incs="#include <time.h>"
+ngx_feature_incs="#include <time.h>
+                  #include <stdio.h>"
 ngx_feature_path=
 ngx_feature_libs=
-ngx_feature_test="struct tm  tm; tm.tm_gmtoff = 0"
+ngx_feature_test="struct tm  tm; tm.tm_gmtoff = 0;
+                  printf(\"%d\", (int) tm.tm_gmtoff)"
 . auto/feature
 
 
 ngx_feature="struct dirent.d_namlen"
 ngx_feature_name="NGX_HAVE_D_NAMLEN"
 ngx_feature_run=no
-ngx_feature_incs="#include <dirent.h>"
+ngx_feature_incs="#include <dirent.h>
+                  #include <stdio.h>"
 ngx_feature_path=
 ngx_feature_libs=
-ngx_feature_test="struct dirent  dir; dir.d_namlen = 0"
+ngx_feature_test="struct dirent  dir; dir.d_namlen = 0;
+                  printf(\"%d\", (int) dir.d_namlen)"
 . auto/feature
 
 
 ngx_feature="struct dirent.d_type"
 ngx_feature_name="NGX_HAVE_D_TYPE"
 ngx_feature_run=no
-ngx_feature_incs="#include <dirent.h>"
+ngx_feature_incs="#include <dirent.h>
+                  #include <stdio.h>"
 ngx_feature_path=
 ngx_feature_libs=
-ngx_feature_test="struct dirent  dir; dir.d_type = DT_REG"
+ngx_feature_test="struct dirent  dir; dir.d_type = DT_REG;
+                  printf(\"%d\", (int) dir.d_type)"
 . auto/feature
 
 
--- a/src/core/nginx.c	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/core/nginx.c	Wed Mar 28 00:00:00 2012 +0400
@@ -983,15 +983,15 @@
     ngx_conf_init_value(ccf->worker_processes, 1);
     ngx_conf_init_value(ccf->debug_points, 0);
 
-#if (NGX_HAVE_SCHED_SETAFFINITY)
+#if (NGX_HAVE_CPU_AFFINITY)
 
     if (ccf->cpu_affinity_n
         && ccf->cpu_affinity_n != 1
         && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes)
     {
         ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
-                      "number of the \"worker_processes\" is not equal to "
-                      "the number of the \"worker_cpu_affinity\" mask, "
+                      "the number of \"worker_processes\" is not equal to "
+                      "the number of \"worker_cpu_affinity\" masks, "
                       "using last mask for remaining worker processes");
     }
 
@@ -1242,11 +1242,11 @@
 static char *
 ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-#if (NGX_HAVE_SCHED_SETAFFINITY)
+#if (NGX_HAVE_CPU_AFFINITY)
     ngx_core_conf_t  *ccf = conf;
 
     u_char            ch;
-    u_long           *mask;
+    uint64_t         *mask;
     ngx_str_t        *value;
     ngx_uint_t        i, n;
 
@@ -1254,7 +1254,7 @@
         return "is duplicate";
     }
 
-    mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(long));
+    mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(uint64_t));
     if (mask == NULL) {
         return NGX_CONF_ERROR;
     }
@@ -1266,9 +1266,9 @@
 
     for (n = 1; n < cf->args->nelts; n++) {
 
-        if (value[n].len > 32) {
+        if (value[n].len > 64) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                         "\"worker_cpu_affinity\" supports up to 32 CPU only");
+                         "\"worker_cpu_affinity\" supports up to 64 CPUs only");
             return NGX_CONF_ERROR;
         }
 
@@ -1311,7 +1311,7 @@
 }
 
 
-u_long
+uint64_t
 ngx_get_cpu_affinity(ngx_uint_t n)
 {
     ngx_core_conf_t  *ccf;
--- a/src/core/nginx.h	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/core/nginx.h	Wed Mar 28 00:00:00 2012 +0400
@@ -9,8 +9,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version      1001017
-#define NGINX_VERSION      "1.1.17"
+#define nginx_version      1001018
+#define NGINX_VERSION      "1.1.18"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_cycle.h	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/core/ngx_cycle.h	Wed Mar 28 00:00:00 2012 +0400
@@ -86,7 +86,7 @@
      int                      priority;
 
      ngx_uint_t               cpu_affinity_n;
-     u_long                  *cpu_affinity;
+     uint64_t                *cpu_affinity;
 
      char                    *username;
      ngx_uid_t                user;
@@ -124,7 +124,7 @@
 void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user);
 char **ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last);
 ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv);
-u_long ngx_get_cpu_affinity(ngx_uint_t n);
+uint64_t ngx_get_cpu_affinity(ngx_uint_t n);
 ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name,
     size_t size, void *tag);
 
--- a/src/core/ngx_resolver.c	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/core/ngx_resolver.c	Wed Mar 28 00:00:00 2012 +0400
@@ -1840,7 +1840,7 @@
             len++;
 
         } else {
-            if (len == 0) {
+            if (len == 0 || len > 255) {
                 return NGX_DECLINED;
             }
 
@@ -1851,6 +1851,10 @@
         p--;
     }
 
+    if (len == 0 || len > 255) {
+        return NGX_DECLINED;
+    }
+
     *p = (u_char) len;
 
     return NGX_OK;
--- a/src/http/modules/ngx_http_headers_filter_module.c	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/http/modules/ngx_http_headers_filter_module.c	Wed Mar 28 00:00:00 2012 +0400
@@ -25,23 +25,25 @@
 
 struct ngx_http_header_val_s {
     ngx_http_complex_value_t   value;
-    ngx_uint_t                 hash;
     ngx_str_t                  key;
     ngx_http_set_header_pt     handler;
     ngx_uint_t                 offset;
 };
 
 
-#define NGX_HTTP_EXPIRES_OFF       0
-#define NGX_HTTP_EXPIRES_EPOCH     1
-#define NGX_HTTP_EXPIRES_MAX       2
-#define NGX_HTTP_EXPIRES_ACCESS    3
-#define NGX_HTTP_EXPIRES_MODIFIED  4
-#define NGX_HTTP_EXPIRES_DAILY     5
+typedef enum {
+    NGX_HTTP_EXPIRES_OFF,
+    NGX_HTTP_EXPIRES_EPOCH,
+    NGX_HTTP_EXPIRES_MAX,
+    NGX_HTTP_EXPIRES_ACCESS,
+    NGX_HTTP_EXPIRES_MODIFIED,
+    NGX_HTTP_EXPIRES_DAILY,
+    NGX_HTTP_EXPIRES_UNSET
+} ngx_http_expires_t;
 
 
 typedef struct {
-    ngx_uint_t               expires;
+    ngx_http_expires_t       expires;
     time_t                   expires_time;
     ngx_array_t             *headers;
 } ngx_http_headers_conf_t;
@@ -51,6 +53,8 @@
     ngx_http_headers_conf_t *conf);
 static ngx_int_t ngx_http_add_cache_control(ngx_http_request_t *r,
     ngx_http_header_val_t *hv, ngx_str_t *value);
+static ngx_int_t ngx_http_add_header(ngx_http_request_t *r,
+    ngx_http_header_val_t *hv, ngx_str_t *value);
 static ngx_int_t ngx_http_set_last_modified(ngx_http_request_t *r,
     ngx_http_header_val_t *hv, ngx_str_t *value);
 
@@ -313,7 +317,7 @@
             return NGX_ERROR;
         }
 
-        h->hash = hv->hash;
+        h->hash = 1;
         h->key = hv->key;
         h->value = *value;
     }
@@ -366,16 +370,11 @@
 {
     ngx_table_elt_t  *h, **old;
 
-    if (hv->offset) {
-        old = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset);
-
-    } else {
-        old = NULL;
-    }
+    old = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset);
 
     r->headers_out.last_modified_time = -1;
 
-    if (old == NULL || *old == NULL) {
+    if (*old == NULL) {
 
         if (value->len == 0) {
             return NGX_OK;
@@ -386,6 +385,8 @@
             return NGX_ERROR;
         }
 
+        *old = h;
+
     } else {
         h = *old;
 
@@ -395,7 +396,7 @@
         }
     }
 
-    h->hash = hv->hash;
+    h->hash = 1;
     h->key = hv->key;
     h->value = *value;
 
@@ -420,7 +421,7 @@
      *     conf->expires_time = 0;
      */
 
-    conf->expires = NGX_CONF_UNSET_UINT;
+    conf->expires = NGX_HTTP_EXPIRES_UNSET;
 
     return conf;
 }
@@ -432,11 +433,11 @@
     ngx_http_headers_conf_t *prev = parent;
     ngx_http_headers_conf_t *conf = child;
 
-    if (conf->expires == NGX_CONF_UNSET_UINT) {
+    if (conf->expires == NGX_HTTP_EXPIRES_UNSET) {
         conf->expires = prev->expires;
         conf->expires_time = prev->expires_time;
 
-        if (conf->expires == NGX_CONF_UNSET_UINT) {
+        if (conf->expires == NGX_HTTP_EXPIRES_UNSET) {
             conf->expires = NGX_HTTP_EXPIRES_OFF;
         }
     }
@@ -467,7 +468,7 @@
     ngx_uint_t   minus, n;
     ngx_str_t   *value;
 
-    if (hcf->expires != NGX_CONF_UNSET_UINT) {
+    if (hcf->expires != NGX_HTTP_EXPIRES_UNSET) {
         return "is duplicate";
     }
 
@@ -576,7 +577,6 @@
         return NGX_CONF_ERROR;
     }
 
-    hv->hash = 1;
     hv->key = value[1];
     hv->handler = ngx_http_add_header;
     hv->offset = 0;
--- a/src/http/modules/ngx_http_log_module.c	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/http/modules/ngx_http_log_module.c	Wed Mar 28 00:00:00 2012 +0400
@@ -80,6 +80,8 @@
 
 static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf,
     ngx_http_log_op_t *op);
+static u_char *ngx_http_log_connection_requests(ngx_http_request_t *r,
+    u_char *buf, ngx_http_log_op_t *op);
 static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf,
     ngx_http_log_op_t *op);
 static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf,
@@ -193,6 +195,8 @@
 
 static ngx_http_log_var_t  ngx_http_log_vars[] = {
     { ngx_string("connection"), NGX_ATOMIC_T_LEN, ngx_http_log_connection },
+    { ngx_string("connection_requests"), NGX_INT_T_LEN,
+                          ngx_http_log_connection_requests },
     { ngx_string("pipe"), 1, ngx_http_log_pipe },
     { ngx_string("time_local"), sizeof("28/Sep/1970:12:00:00 +0600") - 1,
                           ngx_http_log_time },
@@ -501,7 +505,15 @@
 ngx_http_log_connection(ngx_http_request_t *r, u_char *buf,
     ngx_http_log_op_t *op)
 {
-    return ngx_sprintf(buf, "%ui", r->connection->number);
+    return ngx_sprintf(buf, "%uA", r->connection->number);
+}
+
+
+static u_char *
+ngx_http_log_connection_requests(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op)
+{
+    return ngx_sprintf(buf, "%ui", r->connection->requests);
 }
 
 
--- a/src/http/modules/ngx_http_realip_module.c	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/http/modules/ngx_http_realip_module.c	Wed Mar 28 00:00:00 2012 +0400
@@ -16,13 +16,7 @@
 
 
 typedef struct {
-    in_addr_t          mask;
-    in_addr_t          addr;
-} ngx_http_realip_from_t;
-
-
-typedef struct {
-    ngx_array_t       *from;     /* array of ngx_http_realip_from_t */
+    ngx_array_t       *from;     /* array of ngx_in_cidr_t */
     ngx_uint_t         type;
     ngx_uint_t         hash;
     ngx_str_t          header;
@@ -114,9 +108,9 @@
     ngx_list_part_t             *part;
     ngx_table_elt_t             *header;
     struct sockaddr_in          *sin;
+    ngx_in_cidr_t               *from;
     ngx_connection_t            *c;
     ngx_http_realip_ctx_t       *ctx;
-    ngx_http_realip_from_t      *from;
     ngx_http_realip_loc_conf_t  *rlcf;
 
     ctx = ngx_http_get_module_ctx(r, ngx_http_realip_module);
@@ -317,7 +311,7 @@
     ngx_int_t                rc;
     ngx_str_t               *value;
     ngx_cidr_t               cidr;
-    ngx_http_realip_from_t  *from;
+    ngx_in_cidr_t           *from;
 
     value = cf->args->elts;
 
@@ -332,7 +326,7 @@
 
     if (rlcf->from == NULL) {
         rlcf->from = ngx_array_create(cf->pool, 2,
-                                      sizeof(ngx_http_realip_from_t));
+                                      sizeof(ngx_in_cidr_t));
         if (rlcf->from == NULL) {
             return NGX_CONF_ERROR;
         }
--- a/src/http/modules/ngx_http_split_clients_module.c	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/http/modules/ngx_http_split_clients_module.c	Wed Mar 28 00:00:00 2012 +0400
@@ -97,7 +97,7 @@
         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                        "http split: %uD %uD", hash, part[i].percent);
 
-        if (hash < part[i].percent) {
+        if (hash < part[i].percent || part[i].percent == 0) {
             *v = part[i].value;
             return NGX_OK;
         }
@@ -111,8 +111,9 @@
 ngx_conf_split_clients_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     char                                *rv;
+    uint32_t                             sum, last;
     ngx_str_t                           *value, name;
-    ngx_uint_t                           i, sum, last;
+    ngx_uint_t                           i;
     ngx_conf_t                           save;
     ngx_http_variable_t                 *var;
     ngx_http_split_clients_ctx_t        *ctx;
@@ -175,19 +176,15 @@
     for (i = 0; i < ctx->parts.nelts; i++) {
         sum = part[i].percent ? sum + part[i].percent : 10000;
         if (sum > 10000) {
-           ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                              "percent sum is more than 100%%");
-           return NGX_CONF_ERROR;
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "percent sum is more than 100%%");
+            return NGX_CONF_ERROR;
         }
 
         if (part[i].percent) {
-            part[i].percent = (uint32_t)
-                                 (last + 0xffffffff / 10000 * part[i].percent);
-        } else {
-            part[i].percent = 0xffffffff;
+            last += part[i].percent * (uint64_t) 0xffffffff / 10000;
+            part[i].percent = last;
         }
-
-        last = part[i].percent;
     }
 
     return rv;
--- a/src/http/modules/ngx_http_xslt_filter_module.c	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/http/modules/ngx_http_xslt_filter_module.c	Wed Mar 28 00:00:00 2012 +0400
@@ -14,6 +14,7 @@
 #include <libxslt/xslt.h>
 #include <libxslt/xsltInternals.h>
 #include <libxslt/transform.h>
+#include <libxslt/variables.h>
 #include <libxslt/xsltutils.h>
 
 #if (NGX_HAVE_EXSLT)
@@ -27,38 +28,47 @@
 
 
 typedef struct {
-    u_char              *name;
-    void                *data;
+    u_char                    *name;
+    void                      *data;
 } ngx_http_xslt_file_t;
 
 
 typedef struct {
-    ngx_array_t          dtd_files;    /* ngx_http_xslt_file_t */
-    ngx_array_t          sheet_files;  /* ngx_http_xslt_file_t */
+    ngx_array_t                dtd_files;    /* ngx_http_xslt_file_t */
+    ngx_array_t                sheet_files;  /* ngx_http_xslt_file_t */
 } ngx_http_xslt_filter_main_conf_t;
 
 
 typedef struct {
-    xsltStylesheetPtr    stylesheet;
-    ngx_array_t          params;       /* ngx_http_complex_value_t */
+    u_char                    *name;
+    ngx_http_complex_value_t   value;
+    ngx_uint_t                 quote;        /* unsigned  quote:1; */
+} ngx_http_xslt_param_t;
+
+
+typedef struct {
+    xsltStylesheetPtr          stylesheet;
+    ngx_array_t                params;       /* ngx_http_xslt_param_t */
 } ngx_http_xslt_sheet_t;
 
 
 typedef struct {
-    xmlDtdPtr            dtd;
-    ngx_array_t          sheets;       /* ngx_http_xslt_sheet_t */
-    ngx_hash_t           types;
-    ngx_array_t         *types_keys;
+    xmlDtdPtr                  dtd;
+    ngx_array_t                sheets;       /* ngx_http_xslt_sheet_t */
+    ngx_hash_t                 types;
+    ngx_array_t               *types_keys;
+    ngx_array_t               *params;       /* ngx_http_xslt_param_t */
 } ngx_http_xslt_filter_loc_conf_t;
 
 
 typedef struct {
-    xmlDocPtr            doc;
-    xmlParserCtxtPtr     ctxt;
-    ngx_http_request_t  *request;
-    ngx_array_t          params;
+    xmlDocPtr                  doc;
+    xmlParserCtxtPtr           ctxt;
+    xsltTransformContextPtr    transform;
+    ngx_http_request_t        *request;
+    ngx_array_t                params;
 
-    ngx_uint_t           done;         /* unsigned  done:1; */
+    ngx_uint_t                 done;         /* unsigned  done:1; */
 } ngx_http_xslt_filter_ctx_t;
 
 
@@ -76,7 +86,7 @@
 static ngx_buf_t *ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r,
     ngx_http_xslt_filter_ctx_t *ctx);
 static ngx_int_t ngx_http_xslt_params(ngx_http_request_t *r,
-    ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params);
+    ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params, ngx_uint_t final);
 static u_char *ngx_http_xslt_content_type(xsltStylesheetPtr s);
 static u_char *ngx_http_xslt_encoding(xsltStylesheetPtr s);
 static void ngx_http_xslt_cleanup(void *data);
@@ -85,6 +95,8 @@
     void *conf);
 static char *ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
+static char *ngx_http_xslt_param(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
 static void ngx_http_xslt_cleanup_dtd(void *data);
 static void ngx_http_xslt_cleanup_stylesheet(void *data);
 static void *ngx_http_xslt_filter_create_main_conf(ngx_conf_t *cf);
@@ -117,6 +129,20 @@
       0,
       NULL },
 
+    { ngx_string("xslt_param"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
+      ngx_http_xslt_param,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
+    { ngx_string("xslt_string_param"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
+      ngx_http_xslt_param,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      (void *) 1 },
+
     { ngx_string("xslt_types"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
       ngx_http_types_slot,
@@ -336,15 +362,14 @@
                           "xmlCreatePushParserCtxt() failed");
             return NGX_ERROR;
         }
+        xmlCtxtUseOptions(ctxt, XML_PARSE_NOENT|XML_PARSE_DTDLOAD
+                                               |XML_PARSE_NOWARNING);
 
         ctxt->sax->externalSubset = ngx_http_xslt_sax_external_subset;
         ctxt->sax->setDocumentLocator = NULL;
-        ctxt->sax->warning = NULL;
         ctxt->sax->error = ngx_http_xslt_sax_error;
         ctxt->sax->fatalError = ngx_http_xslt_sax_error;
         ctxt->sax->_private = ctx;
-        ctxt->replaceEntities = 1;
-        ctxt->loadsubset = 1;
 
         ctx->ctxt = ctxt;
         ctx->request = r;
@@ -469,13 +494,31 @@
 
     for (i = 0; i < conf->sheets.nelts; i++) {
 
-        if (ngx_http_xslt_params(r, ctx, &sheet[i].params) != NGX_OK) {
+        ctx->transform = xsltNewTransformContext(sheet[i].stylesheet, doc);
+        if (ctx->transform == NULL) {
             xmlFreeDoc(doc);
             return NULL;
         }
 
-        res = xsltApplyStylesheet(sheet[i].stylesheet, doc, ctx->params.elts);
+        if (conf->params
+            && ngx_http_xslt_params(r, ctx, conf->params, 0) != NGX_OK)
+        {
+            xsltFreeTransformContext(ctx->transform);
+            xmlFreeDoc(doc);
+            return NULL;
+        }
 
+        if (ngx_http_xslt_params(r, ctx, &sheet[i].params, 1) != NGX_OK) {
+            xsltFreeTransformContext(ctx->transform);
+            xmlFreeDoc(doc);
+            return NULL;
+        }
+
+        res = xsltApplyStylesheetUser(sheet[i].stylesheet, doc,
+                                      ctx->params.elts, NULL, NULL,
+                                      ctx->transform);
+
+        xsltFreeTransformContext(ctx->transform);
         xmlFreeDoc(doc);
 
         if (res == NULL) {
@@ -565,27 +608,68 @@
 
 static ngx_int_t
 ngx_http_xslt_params(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
-    ngx_array_t *params)
+    ngx_array_t *params, ngx_uint_t final)
 {
-    u_char                    *p, *last, *value, *dst, *src, **s;
-    size_t                     len;
-    ngx_uint_t                 i;
-    ngx_str_t                  string;
-    ngx_http_complex_value_t  *param;
+    u_char                 *p, *last, *value, *dst, *src, **s;
+    size_t                  len;
+    ngx_uint_t              i;
+    ngx_str_t               string;
+    ngx_http_xslt_param_t  *param;
 
     param = params->elts;
 
     for (i = 0; i < params->nelts; i++) {
 
-        if (ngx_http_complex_value(r, &param[i], &string) != NGX_OK) {
+        if (ngx_http_complex_value(r, &param[i].value, &string) != NGX_OK) {
             return NGX_ERROR;
         }
 
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                        "xslt filter param: \"%s\"", string.data);
 
+        if (param[i].name) {
+
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "xslt filter param name: \"%s\"", param[i].name);
+
+            if (param[i].quote) {
+                if (xsltQuoteOneUserParam(ctx->transform, param[i].name,
+                                          string.data)
+                    != 0)
+                {
+                    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                                "xsltQuoteOneUserParam(\"%s\", \"%s\") failed",
+                                param[i].name, string.data);
+                    return NGX_ERROR;
+                }
+
+                continue;
+            }
+
+            s = ngx_array_push(&ctx->params);
+            if (s == NULL) {
+                return NGX_ERROR;
+            }
+
+            *s = param[i].name;
+
+            s = ngx_array_push(&ctx->params);
+            if (s == NULL) {
+                return NGX_ERROR;
+            }
+
+            *s = string.data;
+
+            continue;
+        }
+
+        /*
+         * parse param1=value1:param2=value2 syntax as used by parameters
+         * specified in xslt_stylesheet directives
+         */
+
         p = string.data;
-        last = string.data + string.len - 1;
+        last = string.data + string.len;
 
         while (p && *p) {
 
@@ -641,13 +725,15 @@
         }
     }
 
-    s = ngx_array_push(&ctx->params);
-    if (s == NULL) {
-        return NGX_ERROR;
+    if (final) {
+        s = ngx_array_push(&ctx->params);
+        if (s == NULL) {
+            return NGX_ERROR;
+        }
+
+        *s = NULL;
     }
 
-    *s = NULL;
-
     return NGX_OK;
 }
 
@@ -768,7 +854,7 @@
     ngx_pool_cleanup_t                *cln;
     ngx_http_xslt_file_t              *file;
     ngx_http_xslt_sheet_t             *sheet;
-    ngx_http_complex_value_t          *param;
+    ngx_http_xslt_param_t             *param;
     ngx_http_compile_complex_value_t   ccv;
     ngx_http_xslt_filter_main_conf_t  *xmcf;
 
@@ -837,7 +923,7 @@
     }
 
     if (ngx_array_init(&sheet->params, cf->pool, n - 2,
-                       sizeof(ngx_http_complex_value_t))
+                       sizeof(ngx_http_xslt_param_t))
         != NGX_OK)
     {
         return NGX_CONF_ERROR;
@@ -850,11 +936,12 @@
             return NGX_CONF_ERROR;
         }
 
+        ngx_memzero(param, sizeof(ngx_http_xslt_param_t));
         ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
 
         ccv.cf = cf;
         ccv.value = &value[i];
-        ccv.complex_value = param;
+        ccv.complex_value = &param->value;
         ccv.zero = 1;
 
         if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
@@ -866,6 +953,48 @@
 }
 
 
+static char *
+ngx_http_xslt_param(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_xslt_filter_loc_conf_t  *xlcf = conf;
+
+    ngx_http_xslt_param_t            *param;
+    ngx_http_compile_complex_value_t  ccv;
+    ngx_str_t                        *value;
+
+    value = cf->args->elts;
+
+    if (xlcf->params == NULL) {
+        xlcf->params = ngx_array_create(cf->pool, 2,
+                                        sizeof(ngx_http_xslt_param_t));
+        if (xlcf->params == NULL) {
+            return NGX_CONF_ERROR;
+        }
+    }
+
+    param = ngx_array_push(xlcf->params);
+    if (param == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    param->name = value[1].data;
+    param->quote = (cmd->post == NULL) ? 0 : 1;
+
+    ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+    ccv.cf = cf;
+    ccv.value = &value[2];
+    ccv.complex_value = &param->value;
+    ccv.zero = 1;
+
+    if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+        return NGX_CONF_ERROR;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
 static void
 ngx_http_xslt_cleanup_dtd(void *data)
 {
@@ -925,6 +1054,7 @@
      *     conf->sheets = { NULL };
      *     conf->types = { NULL };
      *     conf->types_keys = NULL;
+     *     conf->params = NULL;
      */
 
     return conf;
@@ -945,6 +1075,10 @@
         conf->sheets = prev->sheets;
     }
 
+    if (conf->params == NULL) {
+        conf->params = prev->params;
+    }
+
     if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
                              &prev->types_keys, &prev->types,
                              ngx_http_xslt_default_types)
--- a/src/http/modules/perl/nginx.pm	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/http/modules/perl/nginx.pm	Wed Mar 28 00:00:00 2012 +0400
@@ -50,7 +50,7 @@
     HTTP_INSUFFICIENT_STORAGE
 );
 
-our $VERSION = '1.1.17';
+our $VERSION = '1.1.18';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http_copy_filter_module.c	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/http/ngx_http_copy_filter_module.c	Wed Mar 28 00:00:00 2012 +0400
@@ -74,7 +74,7 @@
 };
 
 
-static ngx_http_output_body_filter_pt    ngx_http_next_filter;
+static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
 
 
 static ngx_int_t
@@ -115,7 +115,8 @@
         ctx->bufs = conf->bufs;
         ctx->tag = (ngx_buf_tag_t) &ngx_http_copy_filter_module;
 
-        ctx->output_filter = (ngx_output_chain_filter_pt) ngx_http_next_filter;
+        ctx->output_filter = (ngx_output_chain_filter_pt)
+                                  ngx_http_next_body_filter;
         ctx->filter_ctx = r;
 
 #if (NGX_HAVE_FILE_AIO)
@@ -292,7 +293,7 @@
 static ngx_int_t
 ngx_http_copy_filter_init(ngx_conf_t *cf)
 {
-    ngx_http_next_filter = ngx_http_top_body_filter;
+    ngx_http_next_body_filter = ngx_http_top_body_filter;
     ngx_http_top_body_filter = ngx_http_copy_filter;
 
     return NGX_OK;
--- a/src/http/ngx_http_core_module.c	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/http/ngx_http_core_module.c	Wed Mar 28 00:00:00 2012 +0400
@@ -3568,8 +3568,7 @@
     ngx_conf_merge_bitmask_value(conf->keepalive_disable,
                               prev->keepalive_disable,
                               (NGX_CONF_BITMASK_SET
-                               |NGX_HTTP_KEEPALIVE_DISABLE_MSIE6
-                               |NGX_HTTP_KEEPALIVE_DISABLE_SAFARI));
+                               |NGX_HTTP_KEEPALIVE_DISABLE_MSIE6));
     ngx_conf_merge_uint_value(conf->satisfy, prev->satisfy,
                               NGX_HTTP_SATISFY_ALL);
     ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since,
@@ -4647,7 +4646,7 @@
 {
     ngx_http_core_loc_conf_t *clcf = conf;
 
-    ngx_str_t  *value;
+    ngx_str_t  *value, name;
 
     if (clcf->error_log) {
         return "is duplicate";
@@ -4655,7 +4654,14 @@
 
     value = cf->args->elts;
 
-    clcf->error_log = ngx_log_create(cf->cycle, &value[1]);
+    if (ngx_strcmp(value[1].data, "stderr") == 0) {
+        ngx_str_null(&name);
+
+    } else {
+        name = value[1];
+    }
+
+    clcf->error_log = ngx_log_create(cf->cycle, &name);
     if (clcf->error_log == NULL) {
         return NGX_CONF_ERROR;
     }
--- a/src/http/ngx_http_parse.c	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/http/ngx_http_parse.c	Wed Mar 28 00:00:00 2012 +0400
@@ -1153,6 +1153,7 @@
                 break;
             case '+':
                 r->plus_in_uri = 1;
+                /* fall through */
             default:
                 *u++ = ch;
                 break;
--- a/src/http/ngx_http_postpone_filter_module.c	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/http/ngx_http_postpone_filter_module.c	Wed Mar 28 00:00:00 2012 +0400
@@ -46,7 +46,7 @@
 };
 
 
-static ngx_http_output_body_filter_pt    ngx_http_next_filter;
+static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
 
 
 static ngx_int_t
@@ -80,7 +80,7 @@
     if (r->postponed == NULL) {
 
         if (in || c->buffered) {
-            return ngx_http_next_filter(r->main, in);
+            return ngx_http_next_body_filter(r->main, in);
         }
 
         return NGX_OK;
@@ -116,7 +116,7 @@
                            "http postpone filter output \"%V?%V\"",
                            &r->uri, &r->args);
 
-            if (ngx_http_next_filter(r->main, pr->out) == NGX_ERROR) {
+            if (ngx_http_next_body_filter(r->main, pr->out) == NGX_ERROR) {
                 return NGX_ERROR;
             }
         }
@@ -171,7 +171,7 @@
 static ngx_int_t
 ngx_http_postpone_filter_init(ngx_conf_t *cf)
 {
-    ngx_http_next_filter = ngx_http_top_body_filter;
+    ngx_http_next_body_filter = ngx_http_top_body_filter;
     ngx_http_top_body_filter = ngx_http_postpone_filter;
 
     return NGX_OK;
--- a/src/http/ngx_http_request.c	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/http/ngx_http_request.c	Wed Mar 28 00:00:00 2012 +0400
@@ -1493,7 +1493,9 @@
         } else if (ngx_strstrn(user_agent, "Chrome/", 7 - 1)) {
             r->headers_in.chrome = 1;
 
-        } else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)) {
+        } else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)
+                   && ngx_strstrn(user_agent, "Mac OS X", 8 - 1))
+        {
             r->headers_in.safari = 1;
 
         } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
--- a/src/http/ngx_http_upstream.c	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/http/ngx_http_upstream.c	Wed Mar 28 00:00:00 2012 +0400
@@ -3312,6 +3312,8 @@
         switch (n) {
         case 0:
             u->cacheable = 0;
+            /* fall through */
+
         case NGX_ERROR:
             return NGX_OK;
 
@@ -4460,6 +4462,8 @@
     case NGX_DECLINED:
         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                            "invalid address \"%V\"", &value[1]);
+        /* fall through */
+
     default:
         return NGX_CONF_ERROR;
     }
--- a/src/http/ngx_http_variables.c	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/http/ngx_http_variables.c	Wed Mar 28 00:00:00 2012 +0400
@@ -34,6 +34,10 @@
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
+#if (NGX_HAVE_TCP_INFO)
+static ngx_int_t ngx_http_variable_tcpinfo(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
+#endif
 
 static ngx_int_t ngx_http_variable_host(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
@@ -259,6 +263,20 @@
     { ngx_string("pid"), NULL, ngx_http_variable_pid,
       0, 0, 0 },
 
+#if (NGX_HAVE_TCP_INFO)
+    { ngx_string("tcpinfo_rtt"), NULL, ngx_http_variable_tcpinfo,
+      0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
+
+    { ngx_string("tcpinfo_rttvar"), NULL, ngx_http_variable_tcpinfo,
+      1, NGX_HTTP_VAR_NOCACHEABLE, 0 },
+
+    { ngx_string("tcpinfo_snd_cwnd"), NULL, ngx_http_variable_tcpinfo,
+      2, NGX_HTTP_VAR_NOCACHEABLE, 0 },
+
+    { ngx_string("tcpinfo_rcv_space"), NULL, ngx_http_variable_tcpinfo,
+      3, NGX_HTTP_VAR_NOCACHEABLE, 0 },
+#endif
+
     { ngx_null_string, NULL, NULL, 0, 0, 0 }
 };
 
@@ -384,7 +402,7 @@
     v->flags = 0;
     v->index = cmcf->variables.nelts - 1;
 
-    return cmcf->variables.nelts - 1;
+    return v->index;
 }
 
 
@@ -884,6 +902,61 @@
 }
 
 
+#if (NGX_HAVE_TCP_INFO)
+
+static ngx_int_t
+ngx_http_variable_tcpinfo(ngx_http_request_t *r, ngx_http_variable_value_t *v,
+    uintptr_t data)
+{
+    struct tcp_info  ti;
+    socklen_t        len;
+    uint32_t         value;
+
+    len = sizeof(struct tcp_info);
+    if (getsockopt(r->connection->fd, IPPROTO_TCP, TCP_INFO, &ti, &len) == -1) {
+        v->not_found = 1;
+        return NGX_OK;
+    }
+
+    v->data = ngx_pnalloc(r->pool, NGX_INT32_LEN);
+    if (v->data == NULL) {
+        return NGX_ERROR;
+    }
+
+    switch (data) {
+    case 0:
+        value = ti.tcpi_rtt;
+        break;
+
+    case 1:
+        value = ti.tcpi_rttvar;
+        break;
+
+    case 2:
+        value = ti.tcpi_snd_cwnd;
+        break;
+
+    case 3:
+        value = ti.tcpi_rcv_space;
+        break;
+
+    /* suppress warning */
+    default:
+        value = 0;
+        break;
+    }
+
+    v->len = ngx_sprintf(v->data, "%uD", value) - v->data;
+    v->valid = 1;
+    v->no_cacheable = 0;
+    v->not_found = 0;
+
+    return NGX_OK;
+}
+
+#endif
+
+
 static ngx_int_t
 ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v,
     uintptr_t data)
@@ -1200,10 +1273,13 @@
 ngx_http_variable_realpath_root(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
+    u_char                    *real;
     size_t                     len;
     ngx_str_t                  path;
     ngx_http_core_loc_conf_t  *clcf;
-    u_char                     real[NGX_MAX_PATH];
+#if (NGX_HAVE_MAX_PATH)
+    u_char                     buffer[NGX_MAX_PATH];
+#endif
 
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
@@ -1225,7 +1301,15 @@
         }
     }
 
-    if (ngx_realpath(path.data, real) == NULL) {
+#if (NGX_HAVE_MAX_PATH)
+    real = buffer;
+#else
+    real = NULL;
+#endif
+
+    real = ngx_realpath(path.data, real);
+
+    if (real == NULL) {
         ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
                       ngx_realpath_n " \"%s\" failed", path.data);
         return NGX_ERROR;
@@ -1235,6 +1319,9 @@
 
     v->data = ngx_pnalloc(r->pool, len);
     if (v->data == NULL) {
+#if !(NGX_HAVE_MAX_PATH)
+        ngx_free(real);
+#endif
         return NGX_ERROR;
     }
 
@@ -1245,6 +1332,10 @@
 
     ngx_memcpy(v->data, real, len);
 
+#if !(NGX_HAVE_MAX_PATH)
+    ngx_free(real);
+#endif
+
     return NGX_OK;
 }
 
--- a/src/os/unix/ngx_files.h	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/os/unix/ngx_files.h	Wed Mar 28 00:00:00 2012 +0400
@@ -200,14 +200,25 @@
 #endif
 
 
-#define ngx_realpath(p, r)       realpath((char *) p, (char *) r)
+#define ngx_realpath(p, r)       (u_char *) realpath((char *) p, (char *) r)
 #define ngx_realpath_n           "realpath()"
 #define ngx_getcwd(buf, size)    (getcwd((char *) buf, size) != NULL)
 #define ngx_getcwd_n             "getcwd()"
 #define ngx_path_separator(c)    ((c) == '/')
 
+
+#if defined(PATH_MAX)
+
+#define NGX_HAVE_MAX_PATH        1
 #define NGX_MAX_PATH             PATH_MAX
 
+#else
+
+#define NGX_MAX_PATH             4096
+
+#endif
+
+
 #define NGX_DIR_MASK_LEN         0
 
 
--- a/src/os/unix/ngx_freebsd_config.h	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/os/unix/ngx_freebsd_config.h	Wed Mar 28 00:00:00 2012 +0400
@@ -23,6 +23,7 @@
 #include <grp.h>
 #include <dirent.h>
 #include <glob.h>
+#include <time.h>
 #include <sys/param.h>          /* ALIGN() */
 #include <sys/mount.h>          /* statfs() */
 
--- a/src/os/unix/ngx_posix_config.h	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/os/unix/ngx_posix_config.h	Wed Mar 28 00:00:00 2012 +0400
@@ -45,6 +45,7 @@
 #include <grp.h>
 #include <dirent.h>
 #include <glob.h>
+#include <time.h>
 #if (NGX_HAVE_SYS_PARAM_H)
 #include <sys/param.h>          /* statfs() */
 #endif
--- a/src/os/unix/ngx_process.h	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/os/unix/ngx_process.h	Wed Mar 28 00:00:00 2012 +0400
@@ -9,6 +9,7 @@
 #define _NGX_PROCESS_H_INCLUDED_
 
 
+#include <ngx_setaffinity.h>
 #include <ngx_setproctitle.h>
 
 
--- a/src/os/unix/ngx_process_cycle.c	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/os/unix/ngx_process_cycle.c	Wed Mar 28 00:00:00 2012 +0400
@@ -62,7 +62,7 @@
 #endif
 
 
-u_long         cpu_affinity;
+uint64_t       cpu_affinity;
 static u_char  master_process[] = "master process";
 
 
@@ -913,23 +913,10 @@
         }
     }
 
-#if (NGX_HAVE_SCHED_SETAFFINITY)
-
     if (cpu_affinity) {
-        ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
-                      "sched_setaffinity(0x%08Xl)", cpu_affinity);
-
-        if (sched_setaffinity(0, sizeof(cpu_affinity),
-                              (cpu_set_t *) &cpu_affinity)
-            == -1)
-        {
-            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
-                          "sched_setaffinity(0x%08Xl) failed", cpu_affinity);
-        }
+        ngx_setaffinity(cpu_affinity, cycle->log);
     }
 
-#endif
-
 #if (NGX_HAVE_PR_SET_DUMPABLE)
 
     /* allow coredump after setuid() in Linux 2.4.x */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/unix/ngx_setaffinity.c	Wed Mar 28 00:00:00 2012 +0400
@@ -0,0 +1,69 @@
+
+/*
+ * Copyright (C) Nginx, Inc.
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+#if (NGX_HAVE_CPUSET_SETAFFINITY)
+
+#include <sys/cpuset.h>
+
+void
+ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log)
+{
+    cpuset_t    mask;
+    ngx_uint_t  i;
+
+    ngx_log_error(NGX_LOG_NOTICE, log, 0,
+                  "cpuset_setaffinity(0x%08Xl)", cpu_affinity);
+
+    CPU_ZERO(&mask);
+    i = 0;
+    do {
+        if (cpu_affinity & 1) {
+            CPU_SET(i, &mask);
+        }
+        i++;
+        cpu_affinity >>= 1;
+    } while (cpu_affinity);
+
+    if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,
+                           sizeof(cpuset_t), &mask) == -1)
+    {
+        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                      "cpuset_setaffinity() failed");
+    }
+}
+
+#elif (NGX_HAVE_SCHED_SETAFFINITY)
+
+void
+ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log)
+{
+    cpu_set_t   mask;
+    ngx_uint_t  i;
+
+    ngx_log_error(NGX_LOG_NOTICE, log, 0,
+                  "sched_setaffinity(0x%08Xl)", cpu_affinity);
+
+    CPU_ZERO(&mask);
+    i = 0;
+    do {
+        if (cpu_affinity & 1) {
+            CPU_SET(i, &mask);
+        }
+        i++;
+        cpu_affinity >>= 1;
+    } while (cpu_affinity);
+
+    if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                      "sched_setaffinity() failed");
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/os/unix/ngx_setaffinity.h	Wed Mar 28 00:00:00 2012 +0400
@@ -0,0 +1,23 @@
+
+/*
+ * Copyright (C) Nginx, Inc.
+ */
+
+#ifndef _NGX_SETAFFINITY_H_INCLUDED_
+#define _NGX_SETAFFINITY_H_INCLUDED_
+
+
+#if (NGX_HAVE_SCHED_SETAFFINITY || NGX_HAVE_CPUSET_SETAFFINITY)
+
+#define NGX_HAVE_CPU_AFFINITY 1
+
+void ngx_setaffinity(uint64_t cpu_affinity, ngx_log_t *log);
+
+#else
+
+#define ngx_setaffinity(cpu_affinity, log)
+
+#endif
+
+
+#endif /* _NGX_SETAFFINITY_H_INCLUDED_ */
--- a/src/os/unix/ngx_solaris_config.h	Thu Mar 15 00:00:00 2012 +0400
+++ b/src/os/unix/ngx_solaris_config.h	Wed Mar 28 00:00:00 2012 +0400
@@ -29,6 +29,7 @@
 #include <grp.h>
 #include <dirent.h>
 #include <glob.h>
+#include <time.h>
 #include <sys/statvfs.h>        /* statvfs() */
 
 #include <sys/filio.h>          /* FIONBIO */