changeset 384:12defd37f578 NGINX_0_7_4

nginx 0.7.4 *) Feature: variables support in the "access_log" directive. *) Feature: the "open_log_file_cache" directive. *) Feature: the -g switch. *) Feature: the "Expect" request header line support. *) Bugfix: large SSI inclusions might be truncated.
author Igor Sysoev <http://sysoev.ru>
date Mon, 30 Jun 2008 00:00:00 +0400
parents 6ee3ada01457
children 08118f73d9f2
files CHANGES CHANGES.ru src/core/nginx.c src/core/nginx.h src/core/ngx_conf_file.c src/core/ngx_conf_file.h src/core/ngx_cycle.c src/core/ngx_cycle.h src/core/ngx_open_file_cache.c src/core/ngx_open_file_cache.h src/event/modules/ngx_epoll_module.c src/event/modules/ngx_select_module.c src/event/ngx_event.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_log_module.c src/http/modules/ngx_http_proxy_module.c src/http/modules/ngx_http_static_module.c src/http/modules/perl/nginx.pm src/http/modules/perl/nginx.xs src/http/ngx_http_core_module.c src/http/ngx_http_postpone_filter_module.c src/http/ngx_http_request.c src/http/ngx_http_request.h src/http/ngx_http_script.c src/mail/ngx_mail_auth_http_module.c
diffstat 27 files changed, 603 insertions(+), 143 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,17 @@
 
+Changes with nginx 0.7.4                                         30 Jun 2008
+
+    *) Feature: variables support in the "access_log" directive.
+
+    *) Feature: the "open_log_file_cache" directive.
+
+    *) Feature: the -g switch.
+
+    *) Feature: the "Expect" request header line support.
+
+    *) Bugfix: large SSI inclusions might be truncated.
+
+
 Changes with nginx 0.7.3                                         23 Jun 2008
 
     *) Change: the "rss" extension MIME type has been changed to 
@@ -912,13 +925,13 @@ Changes with nginx 0.5.13               
        send timeout only.
 
     *) Bugfix: nginx could not be built on platforms different from i386, 
-       amd64, sparc and ppc; the bug had appeared in 0.5.8.
+       amd64, sparc, and ppc; the bug had appeared in 0.5.8.
 
 
 Changes with nginx 0.5.12                                        12 Feb 2007
 
     *) Bugfix: nginx could not be built on platforms different from i386, 
-       amd64, sparc и ppc; the bug had appeared in 0.5.8.
+       amd64, sparc, and ppc; the bug had appeared in 0.5.8.
 
     *) Bugfix: a segmentation fault might occur in worker process if the 
        temporarily files were used while working with FastCGI server; the 
@@ -1624,7 +1637,8 @@ Changes with nginx 0.3.45               
     *) Change: the &deg; symbol codes were changed in koi-win conversion 
        table.
 
-    *) Feature: the euro и N symbols were added to koi-win conversion table.
+    *) Feature: the euro and N symbols were added to koi-win conversion 
+       table.
 
     *) Bugfix: if nginx distributed the requests among several backends and 
        some backend failed, then requests intended for this backend was 
@@ -2231,7 +2245,7 @@ Changes with nginx 0.3.7                
     *) Feature: the "access_log" supports the "buffer=" parameter.
 
     *) Bugfix: nginx could not be built on platforms different from i386, 
-       amd64, sparc и ppc; the bug had appeared in 0.3.2.
+       amd64, sparc, and ppc; the bug had appeared in 0.3.2.
 
 
 Changes with nginx 0.3.6                                         24 Oct 2005
@@ -2920,7 +2934,7 @@ Changes with nginx 0.1.23               
        server name of the "server_name" directive.
 
     *) Bugfix: nginx could not be built on platforms different from i386, 
-       amd64, sparc и ppc; the bug had appeared in 0.1.22.
+       amd64, sparc, and ppc; the bug had appeared in 0.1.22.
 
     *) Bugfix: the ngx_http_autoindex_module now shows the information not 
        about the symlink, but about file or directory it points to.
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,17 @@
 
+Изменения в nginx 0.7.4                                           30.06.2008
+
+    *) Добавление: директива access_log поддерживает переменные.
+
+    *) Добавление: директива open_log_file_cache.
+
+    *) Добавление: ключ -g.
+
+    *) Добавление: поддержка строки "Expect" в заголовке запроса.
+
+    *) Исправление: большие включения в SSI могли передавались не полностью.
+
+
 Изменения в nginx 0.7.3                                           23.06.2008
 
     *) Изменение: MIME-тип для расширения rss изменён на 
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -637,8 +637,7 @@ ngx_getopt(ngx_cycle_t *cycle, int argc,
         case 'c':
             if (argv[i + 1] == NULL) {
                 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
-                              "the option: \"%s\" requires file name",
-                              argv[i]);
+                              "the option \"-c\" requires file name");
                 return NGX_ERROR;
             }
 
@@ -646,6 +645,17 @@ ngx_getopt(ngx_cycle_t *cycle, int argc,
             cycle->conf_file.len = ngx_strlen(cycle->conf_file.data);
             break;
 
+        case 'g':
+            if (argv[i + 1] == NULL) {
+                ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
+                              "the option \"-g\" requires parameter");
+                return NGX_ERROR;
+            }
+
+            cycle->conf_param.data = (u_char *) argv[++i];
+            cycle->conf_param.len = ngx_strlen(cycle->conf_param.data);
+            break;
+
         default:
             ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
                           "invalid option: \"%s\"", argv[i]);
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VERSION      "0.7.3"
+#define NGINX_VERSION      "0.7.4"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -58,14 +58,52 @@ static int argument_number[] = {
 
 
 char *
+ngx_conf_param(ngx_conf_t *cf)
+{
+    ngx_str_t        *param;
+    ngx_buf_t         b;
+    ngx_conf_file_t   conf_file;
+
+    param = &cf->cycle->conf_param;
+
+    if (param->len == 0) {
+        return NGX_CONF_OK;
+    }
+
+    ngx_memzero(&conf_file, sizeof(ngx_conf_file_t));
+
+    ngx_memzero(&b, sizeof(ngx_buf_t));
+
+    b.start = param->data;
+    b.pos = param->data;
+    b.last = param->data + param->len;
+    b.end = b.last;
+    b.temporary = 1;
+
+    conf_file.file.fd = NGX_INVALID_FILE;
+    conf_file.file.name.data = (u_char *) "command line";
+    conf_file.line = 1;
+
+    cf->conf_file = &conf_file;
+    cf->conf_file->buffer = &b;
+
+    return ngx_conf_parse(cf, NULL);
+}
+
+
+char *
 ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
 {
     char             *rv;
     ngx_fd_t          fd;
     ngx_int_t         rc;
     ngx_buf_t        *b;
-    ngx_uint_t        block;
     ngx_conf_file_t  *prev;
+    enum {
+        parse_file = 0,
+        parse_block,
+        parse_param
+    } type;
 
 #if (NGX_SUPPRESS_WARN)
     fd = NGX_INVALID_FILE;
@@ -120,10 +158,14 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t
         cf->conf_file->file.log = cf->log;
         cf->conf_file->line = 1;
 
-        block = 0;
+        type = parse_file;
+
+    } else if (cf->conf_file->file.fd != NGX_INVALID_FILE) {
+
+        type = parse_block;
 
     } else {
-        block = 1;
+        type = parse_param;
     }
 
 
@@ -145,24 +187,38 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t
         }
 
         if (rc == NGX_CONF_BLOCK_DONE) {
-            if (!block) {
+
+            if (type != parse_block) {
                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\"");
                 goto failed;
             }
 
-            block = 0;
+            goto done;
         }
 
-        if (rc == NGX_CONF_FILE_DONE && block) {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "unexpected end of file, expecting \"}\"");
-            goto failed;
+        if (rc == NGX_CONF_FILE_DONE) {
+
+            if (type == parse_block) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                   "unexpected end of file, expecting \"}\"");
+                goto failed;
+            }
+
+            goto done;
         }
 
-        if (rc != NGX_OK && rc != NGX_CONF_BLOCK_START) {
-            goto done;
+        if (rc == NGX_CONF_BLOCK_START) {
+
+            if (type == parse_param) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                   "block directives are not supported "
+                                   "in -g option");
+                goto failed;
+            }
         }
 
+        /* rc == NGX_OK || rc == NGX_CONF_BLOCK_START */
+
         if (cf->handler) {
 
             /*
@@ -398,10 +454,19 @@ ngx_conf_read_token(ngx_conf_t *cf)
     for ( ;; ) {
 
         if (b->pos >= b->last) {
+
             if (cf->conf_file->file.offset
                                  >= ngx_file_size(&cf->conf_file->file.info))
             {
                 if (cf->args->nelts > 0) {
+
+                    if (cf->conf_file->file.fd == NGX_INVALID_FILE) {
+                        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                           "unexpected end of parameter, "
+                                           "expecting \";\"");
+                        return NGX_ERROR;
+                    }
+
                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                   "unexpected end of file, "
                                   "expecting \";\" or \"}\"");
--- a/src/core/ngx_conf_file.h
+++ b/src/core/ngx_conf_file.h
@@ -317,6 +317,7 @@ char *ngx_conf_check_num_bounds(ngx_conf
 #define addressof(addr)  ((int) &addr)
 
 
+char *ngx_conf_param(ngx_conf_t *cf);
 char *ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename);
 
 
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -90,6 +90,16 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
                 old_cycle->conf_file.len + 1);
 
 
+    cycle->conf_param.len = old_cycle->conf_param.len;
+    cycle->conf_param.data = ngx_pnalloc(pool, old_cycle->conf_param.len);
+    if (cycle->conf_param.data == NULL) {
+        ngx_destroy_pool(pool);
+        return NULL;
+    }
+    ngx_memcpy(cycle->conf_param.data, old_cycle->conf_param.data,
+               old_cycle->conf_param.len);
+
+
     n = old_cycle->pathes.nelts ? old_cycle->pathes.nelts : 10;
 
     cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *));
@@ -238,6 +248,11 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
     log->log_level = NGX_LOG_DEBUG_ALL;
 #endif
 
+    if (ngx_conf_param(&conf) != NGX_CONF_OK) {
+        ngx_destroy_cycle_pools(&conf);
+        return NULL;
+    }
+
     if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) {
         ngx_destroy_cycle_pools(&conf);
         return NULL;
--- a/src/core/ngx_cycle.h
+++ b/src/core/ngx_cycle.h
@@ -60,6 +60,7 @@ struct ngx_cycle_s {
     ngx_cycle_t              *old_cycle;
 
     ngx_str_t                 conf_file;
+    ngx_str_t                 conf_param;
     ngx_str_t                 root;
     ngx_str_t                 lock_file;
     ngx_str_t                 hostname;
--- a/src/core/ngx_open_file_cache.c
+++ b/src/core/ngx_open_file_cache.c
@@ -135,6 +135,7 @@ ngx_open_cached_file(ngx_open_file_cache
     ngx_pool_cleanup_file_t        *clnf;
     ngx_open_file_cache_cleanup_t  *ofcln;
 
+    of->fd = NGX_INVALID_FILE;
     of->err = 0;
 
     if (cache == NULL) {
@@ -188,8 +189,10 @@ ngx_open_cached_file(ngx_open_file_cache
             goto add_event;
         }
 
-        if ((file->event && file->use_event)
-            || (file->event == NULL && now - file->created < of->valid))
+        if (file->use_event
+            || (file->event == NULL
+                && (of->uniq == 0 || of->uniq == file->uniq)
+                && now - file->created < of->valid))
         {
             if (file->err == 0) {
 
@@ -230,6 +233,9 @@ ngx_open_cached_file(ngx_open_file_cache
             of->test_dir = 1;
         }
 
+        of->fd = file->fd;
+        of->uniq = file->uniq;
+
         rc = ngx_open_and_stat_file(name->data, of, pool->log);
 
         if (rc != NGX_OK && (of->err == 0 || !of->errors)) {
@@ -250,26 +256,14 @@ ngx_open_cached_file(ngx_open_file_cache
                 goto add_event;
             }
 
-            if (of->uniq == file->uniq
-                && of->mtime == file->mtime
-                && of->size == file->size)
-            {
-                if (ngx_close_file(of->fd) == NGX_FILE_ERROR) {
-                    ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
-                                  ngx_close_file_n " \"%s\" failed",
-                                  name->data);
-                }
+            if (of->uniq == file->uniq) {
 
-                of->fd = file->fd;
                 file->count++;
 
                 if (file->event) {
                     file->use_event = 1;
-                    goto renew;
                 }
 
-                ngx_open_file_add_event(cache, file, of, pool->log);
-
                 goto renew;
             }
 
@@ -344,7 +338,6 @@ create:
 
     file->uses = 1;
     file->count = 0;
-    file->use_event = 0;
     file->event = NULL;
 
 add_event:
@@ -446,34 +439,38 @@ ngx_open_and_stat_file(u_char *name, ngx
     ngx_fd_t         fd;
     ngx_file_info_t  fi;
 
-    of->fd = NGX_INVALID_FILE;
-
-    if (of->test_dir) {
+    if (of->fd != NGX_INVALID_FILE) {
 
         if (ngx_file_info(name, &fi) == -1) {
-            of->err = ngx_errno;
-
-            return NGX_ERROR;
+            goto failed;
         }
 
-        of->uniq = ngx_file_uniq(&fi);
-        of->mtime = ngx_file_mtime(&fi);
-        of->size = ngx_file_size(&fi);
-        of->is_dir = ngx_is_dir(&fi);
-        of->is_file = ngx_is_file(&fi);
-        of->is_link = ngx_is_link(&fi);
-        of->is_exec = ngx_is_exec(&fi);
+        if (of->uniq == ngx_file_uniq(&fi)) {
+            goto done;
+        }
+
+    } else if (of->test_dir) {
+
+        if (ngx_file_info(name, &fi) == -1) {
+            goto failed;
+        }
 
         if (of->is_dir) {
-            return NGX_OK;
+            goto done;
         }
     }
 
-    fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
+    if (!of->log) {
+        fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
+
+    } else {
+        fd = ngx_open_file(name, NGX_FILE_RDWR,
+                           NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND,
+                           NGX_FILE_DEFAULT_ACCESS);
+    }
 
     if (fd == NGX_INVALID_FILE) {
-        of->err = ngx_errno;
-        return NGX_ERROR;
+        goto failed;
     }
 
     if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
@@ -485,6 +482,8 @@ ngx_open_and_stat_file(u_char *name, ngx
                           ngx_close_file_n " \"%s\" failed", name);
         }
 
+        of->fd = NGX_INVALID_FILE;
+
         return NGX_ERROR;
     }
 
@@ -494,10 +493,14 @@ ngx_open_and_stat_file(u_char *name, ngx
                           ngx_close_file_n " \"%s\" failed", name);
         }
 
-        fd = NGX_INVALID_FILE;
+        of->fd = NGX_INVALID_FILE;
+
+    } else {
+        of->fd = fd;
     }
 
-    of->fd = fd;
+done:
+
     of->uniq = ngx_file_uniq(&fi);
     of->mtime = ngx_file_mtime(&fi);
     of->size = ngx_file_size(&fi);
@@ -507,6 +510,13 @@ ngx_open_and_stat_file(u_char *name, ngx
     of->is_exec = ngx_is_exec(&fi);
 
     return NGX_OK;
+
+failed:
+
+    of->fd = NGX_INVALID_FILE;
+    of->err = ngx_errno;
+
+    return NGX_ERROR;
 }
 
 
@@ -530,6 +540,8 @@ ngx_open_file_add_event(ngx_open_file_ca
         return;
     }
 
+    file->use_event = 0;
+
     file->event = ngx_calloc(sizeof(ngx_event_t), log);
     if (file->event== NULL) {
         return;
@@ -567,9 +579,10 @@ ngx_open_file_add_event(ngx_open_file_ca
     }
 
     /*
-     * we do not file->use_event here because there may be a race
-     * condition between opening file and adding event, so we rely
-     * upon event notification only after first file revalidation
+     * we do not set file->use_event here because there may be a race
+     * condition: a file may be deleted between opening the file and
+     * adding event, so we rely upon event notification only after
+     * one file revalidation on next file access
      */
 
     return;
@@ -807,6 +820,7 @@ ngx_open_file_cache_remove(ngx_event_t *
 
     /* NGX_ONESHOT_EVENT was already deleted */
     file->event = NULL;
+    file->use_event = 0;
 
     file->close = 1;
 
--- a/src/core/ngx_open_file_cache.h
+++ b/src/core/ngx_open_file_cache.h
@@ -24,6 +24,7 @@ typedef struct {
     ngx_uint_t               min_uses;
 
     unsigned                 test_dir:1;
+    unsigned                 log:1;
     unsigned                 errors:1;
     unsigned                 events:1;
 
--- a/src/event/modules/ngx_epoll_module.c
+++ b/src/event/modules/ngx_epoll_module.c
@@ -143,15 +143,12 @@ ngx_module_t  ngx_epoll_module = {
 static ngx_int_t
 ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
 {
-    ngx_event_conf_t  *ecf;
     ngx_epoll_conf_t  *epcf;
 
-    ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
-
     epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_module);
 
     if (ep == -1) {
-        ep = epoll_create(ecf->connections / 2);
+        ep = epoll_create(cycle->connection_n / 2);
 
         if (ep == -1) {
             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -436,10 +436,10 @@ ngx_select_init_conf(ngx_cycle_t *cycle,
 
 #if !(NGX_WIN32)
 
-    if ((unsigned) ecf->connections > FD_SETSIZE) {
+    if (cycle->connection_n > FD_SETSIZE) {
         ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
                       "the maximum number of files "
-                      "supported by select() is " ngx_value(FD_SETSIZE));
+                      "supported by select() is %ud", FD_SETSIZE);
         return NGX_CONF_ERROR;
     }
 
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -596,22 +596,23 @@ ngx_event_process_init(ngx_cycle_t *cycl
         return NGX_ERROR;
     }
 
-    cycle->connection_n = ecf->connections;
-
     for (m = 0; ngx_modules[m]; m++) {
         if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
             continue;
         }
 
-        if (ngx_modules[m]->ctx_index == ecf->use) {
-            module = ngx_modules[m]->ctx;
-            if (module->actions.init(cycle, ngx_timer_resolution) == NGX_ERROR)
-            {
-                /* fatal */
-                exit(2);
-            }
-            break;
+        if (ngx_modules[m]->ctx_index != ecf->use) {
+            continue;
         }
+
+        module = ngx_modules[m]->ctx;
+
+        if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {
+            /* fatal */
+            exit(2);
+        }
+
+        break;
     }
 
 #if !(NGX_WIN32)
@@ -661,15 +662,15 @@ ngx_event_process_init(ngx_cycle_t *cycl
 
 #endif
 
-    cycle->connections = ngx_alloc(sizeof(ngx_connection_t) * ecf->connections,
-                                   cycle->log);
+    cycle->connections =
+        ngx_alloc(sizeof(ngx_connection_t) * cycle->connection_n, cycle->log);
     if (cycle->connections == NULL) {
         return NGX_ERROR;
     }
 
     c = cycle->connections;
 
-    cycle->read_events = ngx_alloc(sizeof(ngx_event_t) * ecf->connections,
+    cycle->read_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,
                                    cycle->log);
     if (cycle->read_events == NULL) {
         return NGX_ERROR;
@@ -685,7 +686,7 @@ ngx_event_process_init(ngx_cycle_t *cycl
 #endif
     }
 
-    cycle->write_events = ngx_alloc(sizeof(ngx_event_t) * ecf->connections,
+    cycle->write_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,
                                     cycle->log);
     if (cycle->write_events == NULL) {
         return NGX_ERROR;
@@ -719,7 +720,7 @@ ngx_event_process_init(ngx_cycle_t *cycl
     } while (i);
 
     cycle->free_connections = next;
-    cycle->free_connection_n = ecf->connections;
+    cycle->free_connection_n = cycle->connection_n;
 
     /* for each listening socket */
 
@@ -1137,11 +1138,10 @@ ngx_event_init_conf(ngx_cycle_t *cycle, 
     ngx_uint_t           rtsig;
     ngx_core_conf_t     *ccf;
 #endif
-    ngx_int_t            i, connections;
+    ngx_int_t            i;
     ngx_module_t        *module;
     ngx_event_module_t  *event_module;
 
-    connections = NGX_CONF_UNSET_UINT;
     module = NULL;
 
 #if (NGX_HAVE_EPOLL) && !(NGX_TEST_BUILD_EPOLL)
@@ -1150,11 +1150,9 @@ ngx_event_init_conf(ngx_cycle_t *cycle, 
 
     if (fd != -1) {
         close(fd);
-        connections = DEFAULT_CONNECTIONS;
         module = &ngx_epoll_module;
 
     } else if (ngx_errno != NGX_ENOSYS) {
-        connections = DEFAULT_CONNECTIONS;
         module = &ngx_epoll_module;
     }
 
@@ -1163,7 +1161,6 @@ ngx_event_init_conf(ngx_cycle_t *cycle, 
 #if (NGX_HAVE_RTSIG)
 
     if (module == NULL) {
-        connections = DEFAULT_CONNECTIONS;
         module = &ngx_rtsig_module;
         rtsig = 1;
 
@@ -1175,14 +1172,12 @@ ngx_event_init_conf(ngx_cycle_t *cycle, 
 
 #if (NGX_HAVE_DEVPOLL)
 
-    connections = DEFAULT_CONNECTIONS;
     module = &ngx_devpoll_module;
 
 #endif
 
 #if (NGX_HAVE_KQUEUE)
 
-    connections = DEFAULT_CONNECTIONS;
     module = &ngx_kqueue_module;
 
 #endif
@@ -1190,12 +1185,6 @@ ngx_event_init_conf(ngx_cycle_t *cycle, 
 #if (NGX_HAVE_SELECT)
 
     if (module == NULL) {
-
-#if (NGX_WIN32 || FD_SETSIZE >= DEFAULT_CONNECTIONS)
-        connections = DEFAULT_CONNECTIONS;
-#else
-        connections = FD_SETSIZE;
-#endif
         module = &ngx_select_module;
     }
 
@@ -1203,18 +1192,20 @@ ngx_event_init_conf(ngx_cycle_t *cycle, 
 
     if (module == NULL) {
         for (i = 0; ngx_modules[i]; i++) {
-            if (ngx_modules[i]->type == NGX_EVENT_MODULE) {
-                event_module = ngx_modules[i]->ctx;
+
+            if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
+                continue;
+            }
+
+            event_module = ngx_modules[i]->ctx;
 
-                if (ngx_strcmp(event_module->name->data, event_core_name.data)
-                    == 0)
-                {
-                    continue;
-                }
+            if (ngx_strcmp(event_module->name->data, event_core_name.data) == 0)
+            {
+                continue;
+            }
 
-                module = ngx_modules[i];
-                break;
-            }
+            module = ngx_modules[i];
+            break;
         }
     }
 
@@ -1223,7 +1214,7 @@ ngx_event_init_conf(ngx_cycle_t *cycle, 
         return NGX_CONF_ERROR;
     }
 
-    ngx_conf_init_uint_value(ecf->connections, connections);
+    ngx_conf_init_uint_value(ecf->connections, DEFAULT_CONNECTIONS);
     cycle->connection_n = ecf->connections;
 
     ngx_conf_init_uint_value(ecf->use, module->ctx_index);
--- a/src/http/modules/ngx_http_flv_module.c
+++ b/src/http/modules/ngx_http_flv_module.c
@@ -105,7 +105,8 @@ ngx_http_flv_handler(ngx_http_request_t 
 
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
-    of.test_dir = 0;
+    ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+
     of.valid = clcf->open_file_cache_valid;
     of.min_uses = clcf->open_file_cache_min_uses;
     of.errors = clcf->open_file_cache_errors;
--- a/src/http/modules/ngx_http_gzip_static_module.c
+++ b/src/http/modules/ngx_http_gzip_static_module.c
@@ -119,7 +119,8 @@ ngx_http_gzip_static_handler(ngx_http_re
 
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
-    of.test_dir = 0;
+    ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+
     of.valid = clcf->open_file_cache_valid;
     of.min_uses = clcf->open_file_cache_min_uses;
     of.errors = clcf->open_file_cache_errors;
--- a/src/http/modules/ngx_http_index_module.c
+++ b/src/http/modules/ngx_http_index_module.c
@@ -208,7 +208,8 @@ ngx_http_index_handler(ngx_http_request_
 
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "open index \"%V\"", &path);
 
-        of.test_dir = 0;
+        ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+
         of.valid = clcf->open_file_cache_valid;
         of.min_uses = clcf->open_file_cache_min_uses;
         of.errors = clcf->open_file_cache_errors;
@@ -291,9 +292,10 @@ ngx_http_index_test_dir(ngx_http_request
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http index check dir: \"%V\"", &dir);
 
+    ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+
     of.test_dir = 1;
     of.valid = clcf->open_file_cache_valid;
-    of.min_uses = 0;
     of.errors = clcf->open_file_cache_errors;
 
     if (ngx_open_cached_file(clcf->open_file_cache, &dir, &of, r->pool)
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -40,7 +40,14 @@ typedef struct {
 
 
 typedef struct {
+    ngx_array_t                *lengths;
+    ngx_array_t                *values;
+} ngx_http_log_script_t;
+
+
+typedef struct {
     ngx_open_file_t            *file;
+    ngx_http_log_script_t      *script;
     time_t                      disk_full_time;
     time_t                      error_log_time;
     ngx_array_t                *ops;        /* array of ngx_http_log_op_t */
@@ -49,6 +56,11 @@ typedef struct {
 
 typedef struct {
     ngx_array_t                *logs;       /* array of ngx_http_log_t */
+
+    ngx_open_file_cache_t      *open_file_cache;
+    time_t                      open_file_cache_valid;
+    ngx_uint_t                  open_file_cache_min_uses;
+
     ngx_uint_t                  off;        /* unsigned  off:1 */
 } ngx_http_log_loc_conf_t;
 
@@ -62,6 +74,8 @@ typedef struct {
 
 static void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log,
     u_char *buf, size_t len);
+static ssize_t ngx_http_log_script_write(ngx_http_request_t *r,
+    ngx_http_log_script_t *script, u_char **name, u_char *buf, size_t len);
 
 static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf,
     ngx_http_log_op_t *op);
@@ -101,6 +115,8 @@ static char *ngx_http_log_set_format(ngx
     void *conf);
 static char *ngx_http_log_compile_format(ngx_conf_t *cf,
     ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s);
+static char *ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
 static ngx_int_t ngx_http_log_init(ngx_conf_t *cf);
 
 
@@ -121,6 +137,13 @@ static ngx_command_t  ngx_http_log_comma
       0,
       NULL },
 
+    { ngx_string("open_log_file_cache"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
+      ngx_http_log_open_file_cache,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
       ngx_null_command
 };
 
@@ -235,7 +258,7 @@ ngx_http_log_handler(ngx_http_request_t 
 
         file = log[l].file;
 
-        if (file->buffer) {
+        if (file && file->buffer) {
 
             if (len > (size_t) (file->last - file->pos)) {
 
@@ -285,11 +308,19 @@ static void
 ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf,
     size_t len)
 {
-    time_t     now;
-    ssize_t    n;
-    ngx_err_t  err;
+    u_char     *name;
+    time_t      now;
+    ssize_t     n;
+    ngx_err_t   err;
 
-    n = ngx_write_fd(log->file->fd, buf, len);
+    if (log->script == NULL) {
+        name = log->file->name.data;
+        n = ngx_write_fd(log->file->fd, buf, len);
+
+    } else {
+        name = NULL;
+        n = ngx_http_log_script_write(r, log->script, &name, buf, len);
+    }
 
     if (n == (ssize_t) len) {
         return;
@@ -306,8 +337,7 @@ ngx_http_log_write(ngx_http_request_t *r
 
         if (now - log->error_log_time > 59) {
             ngx_log_error(NGX_LOG_ALERT, r->connection->log, err,
-                          ngx_write_fd_n " to \"%V\" failed",
-                          &log->file->name);
+                          ngx_write_fd_n " to \"%s\" failed", name);
 
             log->error_log_time = now;
         }
@@ -317,14 +347,93 @@ ngx_http_log_write(ngx_http_request_t *r
 
     if (now - log->error_log_time > 59) {
         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                      ngx_write_fd_n " to \"%V\" was incomplete: %z of %uz",
-                      &log->file->name, n, len);
+                      ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
+                      name, n, len);
 
         log->error_log_time = now;
     }
 }
 
 
+static ssize_t
+ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
+    u_char **name, u_char *buf, size_t len)
+{
+    size_t                     root;
+    ssize_t                    n;
+    ngx_str_t                  log, path;
+    ngx_open_file_info_t       of;
+    ngx_http_log_loc_conf_t   *llcf;
+    ngx_http_core_loc_conf_t  *clcf;
+
+    if (r->err_status == NGX_HTTP_NOT_FOUND) {
+
+        /* test root directory existance */
+
+        if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
+            /* simulate successfull logging */
+            return len;
+        }
+
+        path.data[root] = '\0';
+
+        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+        ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+
+        of.valid = clcf->open_file_cache_valid;
+        of.min_uses = clcf->open_file_cache_min_uses;
+        of.errors = clcf->open_file_cache_errors;
+        of.events = clcf->open_file_cache_events;
+
+        if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
+                != NGX_OK
+            || !of.is_dir)
+        {
+            /* no root directory: simulate successfull logging */
+            return len;
+        }
+    }
+
+    if (ngx_http_script_run(r, &log, script->lengths->elts, 1,
+                            script->values->elts)
+        == NULL)
+    {
+        /* simulate successfull logging */
+        return len;
+    }
+
+    log.data[log.len - 1] = '\0';
+    *name = log.data;
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "http log \"%s\"", log.data);
+
+    llcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);
+
+    ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+
+    of.log = 1;
+    of.valid = llcf->open_file_cache_valid;
+    of.min_uses = llcf->open_file_cache_min_uses;
+
+    if (ngx_open_cached_file(llcf->open_file_cache, &log, &of, r->pool)
+        != NGX_OK)
+    {
+        ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
+                      ngx_open_file_n " \"%s\" failed", log.data);
+        return -1;
+    }
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "http log #%d", of.fd);
+
+    n = ngx_write_fd(of.fd, buf, len);
+
+    return n;
+}
+
+
 static u_char *
 ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf,
     ngx_http_log_op_t *op)
@@ -620,6 +729,8 @@ ngx_http_log_create_loc_conf(ngx_conf_t 
         return NGX_CONF_ERROR;
     }
 
+    conf->open_file_cache = NGX_CONF_UNSET_PTR;
+
     return conf;
 }
 
@@ -634,6 +745,17 @@ ngx_http_log_merge_loc_conf(ngx_conf_t *
     ngx_http_log_fmt_t        *fmt;
     ngx_http_log_main_conf_t  *lmcf;
 
+    if (conf->open_file_cache == NGX_CONF_UNSET_PTR) {
+
+        conf->open_file_cache = prev->open_file_cache;
+        conf->open_file_cache_valid = prev->open_file_cache_valid;
+        conf->open_file_cache_min_uses = prev->open_file_cache_min_uses;
+
+        if (conf->open_file_cache == NGX_CONF_UNSET_PTR) {
+            conf->open_file_cache = NULL;
+        }
+    }
+
     if (conf->logs || conf->off) {
         return NGX_CONF_OK;
     }
@@ -678,12 +800,13 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx
 {
     ngx_http_log_loc_conf_t *llcf = conf;
 
-    ssize_t                    buf;
-    ngx_uint_t                 i;
-    ngx_str_t                 *value, name;
-    ngx_http_log_t            *log;
-    ngx_http_log_fmt_t        *fmt;
-    ngx_http_log_main_conf_t  *lmcf;
+    ssize_t                     buf;
+    ngx_uint_t                  i, n;
+    ngx_str_t                  *value, name;
+    ngx_http_log_t             *log;
+    ngx_http_log_fmt_t         *fmt;
+    ngx_http_log_main_conf_t   *lmcf;
+    ngx_http_script_compile_t   sc;
 
     value = cf->args->elts;
 
@@ -706,14 +829,41 @@ ngx_http_log_set_log(ngx_conf_t *cf, ngx
         return NGX_CONF_ERROR;
     }
 
-    log->file = ngx_conf_open_file(cf->cycle, &value[1]);
-    if (log->file == NULL) {
-        return NGX_CONF_ERROR;
+    ngx_memzero(log, sizeof(ngx_http_log_t));
+
+    n = ngx_http_script_variables_count(&value[1]);
+
+    if (n == 0) {
+        log->file = ngx_conf_open_file(cf->cycle, &value[1]);
+        if (log->file == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+    } else {
+        if (ngx_conf_full_name(cf->cycle, &value[1], 0) == NGX_ERROR) {
+            return NGX_CONF_ERROR;
+        }
+
+        log->script = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_script_t));
+        if (log->script == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+
+        sc.cf = cf;
+        sc.source = &value[1];
+        sc.lengths = &log->script->lengths;
+        sc.values = &log->script->values;
+        sc.variables = n;
+        sc.complete_lengths = 1;
+        sc.complete_values = 1;
+
+        if (ngx_http_script_compile(&sc) != NGX_OK) {
+            return NGX_CONF_ERROR;
+        }
     }
 
-    log->disk_full_time = 0;
-    log->error_log_time = 0;
-
     if (cf->args->nelts >= 3) {
         name = value[2];
 
@@ -750,6 +900,12 @@ buffer:
             return NGX_CONF_ERROR;
         }
 
+        if (log->script) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "buffered logs can not have variables in name");
+            return NGX_CONF_ERROR;
+        }
+
         name.len = value[3].len - 7;
         name.data = value[3].data + 7;
 
@@ -992,6 +1148,114 @@ invalid:
 }
 
 
+static char *
+ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_log_loc_conf_t *llcf = conf;
+
+    time_t       inactive, valid;
+    ngx_str_t   *value, s;
+    ngx_int_t    max, min_uses;
+    ngx_uint_t   i;
+
+    if (llcf->open_file_cache != NGX_CONF_UNSET_PTR) {
+        return "is duplicate";
+    }
+
+    value = cf->args->elts;
+
+    max = 0;
+    inactive = 10;
+    valid = 60;
+    min_uses = 1;
+
+    for (i = 1; i < cf->args->nelts; i++) {
+
+        if (ngx_strncmp(value[i].data, "max=", 4) == 0) {
+
+            max = ngx_atoi(value[i].data + 4, value[i].len - 4);
+            if (max == NGX_ERROR) {
+                goto failed;
+            }
+
+            continue;
+        }
+
+        if (ngx_strncmp(value[i].data, "inactive=", 9) == 0) {
+
+            s.len = value[i].len - 9;
+            s.data = value[i].data + 9;
+
+            inactive = ngx_parse_time(&s, 1);
+            if (inactive < 0) {
+                goto failed;
+            }
+
+            continue;
+        }
+
+        if (ngx_strncmp(value[i].data, "min_uses=", 9) == 0) {
+
+            min_uses = ngx_atoi(value[i].data + 9, value[i].len - 9);
+            if (min_uses == NGX_ERROR) {
+                goto failed;
+            }
+
+            continue;
+        }
+
+        if (ngx_strncmp(value[i].data, "valid=", 6) == 0) {
+
+            s.len = value[i].len - 6;
+            s.data = value[i].data + 6;
+
+            valid = ngx_parse_time(&s, 1);
+            if (valid < 0) {
+                goto failed;
+            }
+
+            continue;
+        }
+
+        if (ngx_strcmp(value[i].data, "off") == 0) {
+
+            llcf->open_file_cache = NULL;
+
+            continue;
+        }
+
+    failed:
+
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "invalid \"open_log_file_cache\" parameter \"%V\"",
+                           &value[i]);
+        return NGX_CONF_ERROR;
+    }
+
+    if (llcf->open_file_cache == NULL) {
+        return NGX_CONF_OK;
+    }
+
+    if (max == 0) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                        "\"open_log_file_cache\" must have \"max\" parameter");
+        return NGX_CONF_ERROR;
+    }
+
+    llcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);
+
+    if (llcf->open_file_cache) {
+
+        llcf->open_file_cache_valid = valid;
+        llcf->open_file_cache_min_uses = min_uses;
+
+        return NGX_CONF_OK;
+    }
+
+    return NGX_CONF_ERROR;
+}
+
+
 static ngx_int_t
 ngx_http_log_init(ngx_conf_t *cf)
 {
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -402,6 +402,7 @@ static ngx_keyval_t  ngx_http_proxy_head
     { 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_null_string, ngx_null_string }
 };
 
--- a/src/http/modules/ngx_http_static_module.c
+++ b/src/http/modules/ngx_http_static_module.c
@@ -96,7 +96,8 @@ ngx_http_static_handler(ngx_http_request
 
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
-    of.test_dir = 0;
+    ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+
     of.valid = clcf->open_file_cache_valid;
     of.min_uses = clcf->open_file_cache_min_uses;
     of.errors = clcf->open_file_cache_errors;
--- 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.3';
+our $VERSION = '0.7.4';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -639,23 +639,24 @@ sendfile(r, filename, offset = -1, bytes
         XSRETURN_EMPTY;
     }
 
-    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
-    of.test_dir = 0;
-    of.valid = clcf->open_file_cache_valid;
-    of.min_uses = clcf->open_file_cache_min_uses;
-    of.errors = clcf->open_file_cache_errors;
-    of.events = clcf->open_file_cache_events;
-
     path.len = ngx_strlen(filename);
 
-    path.data = ngx_pcalloc(r->pool, path.len + 1);
+    path.data = ngx_pnalloc(r->pool, path.len + 1);
     if (path.data == NULL) {
         XSRETURN_EMPTY;
     }
 
     (void) ngx_cpystrn(path.data, filename, path.len + 1);
 
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+    ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+
+    of.valid = clcf->open_file_cache_valid;
+    of.min_uses = clcf->open_file_cache_min_uses;
+    of.errors = clcf->open_file_cache_errors;
+    of.events = clcf->open_file_cache_events;
+
     if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
         != NGX_OK)
     {
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -25,6 +25,7 @@ typedef struct {
 static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r);
 static ngx_int_t ngx_http_core_find_static_location(ngx_http_request_t *r,
     ngx_http_location_tree_node_t *node);
+static ngx_int_t ngx_http_core_send_continue(ngx_http_request_t *r);
 
 static ngx_int_t ngx_http_core_preconfiguration(ngx_conf_t *cf);
 static void *ngx_http_core_create_main_conf(ngx_conf_t *cf);
@@ -771,7 +772,7 @@ ngx_http_core_find_config_phase(ngx_http
 {
     u_char                    *p;
     size_t                     len;
-    ngx_int_t                  rc;
+    ngx_int_t                  rc, expect;
     ngx_http_core_loc_conf_t  *clcf;
 
     r->content_handler = NULL;
@@ -815,6 +816,15 @@ ngx_http_core_find_config_phase(ngx_http
         return NGX_OK;
     }
 
+    if (r->headers_in.expect) {
+        expect = ngx_http_core_send_continue(r);
+
+        if (expect != NGX_OK) {
+            ngx_http_finalize_request(r, expect);
+            return NGX_OK;
+        }
+    }
+
     if (rc == NGX_DONE) {
         r->headers_out.location = ngx_list_push(&r->headers_out.headers);
         if (r->headers_out.location == NULL) {
@@ -1244,6 +1254,45 @@ ngx_http_core_find_static_location(ngx_h
 }
 
 
+static ngx_int_t
+ngx_http_core_send_continue(ngx_http_request_t *r)
+{
+    ngx_int_t   n;
+    ngx_str_t  *expect;
+
+    if (r->expect_tested) {
+        return NGX_OK;
+    }
+
+    r->expect_tested = 1;
+
+    expect = &r->headers_in.expect->value;
+
+    if (expect->len != sizeof("100-continue") - 1
+        || ngx_strncasecmp(expect->data, (u_char *) "100-continue",
+                           sizeof("100-continue") - 1)
+           != 0)
+    {
+        return NGX_OK;
+    }
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "send 100 Continue");
+
+    n = r->connection->send(r->connection,
+                            (u_char *) "HTTP/1.1 100 Continue" CRLF CRLF,
+                            sizeof("HTTP/1.1 100 Continue" CRLF CRLF) - 1);
+
+    if (n == sizeof("HTTP/1.1 100 Continue" CRLF CRLF) - 1) {
+        return NGX_OK;
+    }
+
+    /* we assume that such small packet should be send successfully */
+
+    return NGX_HTTP_INTERNAL_SERVER_ERROR;
+}
+
+
 ngx_int_t
 ngx_http_set_content_type(ngx_http_request_t *r)
 {
--- a/src/http/ngx_http_postpone_filter_module.c
+++ b/src/http/ngx_http_postpone_filter_module.c
@@ -168,7 +168,7 @@ ngx_http_postpone_filter_output_postpone
         pr = r->postponed;
 
         if (pr == NULL) {
-            return NGX_OK;
+            break;
         }
 
         if (pr->request) {
@@ -196,7 +196,7 @@ ngx_http_postpone_filter_output_postpone
         }
 
         if (pr == NULL) {
-            return NGX_OK;
+            break;
         }
 
         out = pr->out;
@@ -215,6 +215,17 @@ ngx_http_postpone_filter_output_postpone
 
         r->postponed = r->postponed->next;
     }
+
+    if (r->out) {
+        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "http postpone filter out again \"%V?%V\"",
+                       &r->uri, &r->args);
+
+        r->connection->data = r;
+        return NGX_AGAIN;
+    }
+
+    return NGX_OK;
 }
 
 
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -106,6 +106,10 @@ ngx_http_header_t  ngx_http_headers_in[]
                  offsetof(ngx_http_headers_in_t, transfer_encoding),
                  ngx_http_process_header_line },
 
+    { ngx_string("Expect"),
+                 offsetof(ngx_http_headers_in_t, expect),
+                 ngx_http_process_unique_header_line },
+
 #if (NGX_HTTP_GZIP)
     { ngx_string("Accept-Encoding"),
                  offsetof(ngx_http_headers_in_t, accept_encoding),
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -171,6 +171,7 @@ typedef struct {
     ngx_table_elt_t                  *if_range;
 
     ngx_table_elt_t                  *transfer_encoding;
+    ngx_table_elt_t                  *expect;
 
 #if (NGX_HTTP_GZIP)
     ngx_table_elt_t                  *accept_encoding;
@@ -467,6 +468,7 @@ struct ngx_http_request_s {
     unsigned                          request_complete:1;
     unsigned                          request_output:1;
     unsigned                          header_sent:1;
+    unsigned                          expect_tested:1;
     unsigned                          done:1;
     unsigned                          utf8:1;
 
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -994,7 +994,8 @@ ngx_http_script_file_code(ngx_http_scrip
 
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
-    of.test_dir = 0;
+    ngx_memzero(&of, sizeof(ngx_open_file_info_t));
+
     of.valid = clcf->open_file_cache_valid;
     of.min_uses = clcf->open_file_cache_min_uses;
     of.errors = clcf->open_file_cache_errors;
--- a/src/mail/ngx_mail_auth_http_module.c
+++ b/src/mail/ngx_mail_auth_http_module.c
@@ -528,7 +528,7 @@ ngx_mail_auth_http_process_headers(ngx_m
                     continue;
                 }
 
-                p = ngx_pcalloc(s->connection->pool, size);
+                p = ngx_pnalloc(s->connection->pool, size);
                 if (p == NULL) {
                     ngx_close_connection(ctx->peer.connection);
                     ngx_destroy_pool(ctx->pool);