changeset 32:da8c190bdaba NGINX_0_1_16

nginx 0.1.16 *) Bugfix: if the response were transferred by chunks, then on the HEAD request the final chunk was issued. *) Bugfix: the "Connection: keep-alive" header were issued, even if the keepalive_timeout directive forbade the keep-alive use. *) Bugfix: the errors in the ngx_http_fastcgi_module caused the segmentation faults. *) Bugfix: the compressed response encrypted by SSL may not transferred complete. *) Bugfix: the TCP-specific TCP_NODELAY, TCP_NOPSUH, and TCP_CORK options, are not used for the unix domain sockets. *) Feature: the rewrite directive supports the arguments rewriting. *) Bugfix: the response code 400 was returned for the POST request with the "Content-Length: 0" header; bug appeared in 0.1.14.
author Igor Sysoev <http://sysoev.ru>
date Tue, 25 Jan 2005 00:00:00 +0300
parents 1b17dd824438
children 27f09a550803
files CHANGES CHANGES.ru auto/sources src/core/nginx.h src/core/ngx_conf_file.c src/core/ngx_connection.c src/core/ngx_connection.h src/core/ngx_log.c src/core/ngx_log.h src/core/ngx_output_chain.c src/event/modules/ngx_devpoll_module.c src/event/modules/ngx_epoll_module.c src/event/modules/ngx_poll_module.c src/event/ngx_event.c src/event/ngx_event_accept.c src/event/ngx_event_connect.c src/event/ngx_event_pipe.c src/event/ngx_event_pipe.h src/http/modules/ngx_http_chunked_filter.c src/http/modules/ngx_http_fastcgi_handler.c src/http/modules/ngx_http_gzip_filter.c src/http/modules/ngx_http_rewrite_handler.c src/http/modules/ngx_http_static_handler.c src/http/modules/proxy/ngx_http_proxy_handler.c src/http/modules/proxy/ngx_http_proxy_handler.h src/http/ngx_http.h src/http/ngx_http_core_module.c src/http/ngx_http_request.c src/http/ngx_http_upstream.c src/http/ngx_http_upstream.h src/http/ngx_http_write_filter.c src/os/unix/ngx_channel.c src/os/unix/ngx_freebsd_sendfile_chain.c src/os/unix/ngx_linux_sendfile_chain.c src/os/unix/rfork_thread.S
diffstat 35 files changed, 678 insertions(+), 498 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,26 @@
+
+Changes with nginx 0.1.16                                        25 Jan 2005
+
+    *) Bugfix: if the response were transferred by chunks, then on the HEAD 
+       request the final chunk was issued.
+
+    *) Bugfix: the "Connection: keep-alive" header were issued, even if the 
+       keepalive_timeout derective forbade the keep-alive use.
+
+    *) Bugfix: the errors in the ngx_http_fastcgi_module caused the 
+       segmentation faults.
+
+    *) Bugfix: the compressed response encrypted by SSL may not transferred 
+       complete.
+
+    *) Bugfix: the TCP-specific TCP_NODELAY, TCP_NOPSUH, and TCP_CORK 
+       options, are not used for the unix domain sockets.
+
+    *) Feature: the rewrite directive supports the agruments rewriting.
+
+    *) Bugfix: the response code 400 was returend for the POST request with 
+       the "Content-Length: 0" header; bug appeared in 0.1.14.
+
 
 Changes with nginx 0.1.15                                        19 Jan 2005
 
@@ -13,16 +36,17 @@ Changes with nginx 0.1.15               
     *) Bugfix: the FastCGI's parameter REQUEST_URI is now passed with the 
        arguments and in the original state.
 
-    *) Bugfix: the ngx_http_rewrite_module module was required to be built to 
-       use the regular expressions in locations.
+    *) Bugfix: the ngx_http_rewrite_module module was required to be built 
+       to use the regular expressions in locations.
 
     *) Bugfix: the directive "proxy_preserve_host  on" adds port 80 to the 
-       "Host" headers, if upstream listen on port 80; bug appeared in 0.1.14.
+       "Host" headers, if upstream listen on port 80; bug appeared in 
+       0.1.14.
 
     *) Bugfix: the same pathes in autoconfiguration paramters 
-       --http-client-body-temp-path=PATH and --http-proxy-temp-path=PATH, or 
-       --http-client-body-temp-path=PATH nad --http-fastcgi-temp-path=PATH 
-       caused segmentation fault.
+       --http-client-body-temp-path=PATH and --http-proxy-temp-path=PATH, 
+       or --http-client-body-temp-path=PATH nad 
+       --http-fastcgi-temp-path=PATH caused segmentation fault.
 
 
 Changes with nginx 0.1.14                                        18 Jan 2005
@@ -35,10 +59,10 @@ Changes with nginx 0.1.14               
        request body is specified by directive client_body_temp_path, by 
        default it is <prefix>/client_body_temp.
 
-    *) Feature: the ngx_http_fastcgi_module and the directives: fastcgi_pass, 
-       fastcgi_root, fastcgi_index, fastcgi_params, fastcgi_connect_timeout, 
-       fastcgi_send_timeout, fastcgi_read_timeout, fastcgi_send_lowat, 
-       fastcgi_header_buffer_size, fastcgi_buffers, 
+    *) Feature: the ngx_http_fastcgi_module and the directives: 
+       fastcgi_pass, fastcgi_root, fastcgi_index, fastcgi_params, 
+       fastcgi_connect_timeout, fastcgi_send_timeout, fastcgi_read_timeout, 
+       fastcgi_send_lowat, fastcgi_header_buffer_size, fastcgi_buffers, 
        fastcgi_busy_buffers_size, fastcgi_temp_path, 
        fastcgi_max_temp_file_size, fastcgi_temp_file_write_size, 
        fastcgi_next_upstream, and fastcgi_x_powered_by.
@@ -51,7 +75,8 @@ Changes with nginx 0.1.14               
     *) Change: the %3F symbol in the URI was considered as the argument 
        string start.
 
-    *) Feature: the unix domain sockets support in the ngx_http_proxy_module.
+    *) Feature: the unix domain sockets support in the 
+       ngx_http_proxy_module.
 
     *) Feature: the ssl_engine and ssl_ciphers directives.
        Thanks to Sergey Skvortsov for SSL-accelerator.
@@ -65,7 +90,8 @@ Changes with nginx 0.1.13               
     *) Bugfix: the *.domain.tld names in the server_name directive did not 
        work.
 
-    *) Bugfix: the %request_length log parameter logged the incorrect length.
+    *) Bugfix: the %request_length log parameter logged the incorrect 
+       length.
 
 
 Changes with nginx 0.1.12                                        06 Dec 2004
@@ -100,9 +126,9 @@ Changes with nginx 0.1.11               
     *) Bugfix: the files bigger than 4G could not be transferred using 
        sendfile.
 
-    *) Bugfix: if the backend was resolved to several backends and there was 
-       an error while the response waiting then process may got caught in an 
-       endless loop.
+    *) Bugfix: if the backend was resolved to several backends and there 
+       was an error while the response waiting then process may got caught 
+       in an endless loop.
 
     *) Bugfix: the worker process may exit with the "unknown cycle" message 
        when the /dev/poll method was used.
@@ -113,28 +139,29 @@ Changes with nginx 0.1.11               
 
     *) Bugfix: the send_lowat directive did not work on Linux.
 
-    *) Bugfix: the segmentation fault occurred if there was no events section 
-       in configuration.
+    *) Bugfix: the segmentation fault occurred if there was no events 
+       section in configuration.
 
     *) Bugfix: nginx could not be built on OpenBSD.
 
-    *) Bugfix: the double slashes in "://" in the URI were converted to ":/".
+    *) Bugfix: the double slashes in "://" in the URI were converted to 
+       ":/".
 
 
 Changes with nginx 0.1.10                                        26 Nov 2004
 
-    *) Bugfix: if the request without arguments contains "//", "/./", "/../" 
-       or "%XX" then the lost character in the request line was lost; bug 
-       appeared in 0.1.9.
+    *) Bugfix: if the request without arguments contains "//", "/./", 
+       "/../" or "%XX" then the lost character in the request line was 
+       lost; bug appeared in 0.1.9.
 
-    *) Bugfix: the fix in 0.1.9 for the files bigger than 2G on Linux did not 
-       work.
+    *) Bugfix: the fix in 0.1.9 for the files bigger than 2G on Linux did 
+       not work.
 
 
 Changes with nginx 0.1.9                                         25 Nov 2004
 
-    *) Bugfix: the proxied request was sent without arguments if the request 
-       contains "//", "/./", "/../" or "%XX".
+    *) Bugfix: the proxied request was sent without arguments if the 
+       request contains "//", "/./", "/../" or "%XX".
 
     *) Bugfix: the large compressed responses may be transferred not 
        completely.
@@ -142,8 +169,8 @@ Changes with nginx 0.1.9                
     *) Bugfix: the files bigger than 2G was not transferred on Linux that 
        does not support sendfile64().
 
-    *) Bugfix: while the build configuration on Linux the --with-poll_module 
-       parameter was required; bug appeared in 0.1.8.
+    *) Bugfix: while the build configuration on Linux the 
+       --with-poll_module parameter was required; bug appeared in 0.1.8.
 
 
 Changes with nginx 0.1.8                                         20 Nov 2004
@@ -158,8 +185,8 @@ Changes with nginx 0.1.8                
 
 Changes with nginx 0.1.7                                         12 Nov 2004
 
-    *) Bugfix: on FreeBSD the segmentation fault may occur if the size of the 
-       transferred file was changed; bug appeared in 0.1.5.
+    *) Bugfix: on FreeBSD the segmentation fault may occur if the size of 
+       the transferred file was changed; bug appeared in 0.1.5.
 
 
 Changes with nginx 0.1.6                                         11 Nov 2004
@@ -170,14 +197,16 @@ Changes with nginx 0.1.6                
 
 Changes with nginx 0.1.5                                         11 Nov 2004
 
-    *) Bugfix: on Solaris and Linux there may be too many "recvmsg() returned 
-       not enough data" alerts.
+    *) Bugfix: on Solaris and Linux there may be too many "recvmsg() 
+       returned not enough data" alerts.
 
-    *) Bugfix: there were the "writev() failed (22: Invalid argument)" errors 
-       on Solaris in proxy mode without sendfile. On other platforms that do 
-       not support sendfile at all the process got caught in an endless loop.
+    *) Bugfix: there were the "writev() failed (22: Invalid argument)" 
+       errors on Solaris in proxy mode without sendfile. On other platforms 
+       that do not support sendfile at all the process got caught in an 
+       endless loop.
 
-    *) Bugfix: segmentation fault on Solaris in proxy mode and using sendfile.
+    *) Bugfix: segmentation fault on Solaris in proxy mode and using 
+       sendfile.
 
     *) Bugfix: segmentation fault on Solaris.
 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,3 +1,27 @@
+
+Изменения в nginx 0.1.16                                          25.01.2005
+
+    *) Исправление: если ответ передавался chunk'ами, то при запросе HEAD 
+       выдавался завершающий chunk.
+
+    *) Исправление: заголовок "Connection: keep-alive" выдавался, даже если 
+       директива keepalive_timeout запрещала использование keep-alive.
+
+    *) Исправление: ошибки в модуле ngx_http_fastcgi_module вызывали 
+       segmentation fault.
+
+    *) Исправление: при использовании SSL сжатый ответ мог передаваться не 
+       до конца.
+
+    *) Исправление: опции TCP_NODELAY, TCP_NOPSUH и TCP_CORK, специфичные 
+       для TCP сокетов, не используются для unix domain сокетов.
+
+    *) Добавление: директива rewrite поддерживает перезаписывание 
+       аргументов.
+
+    *) Исправление: на запрос POST с заголовком "Content-Length: 0" 
+       возвращался ответ 400; ошибка появилась в 0.1.14.
+
 
 Изменения в nginx 0.1.15                                          19.01.2005
 
@@ -20,10 +44,10 @@
        директивы "proxy_preserve_host  on" в заголовке "Host" указывался 
        также порт 80; ошибка появилась в 0.1.14.
 
-    *) Исправление: если задать одинаковые пути в параметрах автоконфигурации 
-       --http-client-body-temp-path=PATH и --http-proxy-temp-path=PATH или 
-       --http-client-body-temp-path=PATH и --http-fastcgi-temp-path=PATH, то 
-       происходил segmentation fault.
+    *) Исправление: если задать одинаковые пути в параметрах 
+       автоконфигурации --http-client-body-temp-path=PATH и 
+       --http-proxy-temp-path=PATH или --http-client-body-temp-path=PATH и 
+       --http-fastcgi-temp-path=PATH, то происходил segmentation fault.
 
 
 Изменения в nginx 0.1.14                                          18.01.2005
@@ -32,19 +56,20 @@
        --http-client-body-temp-path=PATH, --http-proxy-temp-path=PATH и 
        --http-fastcgi-temp-path=PATH
 
-    *) Изменение: имя каталога с временными файлами, содержащие тело запроса 
-       клиента, задаётся директивой client_body_temp_path, по умолчанию 
-       <prefix>/client_body_temp.
+    *) Изменение: имя каталога с временными файлами, содержащие тело 
+       запроса клиента, задаётся директивой client_body_temp_path, по 
+       умолчанию <prefix>/client_body_temp.
 
     *) Добавление: модуль ngx_http_fastcgi_module и директивы fastcgi_pass, 
-       fastcgi_root, fastcgi_index, fastcgi_params, fastcgi_connect_timeout, 
-       fastcgi_send_timeout, fastcgi_read_timeout, fastcgi_send_lowat, 
-       fastcgi_header_buffer_size, fastcgi_buffers, 
+       fastcgi_root, fastcgi_index, fastcgi_params, 
+       fastcgi_connect_timeout, fastcgi_send_timeout, fastcgi_read_timeout, 
+       fastcgi_send_lowat, fastcgi_header_buffer_size, fastcgi_buffers, 
        fastcgi_busy_buffers_size, fastcgi_temp_path, 
        fastcgi_max_temp_file_size, fastcgi_temp_file_write_size, 
        fastcgi_next_upstream и fastcgi_x_powered_by.
 
-    *) Исправление: ошибка "[alert] zero size buf"; ошибка появилась в 0.1.3.
+    *) Исправление: ошибка "[alert] zero size buf"; ошибка появилась в 
+       0.1.3.
 
     *) Изменение: в директиве proxy_pass нужно обязательно указывать URI 
        после имени хоста.
@@ -61,7 +86,8 @@
 
 Изменения в nginx 0.1.13                                          21.12.2004
 
-    *) Добавление: директивы server_names_hash и server_names_hash_threshold.
+    *) Добавление: директивы server_names_hash и 
+       server_names_hash_threshold.
 
     *) Исправление: имена *.domain.tld в директиве server_name не работали.
 
@@ -72,13 +98,14 @@
 
     *) Добавление: параметр лога %request_length.
 
-    *) Исправление: при использовании /dev/poll, select и poll на платформах, 
-       где возможны ложные срабатывания указанных методов, могли быть 
-       длительные задержки при обработке запроса по keep-alive соединению. 
-       Наблюдалось по крайней мере на Solaris с использованием /dev/poll.
+    *) Исправление: при использовании /dev/poll, select и poll на 
+       платформах, где возможны ложные срабатывания указанных методов, 
+       могли быть длительные задержки при обработке запроса по keep-alive 
+       соединению. Наблюдалось по крайней мере на Solaris с использованием 
+       /dev/poll.
 
-    *) Исправление: директива send_lowat игнорируется на Linux, так как Linux 
-       не поддерживает опцию SO_SNDLOWAT.
+    *) Исправление: директива send_lowat игнорируется на Linux, так как 
+       Linux не поддерживает опцию SO_SNDLOWAT.
 
 
 Изменения в nginx 0.1.11                                          02.12.2004
@@ -97,10 +124,11 @@
     *) Исправление: ngx_http_auto_index_module возвращал ошибку 500, если в 
        каталоге есть битый symlink.
 
-    *) Исправление: файлы больше 4G не передавались с использованием sendfile.
+    *) Исправление: файлы больше 4G не передавались с использованием 
+       sendfile.
 
-    *) Исправление: если бэкенд резолвился в несколько адресов и при ожидании 
-       от него ответа происходила ошибка, то процесс зацикливался.
+    *) Исправление: если бэкенд резолвился в несколько адресов и при 
+       ожидании от него ответа происходила ошибка, то процесс зацикливался.
 
     *) Исправление: при использовании метода /dev/poll рабочий процесс мог 
        завершиться с сообщением "unknown cycle".
@@ -111,8 +139,8 @@
 
     *) Исправление: директива send_lowat не работала на Linux.
 
-    *) Исправление: если в конфигурации не было раздела events, то происходил 
-       segmentation fault.
+    *) Исправление: если в конфигурации не было раздела events, то 
+       происходил segmentation fault.
 
     *) Исправление: nginx не собирался под OpenBSD.
 
@@ -125,8 +153,8 @@
        или "%XX", то терялся последний символ в строке запроса; ошибка 
        появилась в 0.1.9.
 
-    *) Исправление: исправление в версии 0.1.9 для файлов больше 2G на Linux 
-       не работало.
+    *) Исправление: исправление в версии 0.1.9 для файлов больше 2G на 
+       Linux не работало.
 
 
 Изменения в nginx 0.1.9                                           25.11.2004
@@ -163,8 +191,9 @@
 
 Изменения в nginx 0.1.6                                           11.11.2004
 
-    *) Исправление: при некоторых комбинациях директив location c регулярными 
-       выражениями использовалась конфигурация не из того location.
+    *) Исправление: при некоторых комбинациях директив location c 
+       регулярными выражениями использовалась конфигурация не из того 
+       location.
 
 
 Изменения в nginx 0.1.5                                           11.11.2004
@@ -204,8 +233,8 @@
 
     *) Добавление: директива proxy_set_x_url.
 
-    *) Исправление: модуль проксировании мог привести к зацикливанию, если не 
-       использовался sendfile.
+    *) Исправление: модуль проксировании мог привести к зацикливанию, если 
+       не использовался sendfile.
 
 
 Изменения в nginx 0.1.2                                           21.10.2004
@@ -220,12 +249,12 @@
     *) Исправление: нельзя переконфигурировать nginx, если конфигурационный 
        файл указан в командной строке; ошибка появилась в 0.1.1.
 
-    *) Исправление: модуль проксировании мог привести к зацикливанию, если не 
-       использовался sendfile.
+    *) Исправление: модуль проксировании мог привести к зацикливанию, если 
+       не использовался sendfile.
 
     *) Исправление: при использовании sendfile текст ответа не 
-       перекодировался согласно директивам модуля charset; ошибка появилась в 
-       0.1.1.
+       перекодировался согласно директивам модуля charset; ошибка появилась 
+       в 0.1.1.
 
     *) Исправление: очень редкая ошибка при обработке kqueue.
 
@@ -253,8 +282,8 @@
 
     *) Исправление: ошибки в модуле /dev/poll.
 
-    *) Исправление: при проксировании и использовании временных файлов ответы 
-       портились.
+    *) Исправление: при проксировании и использовании временных файлов 
+       ответы портились.
 
     *) Исправление: бэкенду передавались запросы с неперекодированными 
        символами.
--- a/auto/sources
+++ b/auto/sources
@@ -181,6 +181,7 @@ WIN32_DEPS="$CORE_DEPS $EVENT_DEPS \
             src/os/win32/ngx_socket.h \
             src/os/win32/ngx_os.h \
             src/os/win32/ngx_gui.h \
+            src/os/win32/ngx_gui_resources.h \
             src/os/win32/ngx_process_cycle.h"
 
 WIN32_CONFIG=src/os/win32/ngx_win32_config.h
@@ -201,7 +202,7 @@ WIN32_SRCS="$CORE_SRCS $EVENT_SRCS \
             src/os/win32/ngx_process_cycle.c \
             src/event/ngx_event_acceptex.c"
 
-NGX_WIN32_ICONS="src/os/win32/nginx.ico src/os/win32/tray.ico"
+NGX_WIN32_ICONS="src/os/win32/nginx.ico src/os/win32/nginx_tray.ico"
 NGX_WIN32_RC="src/os/win32/nginx.rc"
 
 
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VER          "nginx/0.1.15"
+#define NGINX_VER          "nginx/0.1.16"
 
 #define NGINX_VAR          "NGINX"
 #define NGX_NEWPID_EXT     ".newbin"
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -111,10 +111,6 @@ char *ngx_conf_parse(ngx_conf_t *cf, ngx
          *    NGX_CONF_FILE_DONE    the configuration file is done
          */
 
-#if 0
-ngx_log_debug(cf->log, "token %d" _ rc);
-#endif
-
         if (rc == NGX_ERROR) {
             break;
         }
@@ -173,9 +169,7 @@ ngx_log_debug(cf->log, "token %d" _ rc);
                 {
 
                     found = 1;
-#if 0
-ngx_log_debug(cf->log, "command '%s'" _ cmd->name.data);
-#endif
+
                     /* is the directive's location right ? */
 
                     if ((cmd->type & cf->cmd_type) == 0) {
@@ -284,10 +278,6 @@ ngx_log_debug(cf->log, "command '%s'" _ 
 
                     rv = cmd->set(cf, cmd, conf);
 
-#if 0
-ngx_log_debug(cf->log, "rv: %d" _ rv);
-#endif
-
                     if (rv == NGX_CONF_OK) {
                         break;
 
@@ -366,10 +356,6 @@ static int ngx_conf_read_token(ngx_conf_
     b = cf->conf_file->buffer;
     start = b->pos;
 
-#if 0
-ngx_log_debug(cf->log, "TOKEN START");
-#endif
-
     for ( ;; ) {
 
         if (b->pos >= b->last) {
@@ -398,12 +384,6 @@ ngx_log_debug(cf->log, "TOKEN START");
 
         ch = *b->pos++;
 
-#if 0
-ngx_log_debug(cf->log, "%d:%d:%d:%d:%d '%c'" _
-              last_space _ need_space _
-              quoted _ s_quoted _ d_quoted _ ch);
-#endif
-
         if (ch == LF) {
             cf->conf_file->line++;
 
@@ -574,10 +554,6 @@ ngx_log_debug(cf->log, "%d:%d:%d:%d:%d '
                 *dst = '\0';
                 word->len = len;
 
-#if 0
-ngx_log_debug(cf->log, "FOUND %d:'%s'" _ word->len _ word->data);
-#endif
-
                 if (ch == ';') {
                     return NGX_OK;
                 }
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -13,8 +13,8 @@ ngx_os_io_t  ngx_io;
 
 
 ngx_listening_t *ngx_listening_inet_stream_socket(ngx_conf_t *cf,
-                                                 in_addr_t addr,
-                                                 in_port_t port)
+                                                  in_addr_t addr,
+                                                  in_port_t port)
 {
     size_t               len;
     ngx_listening_t     *ls;
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -64,9 +64,16 @@ typedef enum {
 
 
 typedef enum {
-     NGX_TCP_NOPUSH_DISABLED = -1,
+     NGX_TCP_NODELAY_UNSET = 0,
+     NGX_TCP_NODELAY_SET,
+     NGX_TCP_NODELAY_DISABLED
+} ngx_connection_tcp_nodelay_e;
+
+
+typedef enum {
      NGX_TCP_NOPUSH_UNSET = 0,
-     NGX_TCP_NOPUSH_SET
+     NGX_TCP_NOPUSH_SET,
+     NGX_TCP_NOPUSH_DISABLED
 } ngx_connection_tcp_nopush_e;
 
 
@@ -109,7 +116,7 @@ struct ngx_connection_s {
 
     ngx_uint_t          number;
 
-    unsigned            log_error:2;  /* ngx_connection_log_error_e */
+    unsigned            log_error:2;     /* ngx_connection_log_error_e */
 
     unsigned            buffered:1;
     unsigned            single_connection:1;
@@ -118,8 +125,8 @@ struct ngx_connection_s {
 
     unsigned            sendfile:1;
     unsigned            sndlowat:1;
-    unsigned            tcp_nodelay:1;
-    signed              tcp_nopush:2;
+    unsigned            tcp_nodelay:2;   /* ngx_connection_tcp_nodelay_e */
+    unsigned            tcp_nopush:2;    /* ngx_connection_tcp_nopush_e */
 
 #if (NGX_HAVE_IOCP)
     unsigned            accept_context_updated:1;
--- a/src/core/ngx_log.c
+++ b/src/core/ngx_log.c
@@ -86,9 +86,15 @@ void ngx_log_error_core(ngx_uint_t level
     /* pid#tid */
     p = ngx_sprintf(p, "%P#" NGX_TID_T_FMT ": ", ngx_log_pid, ngx_log_tid);
 
+    if (log->connection) {
+        p = ngx_sprintf(p, "*%ui ", log->connection);
+    }
+
+#if 0
     if (log->data && *(int *) log->data != -1) {
         p = ngx_sprintf(p, "*%ud ", *(u_int *) log->data);
     }
+#endif
 
 #if (NGX_HAVE_VARIADIC_MACROS)
 
@@ -137,7 +143,7 @@ void ngx_log_error_core(ngx_uint_t level
     }
 
     if (level != NGX_LOG_DEBUG && log->handler) {
-        p = log->handler(log->data, p, last - p);
+        p = log->handler(log, p, last - p);
     }
 
     ngx_log_write(log, errstr, p - errstr);
--- a/src/core/ngx_log.h
+++ b/src/core/ngx_log.h
@@ -40,14 +40,25 @@
 #define NGX_LOG_DEBUG_ALL         0x7ffffff0
 
 
-typedef u_char *(*ngx_log_handler_pt) (void *ctx, u_char *buf, size_t len);
+typedef u_char *(*ngx_log_handler_pt) (ngx_log_t *log, u_char *buf, size_t len);
 
 
 struct ngx_log_s {
     ngx_uint_t           log_level;
     ngx_open_file_t     *file;
+
+    ngx_uint_t           connection;
+
+    ngx_log_handler_pt   handler;
     void                *data;
-    ngx_log_handler_pt   handler;
+
+    /*
+     * we declare "action" as "char *" because the actions are usually
+     * the static strings and in the "u_char *" case we have to override
+     * their types all the time
+     */
+
+    char                *action;
 };
 
 
@@ -60,24 +71,32 @@ struct ngx_log_s {
 
 #define NGX_HAVE_VARIADIC_MACROS  1
 
-#define ngx_log_error(level, log, args...) \
+#define ngx_log_error(level, log, args...)                                    \
         if (log->log_level >= level) ngx_log_error_core(level, log, args)
 
 void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
                         const char *fmt, ...);
 
+#define ngx_log_debug(level, log, args...)                                    \
+    if (log->log_level & level)                                               \
+        ngx_log_error_core(NGX_LOG_DEBUG, log, args)
+
 /*********************************/
 
 #elif (NGX_HAVE_C99_VARIADIC_MACROS)
 
 #define NGX_HAVE_VARIADIC_MACROS  1
 
-#define ngx_log_error(level, log, ...) \
+#define ngx_log_error(level, log, ...)                                        \
         if (log->log_level >= level) ngx_log_error_core(level, log, __VA_ARGS__)
 
 void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
                         const char *fmt, ...);
 
+#define ngx_log_debug(level, log, ...)                                        \
+    if (log->log_level & level)                                               \
+        ngx_log_error_core(NGX_LOG_DEBUG, log, __VA_ARGS__)
+
 /*********************************/
 
 #else /* NO VARIADIC MACROS */
@@ -100,80 +119,59 @@ void ngx_log_debug_core(ngx_log_t *log, 
 
 #if (NGX_HAVE_VARIADIC_MACROS)
 
-#define ngx_log_debug0(level, log, err, fmt) \
-    if (log->log_level & level) \
-        ngx_log_error_core(NGX_LOG_DEBUG, log, err, fmt)
-
-#define ngx_log_debug1(level, log, err, fmt, arg1) \
-    if (log->log_level & level) \
-        ngx_log_error_core(NGX_LOG_DEBUG, log, err, fmt, arg1)
-
-#define ngx_log_debug2(level, log, err, fmt, arg1, arg2) \
-    if (log->log_level & level) \
-        ngx_log_error_core(NGX_LOG_DEBUG, log, err, fmt, arg1, arg2)
-
-#define ngx_log_debug3(level, log, err, fmt, arg1, arg2, arg3) \
-    if (log->log_level & level) \
-        ngx_log_error_core(NGX_LOG_DEBUG, log, err, fmt, arg1, arg2, arg3)
-
-#define ngx_log_debug4(level, log, err, fmt, arg1, arg2, arg3, arg4) \
-    if (log->log_level & level) \
-        ngx_log_error_core(NGX_LOG_DEBUG, log, err, fmt, arg1, arg2, arg3, arg4)
-
-#define ngx_log_debug5(level, log, err, fmt, arg1, arg2, arg3, arg4, arg5) \
-    if (log->log_level & level) \
-        ngx_log_error_core(NGX_LOG_DEBUG, log, err, fmt, \
-                           arg1, arg2, arg3, arg4, arg5)
-
-#define ngx_log_debug6(level, log, err, fmt, \
-                       arg1, arg2, arg3, arg4, arg5, arg6) \
-    if (log->log_level & level) \
-        ngx_log_error_core(NGX_LOG_DEBUG, log, err, fmt, \
-                           arg1, arg2, arg3, arg4, arg5, arg6)
-
-#define ngx_log_debug7(level, log, err, fmt, \
-                       arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
-    if (log->log_level & level) \
-        ngx_log_error_core(NGX_LOG_DEBUG, log, err, fmt, \
-                           arg1, arg2, arg3, arg4, arg5, arg6, arg7)
+#define ngx_log_debug0  ngx_log_debug
+#define ngx_log_debug1  ngx_log_debug
+#define ngx_log_debug2  ngx_log_debug
+#define ngx_log_debug3  ngx_log_debug
+#define ngx_log_debug4  ngx_log_debug
+#define ngx_log_debug5  ngx_log_debug
+#define ngx_log_debug6  ngx_log_debug
+#define ngx_log_debug7  ngx_log_debug
+#define ngx_log_debug8  ngx_log_debug
 
 #else /* NO VARIADIC MACROS */
 
-#define ngx_log_debug0(level, log, err, fmt) \
-    if (log->log_level & level) \
+#define ngx_log_debug0(level, log, err, fmt)                                  \
+    if (log->log_level & level)                                               \
         ngx_log_debug_core(log, err, fmt)
 
-#define ngx_log_debug1(level, log, err, fmt, arg1) \
-    if (log->log_level & level) \
+#define ngx_log_debug1(level, log, err, fmt, arg1)                            \
+    if (log->log_level & level)                                               \
         ngx_log_debug_core(log, err, fmt, arg1)
 
-#define ngx_log_debug2(level, log, err, fmt, arg1, arg2) \
-    if (log->log_level & level) \
+#define ngx_log_debug2(level, log, err, fmt, arg1, arg2)                      \
+    if (log->log_level & level)                                               \
         ngx_log_debug_core(log, err, fmt, arg1, arg2)
 
-#define ngx_log_debug3(level, log, err, fmt, arg1, arg2, arg3) \
-    if (log->log_level & level) \
+#define ngx_log_debug3(level, log, err, fmt, arg1, arg2, arg3)                \
+    if (log->log_level & level)                                               \
         ngx_log_debug_core(log, err, fmt, arg1, arg2, arg3)
 
-#define ngx_log_debug4(level, log, err, fmt, arg1, arg2, arg3, arg4) \
-    if (log->log_level & level) \
+#define ngx_log_debug4(level, log, err, fmt, arg1, arg2, arg3, arg4)          \
+    if (log->log_level & level)                                               \
         ngx_log_debug_core(log, err, fmt, arg1, arg2, arg3, arg4)
 
-#define ngx_log_debug5(level, log, err, fmt, arg1, arg2, arg3, arg4, arg5) \
-    if (log->log_level & level) \
+#define ngx_log_debug5(level, log, err, fmt, arg1, arg2, arg3, arg4, arg5)    \
+    if (log->log_level & level)                                               \
         ngx_log_debug_core(log, err, fmt, arg1, arg2, arg3, arg4, arg5)
 
-#define ngx_log_debug6(level, log, err, fmt, \
-                       arg1, arg2, arg3, arg4, arg5, arg6) \
-    if (log->log_level & level) \
+#define ngx_log_debug6(level, log, err, fmt,                                  \
+                       arg1, arg2, arg3, arg4, arg5, arg6)                    \
+    if (log->log_level & level)                                               \
         ngx_log_debug_core(log, err, fmt, arg1, arg2, arg3, arg4, arg5, arg6)
 
-#define ngx_log_debug7(level, log, err, fmt, \
-                       arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
-    if (log->log_level & level) \
-        ngx_log_debug_core(log, err, fmt, \
+#define ngx_log_debug7(level, log, err, fmt,                                  \
+                       arg1, arg2, arg3, arg4, arg5, arg6, arg7)              \
+    if (log->log_level & level)                                               \
+        ngx_log_debug_core(log, err, fmt,                                     \
                        arg1, arg2, arg3, arg4, arg5, arg6, arg7)
 
+#define ngx_log_debug8(level, log, err, fmt,                                  \
+                       arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)        \
+    if (log->log_level & level)                                               \
+        ngx_log_debug_core(log, err, fmt,                                     \
+                       arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
+
 #endif
 
 #else /* NO NGX_DEBUG */
@@ -187,6 +185,8 @@ void ngx_log_debug_core(ngx_log_t *log, 
 #define ngx_log_debug6(level, log, err, fmt, arg1, arg2, arg3, arg4, arg5, arg6)
 #define ngx_log_debug7(level, log, err, fmt, arg1, arg2, arg3, arg4, arg5,    \
                        arg6, arg7)
+#define ngx_log_debug8(level, log, err, fmt, arg1, arg2, arg3, arg4, arg5,    \
+                       arg6, arg7, arg8)
 
 #endif
 
--- a/src/core/ngx_output_chain.c
+++ b/src/core/ngx_output_chain.c
@@ -80,7 +80,17 @@ ngx_int_t ngx_output_chain(ngx_output_ch
             if (bsize == 0 && !ngx_buf_special(ctx->in->buf)) {
 
                 ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
-                              "zero size buf in output");
+                              "zero size buf in output "
+                              "t:%d r:%d f:%d %p %p-%p %p %O-%O",
+                              ctx->in->buf->temporary,
+                              ctx->in->buf->recycled,
+                              ctx->in->buf->in_file,
+                              ctx->in->buf->start,
+                              ctx->in->buf->pos,
+                              ctx->in->buf->last,
+                              ctx->in->buf->file,
+                              ctx->in->buf->file_pos,
+                              ctx->in->buf->file_last);
 
                 ngx_debug_point();
 
--- a/src/event/modules/ngx_devpoll_module.c
+++ b/src/event/modules/ngx_devpoll_module.c
@@ -310,7 +310,7 @@ static int ngx_devpoll_set_event(ngx_eve
 
 int ngx_devpoll_process_events(ngx_cycle_t *cycle)
 {
-    int                 events;
+    int                 events, revents;
     ngx_int_t           i;
     ngx_uint_t          j, lock, accept_lock, expire;
     size_t              n;
@@ -463,30 +463,40 @@ int ngx_devpoll_process_events(ngx_cycle
         }
 #endif
 
+        revents = event_list[i].revents;
+
         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                        "devpoll: fd:%d, ev:%04Xd, rev:%04Xd",
-                       event_list[i].fd,
-                       event_list[i].events, event_list[i].revents);
+                       event_list[i].fd, event_list[i].events, revents);
 
-        if (event_list[i].revents & (POLLERR|POLLHUP|POLLNVAL)) {
+        if (revents & (POLLERR|POLLHUP|POLLNVAL)) {
             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                           "ioctl(DP_POLL) error fd:%d ev:%04Xd rev:%04Xd",
-                          event_list[i].fd,
-                          event_list[i].events, event_list[i].revents);
+                          event_list[i].fd, event_list[i].events, revents);
         }
 
-        if (event_list[i].revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL))
-        {
+        if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                           "strange ioctl(DP_POLL) events "
                           "fd:%d ev:%04Xd rev:%04Xd",
-                          event_list[i].fd,
-                          event_list[i].events, event_list[i].revents);
+                          event_list[i].fd, event_list[i].events, revents);
+        }
+
+        if ((revents & (POLLERR|POLLHUP|POLLNVAL))
+             && (revents & (POLLIN|POLLOUT)) == 0)
+        {
+            /*
+             * if the error events were returned without POLLIN or POLLOUT,
+             * then add these flags to handle the events at least in one
+             * active handler 
+             */
+
+            revents |= POLLIN|POLLOUT;
         }
 
         wev = c->write;
 
-        if ((event_list[i].events & (POLLOUT|POLLERR|POLLHUP)) && wev->active) {
+        if ((revents & POLLOUT) && wev->active) {
             wev->ready = 1;
 
             if (!ngx_threaded && !ngx_accept_mutex_held) {
@@ -505,7 +515,7 @@ int ngx_devpoll_process_events(ngx_cycle
 
         rev = c->read;
 
-        if ((event_list[i].events & (POLLIN|POLLERR|POLLHUP)) && rev->active) {
+        if ((revents & POLLIN) && rev->active) {
             rev->ready = 1;
 
             if (!ngx_threaded && !ngx_accept_mutex_held) {
--- a/src/event/modules/ngx_epoll_module.c
+++ b/src/event/modules/ngx_epoll_module.c
@@ -198,37 +198,40 @@ static void ngx_epoll_done(ngx_cycle_t *
 
 static int ngx_epoll_add_event(ngx_event_t *ev, int event, u_int flags)
 {
-    int                  op, prev;
+    int                  op;
+    uint32_t             events, prev;
     ngx_event_t         *e;
     ngx_connection_t    *c;
     struct epoll_event   ee;
 
     c = ev->data;
 
+    events = (uint32_t) event;
+
     if (event == NGX_READ_EVENT) {
         e = c->write;
         prev = EPOLLOUT;
 #if (NGX_READ_EVENT != EPOLLIN)
-        event = EPOLLIN;
+        events = EPOLLIN;
 #endif
 
     } else {
         e = c->read;
         prev = EPOLLIN;
 #if (NGX_WRITE_EVENT != EPOLLOUT)
-        event = EPOLLOUT;
+        events = EPOLLOUT;
 #endif
     }
 
     if (e->active) {
         op = EPOLL_CTL_MOD;
-        event |= prev;
+        events |= prev;
 
     } else {
         op = EPOLL_CTL_ADD;
     }
 
-    ee.events = event | flags;
+    ee.events = events | flags;
     ee.data.u64 = (uintptr_t) c | ev->instance;
 
     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
@@ -252,14 +255,15 @@ static int ngx_epoll_add_event(ngx_event
 
 static int ngx_epoll_del_event(ngx_event_t *ev, int event, u_int flags)
 {
-    int                  op, prev;
+    int                  op;
+    uint32_t             prev;
     ngx_event_t         *e;
     ngx_connection_t    *c;
     struct epoll_event   ee;
 
     /*
-     * when the file descriptor is closed the epoll automatically deletes
-     * it from its queue so we do not need to delete explicity the event
+     * when the file descriptor is closed, the epoll automatically deletes
+     * it from its queue, so we do not need to delete explicity the event
      * before the closing the file descriptor
      */
 
@@ -370,6 +374,7 @@ int ngx_epoll_process_events(ngx_cycle_t
 {
     int                events;
     size_t             n;
+    uint32_t           revents;
     ngx_int_t          instance, i;
     ngx_uint_t         lock, accept_lock, expire;
     ngx_err_t          err;
@@ -521,27 +526,40 @@ int ngx_epoll_process_events(ngx_cycle_t
         log = c->log ? c->log : cycle->log;
 #endif
 
+        revents = event_list[i].events;
+
         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0,
                        "epoll: fd:%d ev:%04XD d:%p",
-                       c->fd, event_list[i].events, event_list[i].data);
+                       c->fd, revents, event_list[i].data);
 
-        if (event_list[i].events & (EPOLLERR|EPOLLHUP)) {
+        if (revents & (EPOLLERR|EPOLLHUP)) {
             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
                            "epoll_wait() error on fd:%d ev:%04XD",
-                           c->fd, event_list[i].events);
+                           c->fd, revents);
+        }
+
+        if (revents & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) {
+            ngx_log_error(NGX_LOG_ALERT, log, 0,
+                          "strange epoll_wait() events fd:%d ev:%04XD",
+                          c->fd, revents);
         }
 
-        if (event_list[i].events & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) {
-            ngx_log_error(NGX_LOG_ALERT, log, 0,
-                          "strange epoll_wait() events fd:%d ev:%04XD",
-                          c->fd, event_list[i].events);
+        if ((revents & (EPOLLERR|EPOLLHUP))
+             && (revents & (EPOLLIN|EPOLLOUT)) == 0)
+        {
+            /*
+             * if the error events were returned without EPOLLIN or EPOLLOUT,
+             * then add these flags to handle the events at least in one
+             * active handler
+             */
+
+            revents |= EPOLLIN|EPOLLOUT;
         }
 
         wev = c->write;
 
-        if ((event_list[i].events & (EPOLLOUT|EPOLLERR|EPOLLHUP))
-            && wev->active)
-        {
+        if ((revents & EPOLLOUT) && wev->active) {
+
             if (ngx_threaded) {
                 wev->posted_ready = 1;
                 ngx_post_event(wev);
@@ -564,9 +582,8 @@ int ngx_epoll_process_events(ngx_cycle_t
          * if the accept event is the last one.
          */
 
-        if ((event_list[i].events & (EPOLLIN|EPOLLERR|EPOLLHUP))
-            && rev->active)
-        {
+        if ((revents & EPOLLIN) && rev->active) {
+
             if (ngx_threaded && !rev->accept) {
                 rev->posted_ready = 1;
 
--- a/src/event/modules/ngx_poll_module.c
+++ b/src/event/modules/ngx_poll_module.c
@@ -262,7 +262,7 @@ static ngx_int_t ngx_poll_del_event(ngx_
 
 static ngx_int_t ngx_poll_process_events(ngx_cycle_t *cycle)
 {
-    int                 ready;
+    int                 ready, revents;
     ngx_int_t           i, nready;
     ngx_uint_t          n, found, lock, expire;
     ngx_msec_t          timer;
@@ -378,33 +378,30 @@ static ngx_int_t ngx_poll_process_events
 
     for (i = 0; i < nevents && ready; i++) {
 
+        revents = event_list[i].revents;
+
 #if 0
         ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                        "poll: %d: fd:%d ev:%04Xd rev:%04Xd",
-                       i, event_list[i].fd,
-                       event_list[i].events, event_list[i].revents);
+                       i, event_list[i].fd, event_list[i].events, revents);
 #else
-        if (event_list[i].revents) {
+        if (revents) {
             ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                            "poll: %d: fd:%d ev:%04Xd rev:%04Xd",
-                           i, event_list[i].fd,
-                           event_list[i].events, event_list[i].revents);
+                           i, event_list[i].fd, event_list[i].events, revents);
         }
 #endif
 
-        if (event_list[i].revents & POLLNVAL) {
+        if (revents & POLLNVAL) {
             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                           "poll() error fd:%d ev:%04Xd rev:%04Xd",
-                          event_list[i].fd,
-                          event_list[i].events, event_list[i].revents);
+                          event_list[i].fd, event_list[i].events, revents);
         }
 
-        if (event_list[i].revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL))
-        {
+        if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                           "strange poll() events fd:%d ev:%04Xd rev:%04Xd",
-                          event_list[i].fd,
-                          event_list[i].events, event_list[i].revents);
+                          event_list[i].fd, event_list[i].events, revents);
         }
 
         if (event_list[i].fd == -1) {
@@ -447,9 +444,21 @@ static ngx_int_t ngx_poll_process_events
             continue;
         }
 
+        if ((revents & (POLLERR|POLLHUP|POLLNVAL))
+             && (revents & (POLLIN|POLLOUT)) == 0)
+        {
+            /*
+             * if the error events were returned without POLLIN or POLLOUT,
+             * then add these flags to handle the events at least in one
+             * active handler
+             */
+
+            revents |= POLLIN|POLLOUT;
+        }
+
         found = 0;
 
-        if (event_list[i].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL)) {
+        if (revents & POLLIN) {
             found = 1;
 
             ev = c->read;
@@ -474,7 +483,7 @@ static ngx_int_t ngx_poll_process_events
 #endif
         }
 
-        if (event_list[i].revents & (POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
+        if (revents & POLLOUT) {
             found = 1;
             ev = c->write;
             ev->ready = 1;
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -201,7 +201,7 @@ static ngx_int_t ngx_event_module_init(n
     }
 
 
-    /* TODO: 128 is cache line size */
+    /* TODO: adjust cache line size, 128 is P4 cache line size */
 
     size = 128            /* ngx_accept_mutex */
            + 128;         /* ngx_connection_counter */
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -10,29 +10,22 @@
 #include <nginx.h>
 
 
-typedef struct {
-    int         flag;
-    ngx_str_t  *name;
-} ngx_accept_log_ctx_t;
-
-
 static void ngx_close_accepted_socket(ngx_socket_t s, ngx_log_t *log);
-static u_char *ngx_accept_log_error(void *data, u_char *buf, size_t len);
+static u_char *ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len);
 
 
 void ngx_event_accept(ngx_event_t *ev)
 {
-    ngx_uint_t             instance, accepted;
-    socklen_t              len;
-    struct sockaddr       *sa;
-    ngx_err_t              err;
-    ngx_log_t             *log;
-    ngx_pool_t            *pool;
-    ngx_socket_t           s;
-    ngx_event_t           *rev, *wev;
-    ngx_connection_t      *c, *ls;
-    ngx_event_conf_t      *ecf;
-    ngx_accept_log_ctx_t  *ctx;
+    ngx_uint_t         instance, accepted;
+    socklen_t          len;
+    struct sockaddr   *sa;
+    ngx_err_t          err;
+    ngx_log_t         *log;
+    ngx_pool_t        *pool;
+    ngx_socket_t       s;
+    ngx_event_t       *rev, *wev;
+    ngx_connection_t  *c, *ls;
+    ngx_event_conf_t  *ecf;
 
     ecf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_event_core_module);
 
@@ -81,16 +74,7 @@ void ngx_event_accept(ngx_event_t *ev)
         ngx_memcpy(log, ls->log, sizeof(ngx_log_t));
         pool->log = log;
 
-        if (!(ctx = ngx_palloc(pool, sizeof(ngx_accept_log_ctx_t)))) {
-            ngx_destroy_pool(pool);
-            return;
-        }
-
-        /* -1 disables the connection number logging */
-        ctx->flag = -1;
-        ctx->name = &ls->listening->addr_text;
-
-        log->data = ctx;
+        log->data = &ls->listening->addr_text;
         log->handler = ngx_accept_log_error;
 
         len = ls->listening->socklen;
@@ -467,9 +451,7 @@ static void ngx_close_accepted_socket(ng
 }
 
 
-static u_char *ngx_accept_log_error(void *data, u_char *buf, size_t len)
+static u_char *ngx_accept_log_error(ngx_log_t *log, u_char *buf, size_t len)
 {
-    ngx_accept_log_ctx_t  *ctx = data;
-
-    return ngx_snprintf(buf, len, " while accept() on %V", ctx->name);
+    return ngx_snprintf(buf, len, " while accept() on %V", log->data);
 }
--- a/src/event/ngx_event_connect.c
+++ b/src/event/ngx_event_connect.c
@@ -8,11 +8,8 @@
 #include <ngx_core.h>
 #include <ngx_event.h>
 #include <ngx_event_connect.h>
-#include <nginx.h>
 
 
-/* AF_INET only */
-
 ngx_int_t ngx_event_connect_peer(ngx_peer_connection_t *pc)
 {
     int                  rc;
@@ -170,6 +167,7 @@ ngx_int_t ngx_event_connect_peer(ngx_pee
     }
 
 #if (NGX_WIN32)
+
     /*
      * Winsock assignes a socket number divisible by 4
      * so to find a connection we divide a socket number by 4.
@@ -232,6 +230,11 @@ ngx_int_t ngx_event_connect_peer(ngx_pee
 
     c->log_error = pc->log_error;
 
+    if (peer->sockaddr->sa_family != AF_INET) {
+        c->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
+        c->tcp_nodelay = NGX_TCP_NODELAY_DISABLED;
+    }
+
     pc->connection = c;
 
     /*
@@ -289,6 +292,9 @@ ngx_int_t ngx_event_connect_peer(ngx_pee
         }
  
         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, pc->log, 0, "connected");
+
+        wev->ready = 1;
+
         return NGX_OK;
     }
 
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -17,8 +17,6 @@ static ngx_int_t ngx_event_pipe_write_ch
 static ngx_inline void ngx_event_pipe_remove_shadow_links(ngx_buf_t *buf);
 static ngx_inline void ngx_event_pipe_free_shadow_raw_buf(ngx_chain_t **free,
                                                           ngx_buf_t *buf);
-static ngx_inline void ngx_event_pipe_add_free_buf(ngx_chain_t **chain,
-                                                   ngx_chain_t *cl);
 static ngx_int_t ngx_event_pipe_drain_chains(ngx_event_pipe_t *p);
 
 
@@ -29,6 +27,8 @@ ngx_int_t ngx_event_pipe(ngx_event_pipe_
 
     for ( ;; ) {
         if (do_write) {
+            p->log->action = "sending to client";
+
             if (ngx_event_pipe_write_to_downstream(p) == NGX_ABORT) {
                 return NGX_ABORT;
             }
@@ -37,6 +37,8 @@ ngx_int_t ngx_event_pipe(ngx_event_pipe_
         p->read = 0;
         p->upstream_blocked = 0;
 
+        p->log->action = "reading upstream";
+
         if (ngx_event_pipe_read_upstream(p) == NGX_ABORT) {
             return NGX_ABORT;
         }
@@ -77,12 +79,12 @@ ngx_int_t ngx_event_pipe(ngx_event_pipe_
 }
 
 
-ngx_int_t ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
+static ngx_int_t ngx_event_pipe_read_upstream(ngx_event_pipe_t *p)
 {
     ssize_t       n, size;
     ngx_int_t     rc;
     ngx_buf_t    *b;
-    ngx_chain_t  *chain, *cl, *tl;
+    ngx_chain_t  *chain, *cl;
 
     if (p->upstream_eof || p->upstream_error || p->upstream_done) {
         return NGX_OK;
@@ -169,8 +171,12 @@ ngx_int_t ngx_event_pipe_read_upstream(n
 
                 p->allocated++;
 
-                ngx_alloc_link_and_set_buf(tl, b, p->pool, NGX_ABORT);
-                chain = tl;
+                if (!(chain = ngx_alloc_chain_link(p->pool))) {
+                    return NGX_ABORT;
+                }
+
+                chain->buf = b;
+                chain->next = NULL;
 
             } else if (!p->cachable && p->downstream->write->ready) {
 
@@ -191,7 +197,7 @@ ngx_int_t ngx_event_pipe_read_upstream(n
             {
 
                 /*
-                 * if it's allowed then save some bufs from r->in
+                 * if it is allowed, then save some bufs from r->in
                  * to a temporary file, and add them to a r->out chain
                  */
 
@@ -227,7 +233,7 @@ ngx_int_t ngx_event_pipe_read_upstream(n
 
             } else {
 
-                /* if there're no bufs to read in then disable a level event */
+                /* there are no bufs to read in */
 
                 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0,
                                "no pipe bufs to read in");
@@ -298,52 +304,56 @@ ngx_int_t ngx_event_pipe_read_upstream(n
 
 #if (NGX_DEBUG)
 
-    if (p->in || p->busy || p->free_raw_bufs) {
-        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, p->log, 0, "pipe buf");
-    }
-
     for (cl = p->busy; cl; cl = cl->next) {
-        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, p->log, 0,
-                       "pipe buf busy %p, pos %p, size: %z",
+        ngx_log_debug8(NGX_LOG_DEBUG_EVENT, p->log, 0,
+                       "pipe buf busy s:%d t:%d f:%d "
+                       "%p, pos %p, size: %z "
+                       "file: %O, size: %z",
+                       (cl->buf->shadow ? 1 : 0),
+                       cl->buf->temporary, cl->buf->in_file,
                        cl->buf->start, cl->buf->pos,
-                       cl->buf->last - cl->buf->pos);
+                       cl->buf->last - cl->buf->pos,
+                       cl->buf->file_pos,
+                       cl->buf->file_last - cl->buf->file_pos);
     }
 
     for (cl = p->out; cl; cl = cl->next) {
-        if (cl->buf->in_file && cl->buf->temporary) {
-            ngx_log_debug5(NGX_LOG_DEBUG_EVENT, p->log, 0,
-                           "pipe buf out shadow %p, pos %p, size: %z "
-                           "file: %O, size: %z",
-                           cl->buf->start, cl->buf->pos,
-                           cl->buf->last - cl->buf->pos,
-                           cl->buf->file_pos,
-                           cl->buf->file_last - cl->buf->file_pos);
-
-        } else if (cl->buf->in_file) {
-            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
-                           "pipe buf out file %O, size: %z",
-                           cl->buf->file_pos,
-                           cl->buf->file_last - cl->buf->file_pos);
-        } else {
-            ngx_log_debug3(NGX_LOG_DEBUG_EVENT, p->log, 0,
-                           "pipe buf out %p, pos %p, size: %z",
-                           cl->buf->start, cl->buf->pos,
-                           cl->buf->last - cl->buf->pos);
-        }
+        ngx_log_debug8(NGX_LOG_DEBUG_EVENT, p->log, 0,
+                       "pipe buf out  s:%d t:%d f:%d "
+                       "%p, pos %p, size: %z "
+                       "file: %O, size: %z",
+                       (cl->buf->shadow ? 1 : 0),
+                       cl->buf->temporary, cl->buf->in_file,
+                       cl->buf->start, cl->buf->pos,
+                       cl->buf->last - cl->buf->pos,
+                       cl->buf->file_pos,
+                       cl->buf->file_last - cl->buf->file_pos);
     }
 
     for (cl = p->in; cl; cl = cl->next) {
-        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, p->log, 0,
-                       "pipe buf in %p, pos %p, size: %z",
+        ngx_log_debug8(NGX_LOG_DEBUG_EVENT, p->log, 0,
+                       "pipe buf in   s:%d t:%d f:%d "
+                       "%p, pos %p, size: %z "
+                       "file: %O, size: %z",
+                       (cl->buf->shadow ? 1 : 0),
+                       cl->buf->temporary, cl->buf->in_file,
                        cl->buf->start, cl->buf->pos,
-                       cl->buf->last - cl->buf->pos);
+                       cl->buf->last - cl->buf->pos,
+                       cl->buf->file_pos,
+                       cl->buf->file_last - cl->buf->file_pos);
     }
 
     for (cl = p->free_raw_bufs; cl; cl = cl->next) {
-        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, p->log, 0,
-                       "pipe buf free %p, last %p, size: %z",
-                       cl->buf->start, cl->buf->last,
-                       cl->buf->end - cl->buf->last);
+        ngx_log_debug8(NGX_LOG_DEBUG_EVENT, p->log, 0,
+                       "pipe buf free s:%d t:%d f:%d "
+                       "%p, pos %p, size: %z "
+                       "file: %O, size: %z",
+                       (cl->buf->shadow ? 1 : 0),
+                       cl->buf->temporary, cl->buf->in_file,
+                       cl->buf->start, cl->buf->pos,
+                       cl->buf->last - cl->buf->pos,
+                       cl->buf->file_pos,
+                       cl->buf->file_last - cl->buf->file_pos);
     }
 
 #endif
@@ -377,12 +387,11 @@ ngx_int_t ngx_event_pipe_read_upstream(n
 }
 
 
-ngx_int_t ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
+static ngx_int_t ngx_event_pipe_write_to_downstream(ngx_event_pipe_t *p)
 {
     size_t        bsize;
     ngx_uint_t    flush;
-    ngx_buf_t    *b;
-    ngx_chain_t  *out, **ll, *cl, *tl;
+    ngx_chain_t  *out, **ll, *cl;
 
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0,
                    "pipe write downstream: %d", p->downstream->write->ready);
@@ -522,11 +531,9 @@ ngx_int_t ngx_event_pipe_write_to_downst
             /* add the free shadow raw buf to p->free_raw_bufs */
 
             if (cl->buf->last_shadow) {
-                b = cl->buf->shadow;
-                b->pos = b->last = b->start;
-                b->shadow = NULL;
-                ngx_alloc_link_and_set_buf(tl, b, p->pool, NGX_ABORT);
-                ngx_event_pipe_add_free_buf(&p->free_raw_bufs, tl);
+                if (ngx_event_pipe_add_free_buf(p, cl->buf->shadow) != NGX_OK) {
+                    return NGX_ABORT;
+                }
 
                 cl->buf->last_shadow = 0;
             }
@@ -631,13 +638,21 @@ static ngx_int_t ngx_event_pipe_write_ch
         ngx_chain_add_link(p->out, p->last_out, cl);
 
         if (b->last_shadow) {
+
+            if (!(tl = ngx_alloc_chain_link(p->pool))) {
+                return NGX_ABORT;
+            }
+
+            tl->buf = b->shadow;
+            tl->next = NULL;
+
+            *last_free = tl;
+            last_free = &tl->next;
+
             b->shadow->pos = b->shadow->start;
             b->shadow->last = b->shadow->start;
 
-            ngx_alloc_link_and_set_buf(tl, b->shadow, p->pool, NGX_ABORT);
-
-            *last_free = tl;
-            last_free = &tl->next;
+            ngx_event_pipe_remove_shadow_links(b->shadow);
         }
     }
 
@@ -673,7 +688,12 @@ ngx_int_t ngx_event_pipe_copy_input_filt
     b->recycled = 1;
     buf->shadow = b;
 
-    ngx_alloc_link_and_set_buf(cl, b, p->pool, NGX_ERROR);
+    if (!(cl = ngx_alloc_chain_link(p->pool))) {
+        return NGX_ERROR;
+    }
+
+    cl->buf = b;
+    cl->next = NULL;
 
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d", b->num);
 
@@ -742,28 +762,48 @@ static ngx_inline void ngx_event_pipe_fr
 }
 
 
-static ngx_inline void ngx_event_pipe_add_free_buf(ngx_chain_t **chain,
-                                                   ngx_chain_t *cl)
+ngx_int_t ngx_event_pipe_add_free_buf(ngx_event_pipe_t *p, ngx_buf_t *b)
 {
-    if (*chain == NULL) {
-        *chain = cl;
-        return;
+    ngx_chain_t  *cl;
+
+    if (!(cl = ngx_alloc_chain_link(p->pool))) {
+        return NGX_ERROR;
     }
 
-    if ((*chain)->buf->pos != (*chain)->buf->last) {
-        cl->next = (*chain)->next;
-        (*chain)->next = cl;
+    b->pos = b->start;
+    b->last = b->start;
+    b->shadow = NULL;
+
+    cl->buf = b;
+
+    if (p->free_raw_bufs == NULL) {
+        p->free_raw_bufs = cl;
+        cl->next = NULL;
+
+        return NGX_OK;
+    }
+
+    if (p->free_raw_bufs->buf->pos == p->free_raw_bufs->buf->last) {
 
-    } else {
-        cl->next = (*chain);
-        (*chain) = cl;
+        /* add the free buf to the list start */
+
+        cl->next = p->free_raw_bufs;
+        p->free_raw_bufs = cl;
+
+        return NGX_OK;
     }
+
+    /* the first free buf is partialy filled, thus add the free buf after it */
+
+    cl->next = p->free_raw_bufs->next;
+    p->free_raw_bufs->next = cl;
+
+    return NGX_OK;
 }
 
 
 static ngx_int_t ngx_event_pipe_drain_chains(ngx_event_pipe_t *p)
 {
-    ngx_buf_t    *b;
     ngx_chain_t  *cl, *tl;
 
     for ( ;; ) {
@@ -785,19 +825,10 @@ static ngx_int_t ngx_event_pipe_drain_ch
 
         while (cl) {
             if (cl->buf->last_shadow) {
-                b = cl->buf->shadow;
-                b->pos = b->last = b->start;
-                b->shadow = NULL;
-
-                if (!(tl = ngx_alloc_chain_link(p->pool))) {
+                if (ngx_event_pipe_add_free_buf(p, cl->buf->shadow) != NGX_OK) {
                     return NGX_ABORT;
                 }
 
-                tl->buf = b;
-                tl->next = NULL;
-
-                ngx_event_pipe_add_free_buf(&p->free_raw_bufs, tl);
-
                 cl->buf->last_shadow = 0;
             }
 
--- a/src/event/ngx_event_pipe.h
+++ b/src/event/ngx_event_pipe.h
@@ -88,6 +88,7 @@ struct ngx_event_pipe_s {
 
 ngx_int_t ngx_event_pipe(ngx_event_pipe_t *p, int do_write);
 ngx_int_t ngx_event_pipe_copy_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf);
+ngx_int_t ngx_event_pipe_add_free_buf(ngx_event_pipe_t *p, ngx_buf_t *b);
 
 
 #endif /* _NGX_EVENT_PIPE_H_INCLUDED_ */
--- a/src/http/modules/ngx_http_chunked_filter.c
+++ b/src/http/modules/ngx_http_chunked_filter.c
@@ -67,7 +67,7 @@ static ngx_int_t ngx_http_chunked_body_f
     ngx_buf_t    *b;
     ngx_chain_t   out, tail, *cl, *tl, **ll;
 
-    if (in == NULL || !r->chunked) {
+    if (in == NULL || !r->chunked || r->header_only) {
         return ngx_http_next_body_filter(r, in);
     }
 
--- a/src/http/modules/ngx_http_fastcgi_handler.c
+++ b/src/http/modules/ngx_http_fastcgi_handler.c
@@ -1385,7 +1385,7 @@ static ngx_int_t ngx_http_fastcgi_input_
                                                ngx_buf_t *buf)
 {
     ngx_int_t                rc;
-    ngx_buf_t               *b;
+    ngx_buf_t               *b, **prev;
     ngx_str_t                line;
     ngx_chain_t             *cl;
     ngx_http_request_t      *r;
@@ -1399,6 +1399,7 @@ static ngx_int_t ngx_http_fastcgi_input_
     f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
 
     b = NULL;
+    prev = &buf->shadow;
 
     f->pos = buf->pos;
     f->last = buf->last;
@@ -1510,11 +1511,14 @@ static ngx_int_t ngx_http_fastcgi_input_
         ngx_memzero(b, sizeof(ngx_buf_t));
 
         b->pos = f->pos;
-        b->shadow = buf;
+        b->start = buf->start;
+        b->end = buf->end;
         b->tag = p->tag;
         b->temporary = 1;
         b->recycled = 1;
-        buf->shadow = b;
+
+        *prev = b;
+        prev = &b->shadow;
 
         if (!(cl = ngx_alloc_chain_link(p->pool))) {
             return NGX_ERROR;
@@ -1523,6 +1527,8 @@ static ngx_int_t ngx_http_fastcgi_input_
         cl->buf = b;
         cl->next = NULL;
 
+        /* STUB */ b->num = buf->num;
+
         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d", b->num);
 
         ngx_chain_add_link(p->in, p->last_in, cl);
@@ -1563,7 +1569,16 @@ static ngx_int_t ngx_http_fastcgi_input_
     }
 
     if (b) {
+        b->shadow = buf;
         b->last_shadow = 1;
+
+        return NGX_OK;
+    }
+
+    /* there is no data record in the buf, add it to free chain */
+
+    if (ngx_event_pipe_add_free_buf(p, buf) != NGX_OK) {
+        return NGX_ERROR;
     }
 
     return NGX_OK;
--- a/src/http/modules/ngx_http_gzip_filter.c
+++ b/src/http/modules/ngx_http_gzip_filter.c
@@ -471,8 +471,8 @@ static ngx_int_t ngx_http_gzip_body_filt
 
         /*
          * We preallocate a memory for zlib in one buffer (200K-400K), this
-         * dicreases a number of malloc() and free() calls and also probably
-         * dicreases a number of syscalls (sbrk() and so on).
+         * decreases a number of malloc() and free() calls and also probably
+         * decreases a number of syscalls (sbrk() and so on).
          * Besides we free this memory as soon as the gzipping will complete
          * and do not wait while a whole response will be sent to a client.
          *
--- a/src/http/modules/ngx_http_rewrite_handler.c
+++ b/src/http/modules/ngx_http_rewrite_handler.c
@@ -9,9 +9,10 @@
 #include <ngx_http.h>
 
 
-#define NGX_HTTP_REWRITE_COPY_MATCH  0
-#define NGX_HTTP_REWRITE_COPY_SHORT  1
-#define NGX_HTTP_REWRITE_COPY_LONG   2
+#define NGX_HTTP_REWRITE_COPY_CAPTURE  0
+#define NGX_HTTP_REWRITE_COPY_SHORT    1
+#define NGX_HTTP_REWRITE_COPY_LONG     2
+#define NGX_HTTP_REWRITE_START_ARGS    3
 
 
 typedef struct {
@@ -119,7 +120,7 @@ static ngx_int_t ngx_http_rewrite_handle
     uintptr_t                     data;
     ngx_int_t                     rc;
     ngx_uint_t                    i, m, n;
-    ngx_str_t                     uri;
+    ngx_str_t                     uri, args;
     ngx_http_rewrite_op_t        *op;
     ngx_http_rewrite_rule_t      *rule;
     ngx_http_rewrite_srv_conf_t  *scf;
@@ -176,13 +177,14 @@ static ngx_int_t ngx_http_rewrite_handle
         uri.len = rule[i].size;
 
         for (n = 1; n < (ngx_uint_t) rc; n++) {
-           uri.len += captures[2 * n + 1] - captures[2 * n];
+            uri.len += captures[2 * n + 1] - captures[2 * n];
         }
 
         if (!(uri.data = ngx_palloc(r->pool, uri.len))) {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }
 
+        args.data = NULL;
         p = uri.data;
 
         op = rule[i].ops.elts;
@@ -198,22 +200,34 @@ static ngx_int_t ngx_http_rewrite_handle
             } else if (op[n].op == NGX_HTTP_REWRITE_COPY_LONG) {
                 p = ngx_cpymem(p, (void *) op[n].data, op[n].len);
 
-            } else { /* NGX_HTTP_REWRITE_COPY_MATCH */
+            } else if (op[n].op == NGX_HTTP_REWRITE_START_ARGS) {
+                args.data = p;
+
+            } else { /* NGX_HTTP_REWRITE_COPY_CAPTURE */
                 m = 2 * op[n].data;
                 p = ngx_cpymem(p, &r->uri.data[captures[m]],
                                captures[m + 1] - captures[m]);
             }
         }
 
-        uri.len = p - uri.data;
+        if (args.data) {
+            uri.len = args.data - uri.data;
+            args.len = p - args.data;
+
+            r->args = args;
+
+        } else {
+            uri.len = p - uri.data;
+            args.len = 0;
+        }
+
+        r->uri = uri;
 
         if (scf->log) {
             ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
-                          "rewritten uri: \"%V\"", &uri);
+                          "rewritten uri: \"%V\", args: \"%V\"", &uri, &args);
         }
 
-        r->uri = uri;
-
         if (ngx_http_set_exten(r) != NGX_OK) {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }
@@ -359,7 +373,9 @@ static char *ngx_http_rewrite_rule(ngx_c
             return NGX_CONF_ERROR;
         }
 
-        for (i = 0; i < value[2].len; /* void */) {
+        i = 0;
+
+        while (i < value[2].len) {
 
             if (!(op = ngx_push_array(&rule->ops))) {
                 return NGX_CONF_ERROR;
@@ -372,7 +388,8 @@ static char *ngx_http_rewrite_rule(ngx_c
                 && value[2].data[i + 1] >= '1'
                 && value[2].data[i + 1] <= '9')
             {
-                op->op = NGX_HTTP_REWRITE_COPY_MATCH; 
+                op->op = NGX_HTTP_REWRITE_COPY_CAPTURE; 
+                op->len = 0;
                 op->data = value[2].data[++i] - '0';
 
                 if (rule->ncaptures < op->data) {
@@ -381,39 +398,53 @@ static char *ngx_http_rewrite_rule(ngx_c
 
                 i++;
 
-            } else {
+                continue;
+            }
+
+            if (value[2].data[i] == '?') {
+                op->op = NGX_HTTP_REWRITE_START_ARGS; 
+                op->len = 0;
+                op->data = 0;
+
                 i++;
 
-                while (i < value[2].len && value[2].data[i] != '$') {
-                    i++;
-                }
+                continue;
+            }
 
-                len = &value[2].data[i] - data;
-                rule->size += len;
+            i++;
 
-                if (len) {
-
-                    op->len = len;
+            while (i < value[2].len
+                   && value[2].data[i] != '$'
+                   && value[2].data[i] != '?')
+            {
+                i++;
+            }
 
-                    if (len <= sizeof(uintptr_t)) {
-                        op->op = NGX_HTTP_REWRITE_COPY_SHORT; 
-                        op->data = 0;
+            len = &value[2].data[i] - data;
+            rule->size += len;
+
+            if (len) {
+
+                op->len = len;
 
-                        while (len--) {
-                            op->data <<= 8;
-                            op->data |= data[len];
-                        }
+                if (len <= sizeof(uintptr_t)) {
+                    op->op = NGX_HTTP_REWRITE_COPY_SHORT; 
+                    op->data = 0;
 
-                    } else {
-                        op->op = NGX_HTTP_REWRITE_COPY_LONG;
+                    while (len--) {
+                        op->data <<= 8;
+                        op->data |= data[len];
+                    }
 
-                        if (!(p = ngx_palloc(cf->pool, len))) {
-                            return NGX_CONF_ERROR;
-                        }
+                } else {
+                    op->op = NGX_HTTP_REWRITE_COPY_LONG;
 
-                        ngx_memcpy(p, data, len);
-                        op->data = (uintptr_t) p;
+                    if (!(p = ngx_palloc(cf->pool, len))) {
+                        return NGX_CONF_ERROR;
                     }
+
+                    ngx_memcpy(p, data, len);
+                    op->data = (uintptr_t) p;
                 }
             }
         }
--- a/src/http/modules/ngx_http_static_handler.c
+++ b/src/http/modules/ngx_http_static_handler.c
@@ -76,7 +76,6 @@ static ngx_int_t ngx_http_static_handler
     ngx_chain_t                  out;
     ngx_file_info_t              fi;
     ngx_http_cleanup_t          *file_cleanup, *redirect_cleanup;
-    ngx_http_log_ctx_t          *ctx;
     ngx_http_core_loc_conf_t    *clcf;
     ngx_http_static_loc_conf_t  *slcf;
 #if (NGX_HTTP_CACHE)
@@ -476,8 +475,7 @@ static ngx_int_t ngx_http_static_handler
 
 #endif
 
-    ctx = log->data;
-    ctx->action = "sending response to client";
+    log->action = "sending response to client";
 
     file_cleanup->data.file.fd = fd;
     file_cleanup->data.file.name = name.data;
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -778,17 +778,17 @@ void ngx_http_proxy_close_connection(ngx
 }
 
 
-u_char *ngx_http_proxy_log_error(void *data, u_char *buf, size_t len)
+u_char *ngx_http_proxy_log_error(ngx_log_t *log, u_char *buf, size_t len)
 {
-    ngx_http_proxy_log_ctx_t *ctx = data;
-
     u_char                          *p;
     ngx_int_t                        escape;
     ngx_str_t                        uri;
     ngx_http_request_t              *r;
     ngx_peer_connection_t           *peer;
+    ngx_http_proxy_log_ctx_t        *ctx;
     ngx_http_proxy_upstream_conf_t  *uc;
 
+    ctx = log->data;
     r = ctx->proxy->request;
     uc = ctx->proxy->lcf->upstream;
     peer = &ctx->proxy->upstream->peer;
--- a/src/http/modules/proxy/ngx_http_proxy_handler.h
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.h
@@ -251,7 +251,7 @@ void ngx_http_proxy_check_broken_connect
 void ngx_http_proxy_busy_lock_handler(ngx_event_t *rev);
 void ngx_http_proxy_upstream_busy_lock(ngx_http_proxy_ctx_t *p);
 
-u_char *ngx_http_proxy_log_error(void *data, u_char *buf, size_t len);
+u_char *ngx_http_proxy_log_error(ngx_log_t *log, u_char *buf, size_t len);
 void ngx_http_proxy_finalize_request(ngx_http_proxy_ctx_t *p, int rc);
 void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p);
 
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -36,15 +36,6 @@ typedef struct ngx_http_in_addr_s  ngx_h
 
 
 struct ngx_http_log_ctx_s {
-    ngx_uint_t         connection;
-
-    /*
-     * we declare "action" as "char *" because the actions are usually
-     * the static strings and in the "u_char *" case we have to override
-     * all the time their types
-     */
-
-    char                *action;
     ngx_str_t           *client;
     ngx_http_request_t  *request;
 };
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -351,13 +351,10 @@ ngx_module_t  ngx_http_core_module = {
 
 void ngx_http_handler(ngx_http_request_t *r)
 {
-    ngx_http_log_ctx_t  *ctx;
+    r->connection->log->action = NULL;
 
     r->connection->unexpected_eof = 0;
 
-    ctx = r->connection->log->data;
-    ctx->action = NULL;
-
     switch (r->headers_in.connection_type) {
     case 0:
         if (r->http_version > NGX_HTTP_VERSION_10) {
@@ -541,6 +538,10 @@ ngx_int_t ngx_http_find_location_config(
         r->connection->sendfile = 0;
     }
 
+    if (r->keepalive && clcf->keepalive_timeout == 0) {
+        r->keepalive = 0;
+    }
+
     if (!clcf->tcp_nopush) {
         /* disable TCP_NOPUSH/TCP_CORK use */
         r->connection->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -35,7 +35,7 @@ static void ngx_http_lingering_close_han
 
 static void ngx_http_client_error(ngx_http_request_t *r,
                                   int client_error, int error);
-static u_char *ngx_http_log_error(void *data, u_char *buf, size_t len);
+static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
 
 
 /* NGX_HTTP_PARSE_... errors */
@@ -111,12 +111,14 @@ void ngx_http_init_connection(ngx_connec
         return;
     }
 
-    ctx->connection = c->number;
     ctx->client = &c->addr_text;
-    ctx->action = "reading client request line";
     ctx->request = NULL;
+
+    c->log->connection = c->number;
+    c->log->handler = ngx_http_log_error;
     c->log->data = ctx;
-    c->log->handler = ngx_http_log_error;
+    c->log->action = "reading client request line";
+
     c->log_error = NGX_ERROR_INFO;
 
     rev = c->read;
@@ -634,7 +636,7 @@ static void ngx_http_process_request_lin
                 return;
             }
 
-            ctx->action = "reading client request headers";
+            c->log->action = "reading client request headers";
 
             rev->event_handler = ngx_http_process_request_headers;
             ngx_http_process_request_headers(rev);
@@ -1099,7 +1101,7 @@ static ngx_int_t ngx_http_process_reques
         }
     }
 
-    if (r->method == NGX_HTTP_POST && r->headers_in.content_length_n <= 0) {
+    if (r->method == NGX_HTTP_POST && r->headers_in.content_length_n == -1) {
         return NGX_HTTP_PARSE_POST_WO_CL_HEADER;
     }
 
@@ -1608,7 +1610,6 @@ static void ngx_http_set_keepalive(ngx_h
     ngx_event_t               *rev, *wev;
     ngx_connection_t          *c;
     ngx_http_connection_t     *hc;
-    ngx_http_log_ctx_t        *ctx;
     ngx_http_core_srv_conf_t  *cscf;
     ngx_http_core_loc_conf_t  *clcf;
 
@@ -1617,8 +1618,7 @@ static void ngx_http_set_keepalive(ngx_h
 
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
 
-    ctx = c->log->data;
-    ctx->action = "closing request";
+    c->log->action = "closing request";
 
     hc = r->http_connection;
     b = r->header_in;
@@ -1682,7 +1682,7 @@ static void ngx_http_set_keepalive(ngx_h
         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
 
         hc->pipeline = 1;
-        ctx->action = "reading client pipelined request line";
+        c->log->action = "reading client pipelined request line";
         ngx_http_init_request(rev);
         return;
     }
@@ -1760,7 +1760,7 @@ static void ngx_http_set_keepalive(ngx_h
         }
     }
 
-    ctx->action = "keepalive";
+    c->log->action = "keepalive";
 
     if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
         if (ngx_tcp_push(c->fd) == NGX_ERROR) {
@@ -1776,8 +1776,10 @@ static void ngx_http_set_keepalive(ngx_h
         tcp_nodelay = 1;
     }
 
-    if (tcp_nodelay && clcf->tcp_nodelay && !c->tcp_nodelay) {
-
+    if (tcp_nodelay
+        && clcf->tcp_nodelay
+        && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
+    {
         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
 
         if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
@@ -1789,7 +1791,7 @@ static void ngx_http_set_keepalive(ngx_h
             return;
         }
 
-        c->tcp_nodelay = 1;
+        c->tcp_nodelay = NGX_TCP_NODELAY_SET;
     }
 
 #if 0
@@ -1809,7 +1811,6 @@ static void ngx_http_keepalive_handler(n
     ssize_t                 n;
     ngx_buf_t              *b;
     ngx_connection_t       *c;
-    ngx_http_log_ctx_t     *ctx;
     ngx_http_connection_t  *hc;
 
     c = rev->data;
@@ -1821,16 +1822,14 @@ static void ngx_http_keepalive_handler(n
         return;
     }
 
-    ctx = (ngx_http_log_ctx_t *) rev->log->data;
-
 #if (NGX_HAVE_KQUEUE)
 
     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
         if (rev->pending_eof) {
-            rev->log->handler = NULL;
+            c->log->handler = NULL;
             ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
                           "kevent() reported that client %V closed "
-                          "keepalive connection", ctx->client);
+                          "keepalive connection", &c->addr_text);
 #if (NGX_HTTP_SSL)
             if (c->ssl) {
                 c->ssl->no_send_shut = 1;
@@ -1889,18 +1888,19 @@ static void ngx_http_keepalive_handler(n
         return;
     }
 
-    rev->log->handler = NULL;
+    c->log->handler = NULL;
 
     if (n == 0) {
         ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
-                      "client %V closed keepalive connection", ctx->client);
+                      "client %V closed keepalive connection", &c->addr_text);
         ngx_http_close_connection(c);
         return;
     }
 
     b->last += n;
-    rev->log->handler = ngx_http_log_error;
-    ctx->action = "reading client request line";
+
+    c->log->handler = ngx_http_log_error;
+    c->log->action = "reading client request line";
 
     ngx_http_init_request(rev);
 }
@@ -2302,16 +2302,17 @@ static void ngx_http_client_error(ngx_ht
 }
 
 
-static u_char *ngx_http_log_error(void *data, u_char *buf, size_t len)
+static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
 {
-    ngx_http_log_ctx_t *ctx = data;
-
-    u_char *p;
+    u_char              *p;
+    ngx_http_log_ctx_t  *ctx;
 
     p = buf;
 
-    if (ctx->action) {
-        p = ngx_snprintf(p, len, " while %s", ctx->action);
+    ctx = log->data;
+
+    if (log->action) {
+        p = ngx_snprintf(p, len, " while %s", log->action);
         len -= p - buf;
     }
 
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -117,8 +117,8 @@ void ngx_http_upstream_init(ngx_http_req
     }
 
     u->peer.log = r->connection->log;
-    u->saved_ctx = r->connection->log->data;
-    u->saved_handler = r->connection->log->handler;
+    u->saved_log_ctx = r->connection->log->data;
+    u->saved_log_handler = r->connection->log->handler;
     r->connection->log->data = u->log_ctx;
     r->connection->log->handler = u->log_handler;
 
@@ -160,6 +160,14 @@ static void ngx_http_upstream_check_brok
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, 0,
                    "http upstream check client, write event:%d", ev->write);
 
+    c = ev->data;
+    r = c->data;
+    u = r->upstream;
+
+    if (u->peer.connection == NULL) {
+        return;
+    }
+
 #if (NGX_HAVE_KQUEUE)
 
     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
@@ -174,10 +182,6 @@ static void ngx_http_upstream_check_brok
             ev->error = 1;
         }
 
-        c = ev->data;
-        r = c->data;
-        u = r->upstream;
-
         if (!u->cachable && u->peer.connection) {
             ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
                           "kevent() reported that client closed "
@@ -203,8 +207,6 @@ static void ngx_http_upstream_check_brok
 
 #endif
 
-    c = ev->data;
-
     n = recv(c->fd, buf, 1, MSG_PEEK);
 
     err = ngx_socket_errno;
@@ -218,9 +220,6 @@ static void ngx_http_upstream_check_brok
         return;
     }
 
-    r = c->data;
-    u = r->upstream;
-
     if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) {
         if (ngx_del_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) {
             ngx_http_upstream_finalize_request(r, u,
@@ -242,8 +241,7 @@ static void ngx_http_upstream_check_brok
 
         ev->error = 1;
 
-    } else {
-        /* n == 0 */
+    } else { /* n == 0 */
         err = 0;
     }
 
@@ -272,10 +270,8 @@ static void ngx_http_upstream_connect(ng
 {
     ngx_int_t            rc;
     ngx_connection_t    *c;
-    ngx_http_log_ctx_t  *ctx;
 
-    ctx = r->connection->log->data;
-    ctx->action = "connecting to upstream";
+    r->connection->log->action = "connecting to upstream";
 
     r->connection->single_connection = 0;
 
@@ -413,9 +409,8 @@ static void ngx_http_upstream_reinit(ngx
 static void ngx_http_upstream_send_request(ngx_http_request_t *r,
                                            ngx_http_upstream_t *u)
 {
-    int                  rc;
-    ngx_connection_t    *c;
-    ngx_http_log_ctx_t  *ctx;
+    int                rc;
+    ngx_connection_t  *c;
     
     c = u->peer.connection;
 
@@ -437,8 +432,7 @@ static void ngx_http_upstream_send_reque
 
 #endif
 
-    ctx = c->log->data;
-    ctx->action = "sending request to upstream";
+    c->log->action = "sending request to upstream";
 
     rc = ngx_output_chain(&u->output,
                           u->request_sent ? NULL : r->request_body->bufs);
@@ -515,7 +509,6 @@ static void ngx_http_upstream_send_reque
 {
     ngx_connection_t     *c;
     ngx_http_request_t   *r;
-    ngx_http_log_ctx_t   *ctx;
     ngx_http_upstream_t  *u;
 
     c = wev->data;
@@ -526,8 +519,7 @@ static void ngx_http_upstream_send_reque
                    "http upstream send request handler");
 
     if (wev->timedout) {
-        ctx = c->log->data;
-        ctx->action = "sending request to upstream";
+        c->log->action = "sending request to upstream";
         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
         return;
     }
@@ -548,7 +540,6 @@ static void ngx_http_upstream_process_he
     ngx_int_t             rc;
     ngx_connection_t     *c;
     ngx_http_request_t   *r;
-    ngx_http_log_ctx_t   *ctx;
     ngx_http_upstream_t  *u;
 
     c = rev->data;
@@ -556,10 +547,9 @@ static void ngx_http_upstream_process_he
     u = r->upstream;
 
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
-                   "http upstream process handler");
+                   "http upstream process header");
 
-    ctx = c->log->data;
-    ctx->action = "reading response header from upstream";
+    c->log->action = "reading response header from upstream";
 
     if (rev->timedout) {
         ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_TIMEOUT);
@@ -576,7 +566,7 @@ static void ngx_http_upstream_process_he
 
         u->header_in.pos = u->header_in.start;
         u->header_in.last = u->header_in.start;
-        u->header_in.end = u->header_in.last + u->conf->header_buffer_size;
+        u->header_in.end = u->header_in.start + u->conf->header_buffer_size;
         u->header_in.temporary = 1;
 
         u->header_in.tag = u->output.tag;
@@ -815,7 +805,6 @@ static void ngx_http_upstream_process_bo
 {
     ngx_connection_t     *c;
     ngx_http_request_t   *r;
-    ngx_http_log_ctx_t   *ctx;
     ngx_http_upstream_t  *u;
     ngx_event_pipe_t     *p;
 
@@ -823,17 +812,15 @@ static void ngx_http_upstream_process_bo
     r = c->data;
     u = r->upstream;
 
-    ctx = ev->log->data;
-
     if (ev->write) {
-        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
-                       "http proxy process downstream");
-        ctx->action = "sending to client";
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                       "http upstream process downstream");
+        c->log->action = "sending to client";
     
     } else {
-        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
-                       "http proxy process upstream");
-        ctx->action = "reading upstream body";
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                       "http upstream process upstream");
+        c->log->action = "reading upstream";
     }
     
     p = &u->pipe;
@@ -882,8 +869,8 @@ static void ngx_http_upstream_process_bo
 #endif
 
         if (p->upstream_done || p->upstream_eof || p->upstream_error) {
-            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, 0,
-                           "http proxy upstream exit: %p", p->out);
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                           "http upstream exit: %p", p->out);
 #if 0
             ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
 #endif
@@ -893,8 +880,8 @@ static void ngx_http_upstream_process_bo
     }
 
     if (p->downstream_error) {
-        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
-                       "http proxy downstream error");
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                       "http upstream downstream error");
 
         if (!u->cachable && u->peer.connection) {
             ngx_http_upstream_finalize_request(r, u, 0);
@@ -976,7 +963,7 @@ static void ngx_http_upstream_next(ngx_h
 
             if (u->stale && (u->conf->use_stale & ft_type)) {
                 ngx_http_upstream_finalize_request(r, u,
-                                       ngx_http_proxy_send_cached_response(r));
+                                       ngx_http_send_cached_response(r));
                 return;
             }
 
@@ -1010,8 +997,8 @@ static void ngx_http_upstream_finalize_r
                                                ngx_http_upstream_t *u,
                                                ngx_int_t rc)
 {
-    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "finalize http upstream request");
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "finalize http upstream request: %i", rc);
 
     u->finalize_request(r, rc);
 
@@ -1023,15 +1010,17 @@ static void ngx_http_upstream_finalize_r
         ngx_close_connection(u->peer.connection);
     }
 
+    u->peer.connection = NULL;
+
     if (u->header_sent
         && (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE))
     {
         rc = 0;
     }
 
-    if (u->saved_ctx) {
-        r->connection->log->data = u->saved_ctx;
-        r->connection->log->handler = u->saved_handler;
+    if (u->saved_log_ctx) {
+        r->connection->log->data = u->saved_log_ctx;
+        r->connection->log->handler = u->saved_log_handler;
     }
 
     if (u->pipe.temp_file) {
@@ -1043,7 +1032,7 @@ static void ngx_http_upstream_finalize_r
 #if 0
     if (u->cache) {
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                       "http proxy cache fd: %d",
+                       "http upstream cache fd: %d",
                        u->cache->ctx.file.fd);
     }
 #endif
@@ -1057,6 +1046,8 @@ static void ngx_http_upstream_finalize_r
 #endif
     }
 
+    r->connection->log->action = "sending to client";
+
     if (rc == 0 && r->main == NULL) {
         rc = ngx_http_send_last(r);
     }
@@ -1111,24 +1102,24 @@ static u_char *ngx_http_upstream_log_sta
 }
 
 
-u_char *ngx_http_upstream_log_error(void *data, u_char *buf, size_t len)
+u_char *ngx_http_upstream_log_error(ngx_log_t *log, u_char *buf, size_t len)
 {
-    ngx_http_log_ctx_t *ctx = data;
-    
     u_char                 *p;
     ngx_int_t               escape;
     ngx_str_t               uri;
+    ngx_http_log_ctx_t     *ctx;
     ngx_http_request_t     *r;
     ngx_http_upstream_t    *u;
     ngx_peer_connection_t  *peer;
 
+    ctx = log->data;
     r = ctx->request;
     u = r->upstream;
     peer = &u->peer;
 
     p = ngx_snprintf(buf, len,
                      " while %s, client: %V, URL: %V, upstream: %V%V%s%V",
-                     ctx->action,
+                     log->action,
                      &r->connection->addr_text,
                      &r->unparsed_uri,
                      &u->schema,
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -92,8 +92,8 @@ struct ngx_http_upstream_s {
 
     ngx_http_log_ctx_t         *log_ctx;
     ngx_log_handler_pt          log_handler;
-    ngx_http_log_ctx_t         *saved_ctx;
-    ngx_log_handler_pt          saved_handler;
+    ngx_http_log_ctx_t         *saved_log_ctx;
+    ngx_log_handler_pt          saved_log_handler;
 
     /* used to parse an upstream HTTP header */
     ngx_uint_t                  status;
@@ -113,7 +113,7 @@ struct ngx_http_upstream_s {
 
 
 void ngx_http_upstream_init(ngx_http_request_t *r);
-u_char *ngx_http_upstream_log_error(void *data, u_char *buf, size_t len);
+u_char *ngx_http_upstream_log_error(ngx_log_t *log, u_char *buf, size_t len);
 
 
 extern char *ngx_http_upstream_header_errors[];
--- a/src/http/ngx_http_write_filter.c
+++ b/src/http/ngx_http_write_filter.c
@@ -81,7 +81,18 @@ ngx_int_t ngx_http_write_filter(ngx_http
 #if 1
         if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
             ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                              "zero size buf in writer");
+                          "zero size buf in writer "
+                          "t:%d r:%d f:%d %p %p-%p %p %O-%O",
+                          cl->buf->temporary,
+                          cl->buf->recycled,
+                          cl->buf->in_file,
+                          cl->buf->start,
+                          cl->buf->pos,
+                          cl->buf->last,
+                          cl->buf->file,
+                          cl->buf->file_pos,
+                          cl->buf->file_last);
+
             ngx_debug_point();
         }
 #endif
@@ -120,7 +131,18 @@ ngx_int_t ngx_http_write_filter(ngx_http
 #if 1
         if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
             ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                              "zero size buf in writer");
+                          "zero size buf in writer "
+                          "t:%d r:%d f:%d %p %p-%p %p %O-%O",
+                          cl->buf->temporary,
+                          cl->buf->recycled,
+                          cl->buf->in_file,
+                          cl->buf->start,
+                          cl->buf->pos,
+                          cl->buf->last,
+                          cl->buf->file,
+                          cl->buf->file_pos,
+                          cl->buf->file_last);
+
             ngx_debug_point();
         }
 #endif
@@ -161,15 +183,16 @@ ngx_int_t ngx_http_write_filter(ngx_http
     }
 
     if (size == 0 && !c->buffered) {
-        if (!last) {
-            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                          "the http output chain is empty");
+        if (last) {
+            return NGX_OK;
+        }
 
-            ngx_debug_point();
+        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                      "the http output chain is empty");
 
-            return NGX_ERROR;
-        }
-        return NGX_OK;
+        ngx_debug_point();
+
+        return NGX_ERROR;
     }
 
     sent = c->sent;
@@ -192,7 +215,7 @@ ngx_int_t ngx_http_write_filter(ngx_http
 
     ctx->out = chain;
 
-    if (chain || c->buffered) {
+    if (chain || (last && c->buffered)) {
         return NGX_AGAIN;
     }
 
--- a/src/os/unix/ngx_channel.c
+++ b/src/os/unix/ngx_channel.c
@@ -38,6 +38,8 @@ ngx_int_t ngx_write_channel(ngx_socket_t
         *(int *) CMSG_DATA(&cmsg.cm) = ch->fd;
     }
 
+    msg.msg_flags = 0;
+
 #else
 
     if (ch->fd == -1) {
@@ -58,7 +60,6 @@ ngx_int_t ngx_write_channel(ngx_socket_t
     msg.msg_namelen = 0;
     msg.msg_iov = iov;
     msg.msg_iovlen = 1;
-    msg.msg_flags = 0;
 
     n = sendmsg(s, &msg, 0);
 
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -279,11 +279,17 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
                 }
             }
 
-            if (rc == 0 && sent == 0) {
+            /*
+             * sendfile() in FreeBSD 3.x-4.x may return value >= 0
+             * on success, although only 0 is documented
+             */
+
+            if (rc >= 0 && sent == 0) {
 
                 /*
-                 * rc and sent equal to zero when someone has truncated
-                 * the file, so the offset became beyond the end of the file
+                 * if rc is OK and sent equal to zero, then someone
+                 * has truncated the file, so the offset became beyond
+                 * the end of the file
                  */
 
                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
--- a/src/os/unix/ngx_linux_sendfile_chain.c
+++ b/src/os/unix/ngx_linux_sendfile_chain.c
@@ -89,7 +89,18 @@ ngx_chain_t *ngx_linux_sendfile_chain(ng
 #if 1
             if (!ngx_buf_in_memory(cl->buf) && !cl->buf->in_file) {
                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
-                              "zero size buf in sendfile");
+                              "zero size buf in sendfile "
+                              "t:%d r:%d f:%d %p %p-%p %p %O-%O",
+                              cl->buf->temporary,
+                              cl->buf->recycled,
+                              cl->buf->in_file,
+                              cl->buf->start,
+                              cl->buf->pos,
+                              cl->buf->last,
+                              cl->buf->file,
+                              cl->buf->file_pos,
+                              cl->buf->file_last);
+
                 ngx_debug_point();
             }
 #endif
@@ -129,7 +140,7 @@ ngx_chain_t *ngx_linux_sendfile_chain(ng
         {
             /* the TCP_CORK and TCP_NODELAY are mutually exclusive */
 
-            if (c->tcp_nodelay) {
+            if (c->tcp_nodelay == NGX_TCP_NODELAY_SET) {
 
                 tcp_nodelay = 0;
 
@@ -146,20 +157,20 @@ ngx_chain_t *ngx_linux_sendfile_chain(ng
 
                     if (err != NGX_EINTR) { 
                         wev->error = 1;
-                        ngx_connection_error(c, ngx_socket_errno,
+                        ngx_connection_error(c, err,
                                              "setsockopt(TCP_NODELAY) failed");
                         return NGX_CHAIN_ERROR;
                     }
 
                 } else {
-                    c->tcp_nodelay = 0;
+                    c->tcp_nodelay = NGX_TCP_NODELAY_UNSET;
 
                     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
                                    "no tcp_nodelay");
                 }
             }
 
-            if (!c->tcp_nodelay) {
+            if (c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) {
 
                 if (ngx_tcp_nopush(c->fd) == NGX_ERROR) {
                     err = ngx_errno;
--- a/src/os/unix/rfork_thread.S
+++ b/src/os/unix/rfork_thread.S
@@ -4,7 +4,6 @@
  */
 
 
-
 #include <sys/syscall.h>
 #include <machine/asm.h>
 
@@ -19,14 +18,14 @@ ENTRY(rfork_thread)
 	mov	%esp, %ebp
 	push	%esi
 
-	mov	12(%ebp), %esi	# the stack address
+	mov	12(%ebp), %esi	# the thread stack address
 
 	sub	$4, %esi
 	mov	20(%ebp), %eax	# the thread argument
 	mov	%eax, (%esi)
 
 	sub	$4, %esi
-	mov	16(%ebp), %eax	# the start thread address
+	mov	16(%ebp), %eax	# the thread start address
 	mov	%eax, (%esi)
 
 	push	8(%ebp)		# rfork(2) flags
@@ -41,8 +40,7 @@ ENTRY(rfork_thread)
 parent:
 	add	$8, %esp
 	pop	%esi
-	mov	%ebp, %esp
-	pop	%ebp
+	leave
 	ret
 
 child:
@@ -59,8 +57,7 @@ child:
 error:
 	add	$8, %esp
 	pop	%esi
-	mov	%ebp, %esp
-	pop	%ebp
+	leave
 	PIC_PROLOGUE
 
 	/* libc's cerror: jmp  PIC_PLT(HIDENAME(cerror)) */