changeset 87:5f6d848dcbef

nginx-0.0.1-2003-05-13-20:02:32 import
author Igor Sysoev <igor@sysoev.ru>
date Tue, 13 May 2003 16:02:32 +0000
parents 3973260705cc
children 674d333f4296
files src/core/nginx.c src/core/ngx_alloc.c src/core/ngx_connection.h src/core/ngx_listen.h src/core/ngx_modules.c src/event/modules/ngx_kqueue_module.c src/event/modules/ngx_poll_module.c src/event/modules/ngx_select_module.c src/event/ngx_event.c src/event/ngx_event.h src/event/ngx_event_accept.c src/event/ngx_event_accept.h src/event/ngx_event_timer.c src/http/modules/ngx_http_static_handler.c src/http/ngx_http.h src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_event.c
diffstat 18 files changed, 442 insertions(+), 448 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -67,9 +67,11 @@ int main(int argc, char *const *argv)
 
 #endif
 
+#if 0
     if (ngx_os_init(&ngx_log) == NGX_ERROR) {
         exit(1);
     }
+#endif
 
     ngx_init_array(ngx_listening_sockets, ngx_pool, 10, sizeof(ngx_listen_t),
                    1);
--- a/src/core/ngx_alloc.c
+++ b/src/core/ngx_alloc.c
@@ -73,6 +73,7 @@ void ngx_destroy_pool(ngx_pool_t *pool)
             break;
         }
     }
+    pool = NULL;
 }
 
 void *ngx_palloc(ngx_pool_t *pool, size_t size)
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -26,7 +26,7 @@ struct ngx_connection_s {
 
     off_t             sent;
 
-    int             (*handler)(ngx_connection_t *c);
+    void            (*handler)(ngx_connection_t *c);
     void             *ctx;
     ngx_server_t     *servers;
 
--- a/src/core/ngx_listen.h
+++ b/src/core/ngx_listen.h
@@ -22,7 +22,7 @@ typedef struct {
     int               protocol;
     int               flags;      /* Winsock2 flags */
 
-    int             (*handler)(ngx_connection_t *c); /* handler of accepted
+    void            (*handler)(ngx_connection_t *c); /* handler of accepted
                                                         connection */
     void             *ctx;        /* ngx_http_conf_ctx_t, for example */
     void             *servers;    /* array of ngx_http_in_addr_t, for example */
--- a/src/core/ngx_modules.c
+++ b/src/core/ngx_modules.c
@@ -29,7 +29,9 @@ ngx_module_t *ngx_modules[] = {
     /* &ngx_http_ssi_filter_module, */
 
     &ngx_http_index_module,
+/*
     &ngx_http_proxy_module,
+*/
 
     NULL
 };
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -343,9 +343,7 @@ int ngx_kqueue_process_events(ngx_log_t 
         case EVFILT_AIO:
             ev->ready = 1;
 
-            if (ev->event_handler(ev) == NGX_ERROR) {
-                ev->close_handler(ev);
-            }
+            ev->event_handler(ev);
 
             break;
 
--- a/src/event/modules/ngx_poll_module.c
+++ b/src/event/modules/ngx_poll_module.c
@@ -251,9 +251,7 @@ int ngx_poll_process_events(ngx_log_t *l
             }
         }
 
-        if (ev->event_handler(ev) == NGX_ERROR) {
-            ev->close_handler(ev);
-        }
+        ev->event_handler(ev);
     }
 
     if (ready != 0) {
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -306,8 +306,7 @@ int ngx_select_process_events(ngx_log_t 
                 ngx_select_del_event(ev, NGX_READ_EVENT, 0);
         }
 
-        if (ev->event_handler(ev) == NGX_ERROR)
-            ev->close_handler(ev);
+        ev->event_handler(ev);
     }
 
     if (ready != 0) {
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -9,7 +9,6 @@
 #include <ngx_listen.h>
 #include <ngx_connection.h>
 #include <ngx_event.h>
-#include <ngx_event_accept.h>
 
 #include <ngx_select_module.h>
 
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -28,9 +28,11 @@ typedef struct {
 
 struct ngx_event_s {
     void            *data;
+    void           (*event_handler)(ngx_event_t *ev);
 
-    int            (*event_handler)(ngx_event_t *ev);
+#if 0
     int            (*close_handler)(ngx_event_t *ev);
+#endif
     void            *context;
     char            *action;
 
@@ -39,7 +41,9 @@ struct ngx_event_s {
     ngx_event_t     *prev;     /* queue in mutex(), aio_read(), aio_write()  */
     ngx_event_t     *next;     /*                                            */
 
+#if 0
     int            (*timer_handler)(ngx_event_t *ev);
+#endif
     ngx_event_t     *timer_prev;
     ngx_event_t     *timer_next;
 
@@ -165,7 +169,7 @@ typedef struct {
 #define NGX_HAVE_KQUEUE_EVENT   8
 
 /* The event filter supports low water mark - kqueue's NOTE_LOWAT.
-   Early kqueue implementations have no NOTE_LOWAT so we need a separate flag */
+   kqueue in FreeBSD 4.1-4.2 has no NOTE_LOWAT so we need a separate flag */
 #define NGX_HAVE_LOWAT_EVENT    0x00000010
 
 /* The event filter notifies only the changes (the edges)
@@ -294,6 +298,9 @@ extern int                   ngx_event_f
 #endif
 
 
+void ngx_event_accept(ngx_event_t *ev);
+
+
 ssize_t ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size);
 int ngx_event_close_connection(ngx_event_t *ev);
 
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -7,14 +7,9 @@
 #include <ngx_log.h>
 #include <ngx_connection.h>
 #include <ngx_event.h>
-#include <ngx_event_close.h>
-#include <ngx_event_accept.h>
 
 
-/* This function should always return NGX_OK even there are some failures
-   because if we return NGX_ERROR then listening socket would be closed */
-
-int ngx_event_accept(ngx_event_t *ev)
+void ngx_event_accept(ngx_event_t *ev)
 {
     int                instance;
     socklen_t          len;
@@ -37,9 +32,16 @@ int ngx_event_accept(ngx_event_t *ev)
 #endif
 
     do {
-        ngx_test_null(pool, ngx_create_pool(ls->pool_size, ev->log), NGX_OK);
+        pool = ngx_create_pool(ls->pool_size, ev->log);
+        if (pool == NULL) {
+            return;
+        }
 
-        ngx_test_null(sa, ngx_palloc(pool, ls->socklen), NGX_OK);
+        sa = ngx_palloc(pool, ls->socklen);
+        if (sa == NULL) {
+            return;
+        }
+
         len = ls->socklen;
 
         s = accept(ls->fd, sa, &len);
@@ -50,12 +52,12 @@ int ngx_event_accept(ngx_event_t *ev)
             if (err == NGX_EAGAIN) {
                 ngx_log_error(NGX_LOG_NOTICE, ev->log, err,
                               "EAGAIN while accept %s", ls->addr_text.data);
-                return NGX_OK;
+                return;
             }
 
             ngx_log_error(NGX_LOG_ALERT, ev->log, err,
                           "accept %s failed", ls->addr_text.data);
-            return NGX_OK;
+            return;
         }
 
 
@@ -66,7 +68,7 @@ int ngx_event_accept(ngx_event_t *ev)
             if (ngx_blocking(s) == -1) {
                 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
                               ngx_blocking_n " %s failed", ls->addr_text.data);
-                return NGX_OK;
+                return;
             }
         }
 #endif
@@ -78,14 +80,14 @@ int ngx_event_accept(ngx_event_t *ev)
             if (ngx_nonblocking(s) == -1) {
                 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
                            ngx_nonblocking_n " %s failed", ls->addr_text.data);
-                return NGX_OK;
+                return;
             }
         }
 #else
         if (ngx_nonblocking(s) == -1) {
             ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_socket_errno,
                           ngx_nonblocking_n " %s failed", ls->addr_text.data);
-            return NGX_OK;
+            return;
         }
 #endif
 
@@ -133,13 +135,13 @@ int ngx_event_accept(ngx_event_t *ev)
 
         /* STUB ? */ wev->timer = rev->timer = 10000;
 
-        wev->timer_handler = rev->timer_handler = ngx_event_close_connection;
-        wev->close_handler = rev->close_handler = ngx_event_close_connection;
-
         c->ctx = ls->ctx;
         c->servers = ls->servers;
 
-        ngx_test_null(c->log, ngx_palloc(c->pool, sizeof(ngx_log_t)), NGX_OK);
+        c->log = ngx_palloc(c->pool, sizeof(ngx_log_t));
+        if (c->log == NULL) {
+            return;
+        }
         ngx_memcpy(c->log, ev->log, sizeof(ngx_log_t));
         rev->log = wev->log = c->log;
 
@@ -159,7 +161,7 @@ int ngx_event_accept(ngx_event_t *ev)
 
         if (ngx_event_flags & NGX_HAVE_EDGE_EVENT) {
             if (ngx_edge_add_event(ev) == NGX_ERROR) {
-                return NGX_OK;
+                return;
             }
         }
 
@@ -183,5 +185,5 @@ int ngx_event_accept(ngx_event_t *ev)
 #endif
     } while (ev->available);
   
-    return NGX_OK;
+    return;
 }
deleted file mode 100644
--- a/src/event/ngx_event_accept.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _NGX_EVENT_ACCEPT_H_INCLUDED_
-#define _NGX_EVENT_ACCEPT_H_INCLUDED_
-
-
-#include <ngx_event.h>
-
-int ngx_event_accept(ngx_event_t *ev);
-
-
-#endif /* _NGX_EVENT_ACCEPT_H_INCLUDED_ */
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -136,9 +136,7 @@ void ngx_event_expire_timers(ngx_msec_t 
                 ev->timedout = 1;
             }
 
-            if (ev->event_handler(ev) == NGX_ERROR) {
-                ev->close_handler(ev);
-            }
+            ev->event_handler(ev);
         }
     }
 }
--- a/src/http/modules/ngx_http_static_handler.c
+++ b/src/http/modules/ngx_http_static_handler.c
@@ -1,6 +1,6 @@
 
 #include <ngx_config.h>
-
+#include <ngx_core.h>
 #include <ngx_string.h>
 #include <ngx_file.h>
 #include <ngx_hunk.h>
@@ -14,9 +14,9 @@ ngx_http_module_t  ngx_http_static_modul
 
 int ngx_http_static_handler(ngx_http_request_t *r)
 {
-    int  rc;
-    ngx_err_t    err;
-    ngx_hunk_t  *h;
+    int                  rc;
+    ngx_err_t            err;
+    ngx_hunk_t          *h;
     ngx_http_log_ctx_t  *ctx;
 
 #if 0
@@ -40,10 +40,7 @@ int ngx_http_static_handler(ngx_http_req
                       "ngx_http_static_handler: "
                       ngx_open_file_n " %s failed", r->file.name.data);
 
-        if (err == NGX_ENOENT) {
-            return NGX_HTTP_NOT_FOUND;
-
-        } else if (err == NGX_ENOTDIR) {
+        if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
             return NGX_HTTP_NOT_FOUND;
 
         } else {
@@ -126,11 +123,10 @@ int ngx_http_static_handler(ngx_http_req
     ngx_test_null(h->file, ngx_pcalloc(r->pool, sizeof(ngx_file_t)),
                   NGX_HTTP_INTERNAL_SERVER_ERROR);
 
-    rc = ngx_http_send_header(r);
+    ngx_http_send_header(r);
     if (r->header_only)
-        return rc;
+        return NGX_OK;
 
-#if 1
 
     h->type = NGX_HUNK_FILE|NGX_HUNK_LAST;
     h->file_pos = 0;
@@ -141,44 +137,14 @@ int ngx_http_static_handler(ngx_http_req
 
     rc = ngx_http_output_filter(r, h);
 
-    ngx_log_debug(r->connection->log, "0 output_filter: %d" _ rc);
-
-#else
-
-#define BLK 10000
-
-    {
-    int  i, s;
-    s = ngx_file_size(r->file.info);
-
-    for (i = 0; i < s; i += BLK) {
-        ngx_test_null(h, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)),
-                      NGX_HTTP_INTERNAL_SERVER_ERROR);
-
-        ngx_test_null(h->file, ngx_pcalloc(r->pool, sizeof(ngx_file_t)),
-                      NGX_HTTP_INTERNAL_SERVER_ERROR);
+    if (r->main == NULL) {
+        if (rc == NGX_AGAIN) {
+            ngx_http_set_write_handler(r);
 
-        h->type = NGX_HUNK_FILE;
-        if (s - i <= BLK) {
-            h->type |= NGX_HUNK_LAST;
+        } else {
+            ngx_http_finalize_request(r, 0);
         }
-
-        h->pos.file = i;
-        h->last.file = i + BLK;
-        if (h->last.file > s) {
-            h->last.file = s;
-        }
-
-        h->file->fd = r->file.fd;
-        h->file->log = r->connection->log;
-
-        rc = ngx_http_output_filter(r, h);
-
-        ngx_log_debug(r->connection->log, "0 output_filter: %d" _ rc);
-    }
     }
 
-#endif
-
-    return rc;
+    return NGX_OK;
 }
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -235,6 +235,13 @@ void ngx_http_init_connection(ngx_connec
 int ngx_parse_http_request_line(ngx_http_request_t *r);
 int ngx_parse_http_header_line(ngx_http_request_t *r, ngx_hunk_t *h);
 int ngx_http_handler(ngx_http_request_t *r);
+void ngx_http_finalize_request(ngx_http_request_t *r, int error);
+void ngx_http_set_write_handler(ngx_http_request_t *r);
+
+
+void ngx_http_close_request(ngx_http_request_t *r, int error);
+void ngx_http_close_connection(ngx_connection_t *c);
+
 
 
 int ngx_http_init_client_request_body(ngx_http_request_t *r, int size);
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -517,7 +517,8 @@ int ngx_http_redirect(ngx_http_request_t
 
     /* log request */
 
-    return ngx_http_close_request(r, 0);
+    ngx_http_close_request(r, 0);
+    return NGX_OK;
 }
 
 
@@ -529,48 +530,8 @@ int ngx_http_error(ngx_http_request_t *r
     /* log request */
 
     ngx_http_special_response_handler(r, error);
-    return ngx_http_close_request(r, 0);
-}
-
-
-int ngx_http_close_request(ngx_http_request_t *r, int error)
-{
-    ngx_connection_t    *c;
-    ngx_http_log_ctx_t  *ctx;
-
-    c = r->connection;
-    if (error) {
-        r->headers_out.status = error;
-    }
-
-    ngx_http_log_handler(r);
-
-    if (r->file.fd != NGX_INVALID_FILE) {
-        if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) {
-            ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
-                          ngx_close_file_n " \"%s\" failed", r->file.name.data);
-        }
-    }
-
-    /* ctx->url was allocated from r->pool */
-    ctx = (ngx_http_log_ctx_t *) c->log->data;
-    ctx->url = NULL;
-
-    ngx_destroy_pool(r->pool);
-
-    if (c->read->timer_set) {
-        ngx_del_timer(c->read);
-        c->read->timer_set = 0;
-    }
-
-    if (c->write->timer_set) {
-        ngx_del_timer(c->write);
-        c->write->timer_set = 0;
-    }
-
-    ngx_log_debug(c->log, "http request closed");
-
-    return 0;
+    ngx_http_close_request(r, 0);
+    return NGX_OK;
 }
 
 
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -103,8 +103,5 @@ int ngx_http_core_translate_handler(ngx_
 int ngx_http_internal_redirect(ngx_http_request_t *r, ngx_str_t uri);
 int ngx_http_error(ngx_http_request_t *r, int error);
 
-int ngx_http_finalize_request(ngx_http_request_t *r, int error);
-int ngx_http_close_request(ngx_http_request_t *r, int error);
-
 
 #endif /* _NGX_HTTP_CORE_H_INCLUDED_ */
--- a/src/http/ngx_http_event.c
+++ b/src/http/ngx_http_event.c
@@ -21,26 +21,18 @@
 static void ngx_http_init_request(ngx_event_t *ev);
 static void ngx_http_process_request_line(ngx_event_t *rev);
 static void ngx_http_process_request_headers(ngx_event_t *rev);
-
-
-
 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
 
-
+static void ngx_http_writer(ngx_event_t *ev);
 
-static int ngx_http_process_request(ngx_event_t *ev);
-static int ngx_http_process_request_header_line(ngx_http_request_t *r);
-static int ngx_http_request_handler(ngx_http_request_t *r, int error);
-
-static int ngx_http_writer(ngx_event_t *ev);
 static int ngx_http_block_read(ngx_event_t *ev);
 static int ngx_http_read_discarded_body(ngx_event_t *ev);
-static int ngx_http_set_keepalive(ngx_http_request_t *r);
-static int ngx_http_keepalive_handler(ngx_event_t *ev);
-static int ngx_http_set_lingering_close(ngx_http_request_t *r);
-static int ngx_http_lingering_close_handler(ngx_event_t *ev);
 
-static int ngx_http_close_connection(ngx_connection_t *c);
+static void ngx_http_set_keepalive(ngx_http_request_t *r);
+static void ngx_http_keepalive_handler(ngx_event_t *ev);
+static void ngx_http_set_lingering_close(ngx_http_request_t *r);
+static void ngx_http_lingering_close_handler(ngx_event_t *ev);
+
 static void ngx_http_header_parse_error(ngx_http_request_t *r, int parse_err);
 static size_t ngx_http_log_error(void *data, char *buf, size_t len);
 
@@ -69,8 +61,12 @@ static ngx_http_header_t headers_in[] = 
     { ngx_string("Content-Length"), 
                             offsetof(ngx_http_headers_in_t, content_length) },
 
+#if 0
+
     { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) },
 
+#endif
+
     { ngx_null_string, 0 }
 };
 
@@ -135,8 +131,6 @@ void ngx_http_init_connection(ngx_connec
     if (ngx_add_event(rev, NGX_READ_EVENT, event) == NGX_ERROR) {
         ngx_http_close_connection(c);
     }
-
-    return;
 }
 
 
@@ -202,8 +196,6 @@ static void ngx_http_init_request(ngx_ev
 
     rev->event_handler = ngx_http_process_request_line;
     ngx_http_process_request_line(rev);
-
-    return;
 }
 
 
@@ -268,7 +260,7 @@ static void ngx_http_process_request_lin
 
         r->request_line.len = r->request_end - r->request_start;
 
-        /* if the large client header is enabled then
+        /* if the large client headers are enabled then
            we need to copy a request line */
 
         if (ngx_http_large_client_header) {
@@ -346,7 +338,8 @@ static void ngx_http_process_request_lin
         }
 
         if (r->http_version == NGX_HTTP_VERSION_9) {
-            /* STUB */ return;
+            ngx_http_handler(r);
+            return;
         }
 
         lcx->action = "reading client request headers";
@@ -358,12 +351,18 @@ static void ngx_http_process_request_lin
             r->header_in->pos = r->header_in->last = r->header_in->start;
         }
 
+        rev->event_handler = ngx_http_process_request_headers;
+        ngx_http_process_request_headers(rev);
+
+        return;
+
     } else if (rc != NGX_AGAIN) {
 
         /* there was error while a request line parsing */
 
         ngx_http_header_parse_error(r, rc);
         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+
         return;
     }
 
@@ -383,6 +382,7 @@ static void ngx_http_process_request_lin
             if (offset == 0) {
                 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI);
                 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
+
                 return;
             }
 
@@ -405,59 +405,108 @@ static void ngx_http_process_request_lin
         } else {
             ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_URI);
             ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
-            return;
         }
     }
 
-    rev->event_handler = ngx_http_process_request_headers;
-    ngx_http_process_request_headers(rev);
-
     return;
 }
 
 
 static void ngx_http_process_request_headers(ngx_event_t *rev)
 {
-    int                  rc, offset;
+    int                  rc, i, offset;
     size_t               len;
     ssize_t              n;
+    ngx_table_elt_t     *h;
     ngx_connection_t    *c;
     ngx_http_request_t  *r;
     ngx_http_log_ctx_t  *ctx;
 
+    c = (ngx_connection_t *) rev->data;
+    r = (ngx_http_request_t *) c->data;
+
+    ngx_log_debug(rev->log, "http process request header line");
+
     if (rev->timedout) {
         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
         ngx_http_close_connection(c);
         return;
     }
 
-    n = ngx_http_read_request_header(r);
-
-    if (n == NGX_AGAIN || n == NGX_ERROR) {
-        return;
-    }
+    rc = NGX_AGAIN;
 
     for ( ;; ) {
+        if (rc == NGX_AGAIN) {
+            n = ngx_http_read_request_header(r);
+
+            if (n == NGX_AGAIN || n == NGX_ERROR) {
+                return;
+            }
+        }
+
         rc = ngx_parse_http_header_line(r, r->header_in);
 
-        /* a header line has been parsed successfully */
+        if (rc == NGX_OK) {
+
+            /* a header line has been parsed successfully */
+
+            h = ngx_push_table(r->headers_in.headers);
+            if (h == NULL) {
+                ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+                ngx_http_close_connection(c);
+                return;
+            }
+
+            h->key.len = r->header_name_end - r->header_name_start;
+            h->value.len = r->header_end - r->header_start;
+
+            /* if the large client headers are enabled then
+               we need to copy the header name and value */
 
-        if (rc == NGX_OK) {
-            if (ngx_http_process_request_header_line(r) == NGX_ERROR) {
-                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+            if (ngx_http_large_client_header) {
+                h->key.data = ngx_palloc(r->pool,
+                                         h->key.len + 1 + h->value.len + 1);
+                if (h->key.data == NULL) {
+                    ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+                    ngx_http_close_connection(c);
+                    return;
+                }
+
+                h->value.data = h->key.data + h->key.len + 1;
+                ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
+                ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
+
+            } else {
+                h->key.data = r->header_name_start;
+                h->key.data[h->key.len] = '\0';
+                h->value.data = r->header_start;
+                h->value.data[h->value.len] = '\0';
             }
 
+            for (i = 0; headers_in[i].name.len != 0; i++) {
+                if (headers_in[i].name.len != h->key.len) {
+                    continue;
+                }
+
+                if (ngx_strcasecmp(headers_in[i].name.data, h->key.data) == 0) {
+                    *((ngx_table_elt_t **)
+                        ((char *) &r->headers_in + headers_in[i].offset)) = h;
+                }
+            }
+
+            ngx_log_debug(r->connection->log, "HTTP header: '%s: %s'" _
+                          h->key.data _ h->value.data);
+
             if (ngx_http_large_client_header
                 && r->header_in->pos == r->header_in->last)
             {
                 r->header_in->pos = r->header_in->last = r->header_in->start;
             }
 
-            return NGX_AGAIN;
+        } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
 
-        /* a whole header has been parsed successfully */
+            /* a whole header has been parsed successfully */
 
-        } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
             ngx_log_debug(r->connection->log, "HTTP header done");
 
             if (r->headers_in.host) {
@@ -472,7 +521,8 @@ static void ngx_http_process_request_hea
                 if (r->http_version > NGX_HTTP_VERSION_10) {
                     ngx_http_header_parse_error(r,
                                                 NGX_HTTP_PARSE_NO_HOST_HEADER);
-                    return NGX_HTTP_BAD_REQUEST;
+                    ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+                    return;
                 }
                 r->headers_in.host_name_len = 0;
             }
@@ -484,18 +534,22 @@ static void ngx_http_process_request_hea
                 if (r->headers_in.content_length_n == NGX_ERROR) {
                     ngx_http_header_parse_error(r,
                                              NGX_HTTP_PARSE_INVALID_CL_HEADER);
-                    return NGX_HTTP_BAD_REQUEST;
+                    ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+                    return;
                 }
             }
 
-            r->state_handler = NULL;
-            return NGX_OK;
-
-        /* there was error while a header line parsing */
+            ngx_http_handler(r);
+            return;
 
         } else if (rc != NGX_AGAIN) {
+
+            /* there was error while a header line parsing */
+
             ngx_http_header_parse_error(r, rc);
-            return NGX_HTTP_BAD_REQUEST;
+            ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+
+            return;
         }
 
         /* NGX_AGAIN: a header line parsing is still not complete */
@@ -511,7 +565,8 @@ static void ngx_http_process_request_hea
                 if (offset == 0) {
                     ngx_http_header_parse_error(r,
                                                 NGX_HTTP_PARSE_TOO_LONG_HEADER);
-                    return NGX_HTTP_BAD_REQUEST;
+                    ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+                    return;
                 }
 
                 ngx_memcpy(r->header_in->start, r->header_name_start,
@@ -526,216 +581,17 @@ static void ngx_http_process_request_hea
 
             } else {
                 ngx_http_header_parse_error(r, NGX_HTTP_PARSE_TOO_LONG_HEADER);
-                return NGX_HTTP_BAD_REQUEST;
+                ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
+                return;
             }
-
-        }
-
-        return NGX_AGAIN;
-    }
-}
-
-
-static int ngx_http_process_request_header_line(ngx_http_request_t *r)
-{
-    int               i;
-    ngx_table_elt_t  *h;
-
-    ngx_test_null(h, ngx_push_table(r->headers_in.headers), NGX_ERROR);
-
-    h->key.len = r->header_name_end - r->header_name_start;
-    h->value.len = r->header_end - r->header_start;
-
-    /* if the large client headers are enabled then
-       we need to copy the header name and value */
-
-    if (ngx_http_large_client_header) {
-        ngx_test_null(h->key.data, ngx_palloc(r->pool, h->key.len + 1),
-                      NGX_ERROR);
-        ngx_test_null(h->value.data, ngx_palloc(r->pool, h->value.len + 1),
-                      NGX_ERROR);
-        ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
-        ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
-
-    } else {
-        h->key.data = r->header_name_start;
-        h->key.data[h->key.len] = '\0';
-        h->value.data = r->header_start;
-        h->value.data[h->value.len] = '\0';
-    }
-
-    for (i = 0; headers_in[i].name.len != 0; i++) {
-        if (headers_in[i].name.len != h->key.len) {
-            continue;
-        }
-
-        if (ngx_strcasecmp(headers_in[i].name.data, h->key.data) == 0) {
-            *((ngx_table_elt_t **)
-                        ((char *) &r->headers_in + headers_in[i].offset)) = h;
         }
     }
-
-    ngx_log_debug(r->connection->log, "HTTP header: '%s: %s'" _
-                  h->key.data _ h->value.data);
-
-    return NGX_OK;
-}
-
-
-int ngx_http_finalize_request(ngx_http_request_t *r, int error)
-{
-    int                        rc, event;
-    ngx_msec_t                 timeout;
-    ngx_event_t               *rev, *wev;
-    ngx_http_core_loc_conf_t  *lcf;
-
-    rc = error;
-
-    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
-
-        rev = r->connection->read;
-
-        if (rev->timer_set) {
-            ngx_del_timer(rev);
-        } else {
-            rev->timer_set = 1;
-        }
-
-        rc = ngx_http_special_response_handler(r, rc);
-    }
-
-    /* a handler has done its work completely */
-
-    if (rc == NGX_OK) {
-
-        if (r->keepalive != 0) {
-            return ngx_http_set_keepalive(r);
-        }
-
-        if (r->lingering_close) {
-            return ngx_http_set_lingering_close(r);
-        }
-
-        return ngx_http_close_request(r, 0);
-    }
-
-    /* NGX_AGAIN: a handler has done its work
-                  but the transfer is still not completed */
-
-    wev = r->connection->write;
-    wev->event_handler = ngx_http_writer;
-
-    if (wev->delayed && wev->ready) {
-        return NGX_AGAIN;
-    }
-
-    lcf = (ngx_http_core_loc_conf_t *)
-                        ngx_http_get_module_loc_conf(r->main ? r->main : r,
-                                                     ngx_http_core_module_ctx);
-    ngx_add_timer(wev, lcf->send_timeout);
-    wev->timer_set = 1;
-
-#if (USE_KQUEUE)
-
-#if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */
-    wev->lowat = lcf->send_lowat;
-#endif
-
-    if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT) == NGX_ERROR) {
-        return ngx_http_close_request(r, 0);
-    }
-
-    return rc;
-
-#else
-
-    /* aio, iocp, epoll */
-
-    if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) {
-        return rc;
-    }
-
-#if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */
-
-    if (ngx_event_flags & NGX_HAVE_LOWAT_EVENT) {
-        wev->lowat = lcf->send_lowat;
-    }
-
-#endif
-
-    /* kqueue */
-
-    if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
-        event = NGX_CLEAR_EVENT;
-
-    /* select, poll, /dev/poll */
-
-    } else {
-        event = NGX_LEVEL_EVENT;
-    }
-
-    if (ngx_add_event(wev, NGX_WRITE_EVENT, event) == NGX_ERROR) {
-        return ngx_http_close_request(r, 0);
-    }
-
-    return rc;
-
-#endif /* USE_KQUEUE */
-}
-
-
-static int ngx_http_writer(ngx_event_t *wev)
-{
-    int                        rc;
-    ngx_msec_t                 timeout;
-    ngx_connection_t          *c;
-    ngx_http_request_t        *r;
-    ngx_http_core_loc_conf_t  *lcf;
-
-    c = (ngx_connection_t *) wev->data;
-    r = (ngx_http_request_t *) c->data;
-
-    rc = ngx_http_output_filter(r, NULL);
-
-    ngx_log_debug(c->log, "output filter in writer: %d" _ rc);
-
-    if (rc == NGX_AGAIN) {
-
-        lcf = (ngx_http_core_loc_conf_t *)
-                        ngx_http_get_module_loc_conf(r->main ? r->main : r,
-                                                     ngx_http_core_module_ctx);
-        if (wev->timer_set) {
-            ngx_del_timer(wev);
-        } else {
-            wev->timer_set = 1;
-        }
-
-        ngx_add_timer(wev, lcf->send_timeout);
-
-        return rc;
-    }
-
-    if (rc == NGX_ERROR)
-        return rc;
-
-    /* rc == NGX_OK */
-
-    ngx_log_debug(c->log, "http writer done");
-
-    if (r->keepalive != 0) {
-        return ngx_http_set_keepalive(r);
-    }
-
-    if (r->lingering_close) {
-        return ngx_http_set_lingering_close(r);
-    }
-
-    return ngx_http_close_request(r, 0);
 }
 
 
 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r)
 {
+    int           event;
     ssize_t       n;
     ngx_event_t  *rev;
 
@@ -762,16 +618,34 @@ static ssize_t ngx_http_read_request_hea
             r->header_timeout_set = 1;
         }
 
+        if (!rev->active) {
+            if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
+                /* kqueue */
+                event = NGX_CLEAR_EVENT;
+
+            } else {
+                /* select, poll, /dev/poll */
+                event = NGX_LEVEL_EVENT;
+            }
+
+            if (ngx_add_event(rev, NGX_READ_EVENT, event) == NGX_ERROR) {
+                ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+                ngx_http_close_connection(r->connection);
+                return NGX_ERROR;
+            }
+        }
+
         return NGX_AGAIN;
     }
 
     if (n == 0) {
         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
                       "client closed prematurely connection");
+    }
 
     if (n == 0 || n == NGX_ERROR) {
         ngx_http_close_request(r, NGX_HTTP_BAD_REQUEST);
-        ngx_http_close_connection(c);
+        ngx_http_close_connection(r->connection);
         return NGX_ERROR;
     }
 
@@ -781,6 +655,166 @@ static ssize_t ngx_http_read_request_hea
 }
 
 
+void ngx_http_finalize_request(ngx_http_request_t *r, int error)
+{
+    int           rc, event;
+    ngx_msec_t    timeout;
+    ngx_event_t  *rev, *wev;
+
+    rc = error;
+
+    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
+
+        rev = r->connection->read;
+
+        if (rev->timer_set) {
+            ngx_del_timer(rev);
+        } else {
+            rev->timer_set = 1;
+        }
+
+        rc = ngx_http_special_response_handler(r, rc);
+    }
+
+    rev = r->connection->read;
+    if (rev->timer_set) {
+        ngx_del_timer(rev);
+        rev->timer_set = 0;
+    }
+
+    wev = r->connection->write;
+    if (wev->timer_set) {
+        ngx_del_timer(wev);
+        wev->timer_set = 0;
+    }
+
+    if (r->keepalive != 0) {
+        ngx_http_set_keepalive(r);
+
+    } else if (r->lingering_close) {
+        ngx_http_set_lingering_close(r);
+
+    } else {
+        ngx_http_close_request(r, 0);
+        ngx_http_close_connection(r->connection);
+    }
+}
+
+
+void ngx_http_set_write_handler(ngx_http_request_t *r)
+{
+    int                        event;
+    ngx_event_t               *wev;
+    ngx_http_core_loc_conf_t  *lcf;
+
+    wev = r->connection->write;
+    wev->event_handler = ngx_http_writer;
+
+    if (wev->delayed && wev->ready) {
+        return;
+    }
+
+    lcf = (ngx_http_core_loc_conf_t *)
+                        ngx_http_get_module_loc_conf(r->main ? r->main : r,
+                                                     ngx_http_core_module_ctx);
+    ngx_add_timer(wev, lcf->send_timeout);
+    wev->timer_set = 1;
+
+    if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) {
+        /* aio, iocp, epoll */
+        return;
+    }
+
+#if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */
+
+    if (ngx_event_flags & NGX_HAVE_LOWAT_EVENT) {
+        wev->lowat = lcf->send_lowat;
+    }
+
+#endif
+
+    if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) {
+        /* kqueue */
+        event = NGX_CLEAR_EVENT;
+
+    } else {
+        /* select, poll, /dev/poll */
+        event = NGX_LEVEL_EVENT;
+    }
+
+    if (ngx_add_event(wev, NGX_WRITE_EVENT, event) == NGX_ERROR) {
+        ngx_http_close_request(r, 0);
+        ngx_http_close_connection(r->connection);
+    }
+}
+
+
+static void ngx_http_writer(ngx_event_t *wev)
+{
+    int                        rc;
+    ngx_msec_t                 timeout;
+    ngx_event_t               *rev;
+    ngx_connection_t          *c;
+    ngx_http_request_t        *r;
+    ngx_http_core_loc_conf_t  *lcf;
+
+    c = (ngx_connection_t *) wev->data;
+    r = (ngx_http_request_t *) c->data;
+
+    rc = ngx_http_output_filter(r, NULL);
+
+    ngx_log_debug(c->log, "writer output filter: %d" _ rc);
+
+    if (rc == NGX_AGAIN) {
+
+        lcf = (ngx_http_core_loc_conf_t *)
+                        ngx_http_get_module_loc_conf(r->main ? r->main : r,
+                                                     ngx_http_core_module_ctx);
+        if (wev->timer_set) {
+            ngx_del_timer(wev);
+        } else {
+            wev->timer_set = 1;
+        }
+
+        ngx_add_timer(wev, lcf->send_timeout);
+
+        return;
+    }
+
+    if (rc == NGX_ERROR) {
+        ngx_http_close_request(r, 0);
+        ngx_http_close_connection(c);
+        return;
+    }
+
+    /* rc == NGX_OK */
+
+    ngx_log_debug(c->log, "http writer done");
+
+    rev = r->connection->read;
+    if (rev->timer_set) {
+        ngx_del_timer(rev);
+        rev->timer_set = 0;
+    }
+
+    if (wev->timer_set) {
+        ngx_del_timer(wev);
+        wev->timer_set = 0;
+    }
+
+    if (r->keepalive != 0) {
+        ngx_http_set_keepalive(r);
+    }
+
+    if (r->lingering_close) {
+        ngx_http_set_lingering_close(r);
+
+    } else {
+        ngx_http_close_request(r, 0);
+    }
+}
+
+
 static int ngx_http_block_read(ngx_event_t *ev)
 {
     ngx_log_debug(ev->log, "http read blocked");
@@ -805,6 +839,13 @@ static int ngx_http_block_read(ngx_event
 }
 
 
+/* STUB */
+int ngx_http_discard_body(ngx_http_request_t *r)
+{
+    return NGX_OK;
+}
+
+#if 0
 /* TODO */
 int ngx_http_discard_body(ngx_http_request_t *r)
 {
@@ -874,9 +915,10 @@ static int ngx_http_read_discarded_body(
     /* XXX: what if r->client_content_length == 0 ? */
     return NGX_OK;
 }
+#endif
 
 
-static int ngx_http_set_keepalive(ngx_http_request_t *r)
+static void ngx_http_set_keepalive(ngx_http_request_t *r)
 {
     int                  len, blocked;
     ngx_hunk_t          *h;
@@ -893,8 +935,10 @@ static int ngx_http_set_keepalive(ngx_ht
 
     if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
         if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) {
-            return NGX_ERROR;
+            ngx_http_close_connection(c);
+            return;
         }
+
         blocked = 1;
         rev->blocked = 0;
 
@@ -922,7 +966,8 @@ static int ngx_http_set_keepalive(ngx_ht
 
         c->pipeline = 1;
         ctx->action = "reading client pipelined request line";
-        return ngx_http_init_request(rev);
+        ngx_http_init_request(rev);
+        return;
     }
 
     c->pipeline = 0;
@@ -933,31 +978,20 @@ static int ngx_http_set_keepalive(ngx_ht
 
     if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
         if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
-            return NGX_ERROR;
+            ngx_http_close_connection(c);
+            return;
         }
     }
 
     ctx->action = "keepalive";
 
-#if (HAVE_AIO_EVENT) /* aio, iocp */
-
     if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) || blocked) {
-        return ngx_http_keepalive_handler(rev);
+        ngx_http_keepalive_handler(rev);
     }
-
-#else
-
-    if (blocked) {
-        return ngx_http_keepalive_handler(rev);
-    }
-
-#endif
-
-    return NGX_OK;
 }
 
 
-static int ngx_http_keepalive_handler(ngx_event_t *rev)
+static void ngx_http_keepalive_handler(ngx_event_t *rev)
 {
     ssize_t n;
     ngx_connection_t    *c;
@@ -968,7 +1002,8 @@ static int ngx_http_keepalive_handler(ng
     ngx_log_debug(c->log, "http keepalive handler");
 
     if (rev->timedout) {
-        return NGX_ERROR;  /* to close connection */
+        ngx_http_close_connection(c);
+        return;
     }
 
     /* MSIE closes a keepalive connection with RST flag
@@ -979,8 +1014,13 @@ static int ngx_http_keepalive_handler(ng
     n = ngx_event_recv(c, c->buffer->last, c->buffer->end - c->buffer->last);
     rev->ignore_econnreset = 0;
 
-    if (n == NGX_AGAIN || n == NGX_ERROR) {
-        return n;
+    if (n == NGX_AGAIN) {
+        return;
+    }
+
+    if (n == NGX_ERROR) {
+        ngx_http_close_connection(c);
+        return;
     }
 
     lctx = (ngx_http_log_ctx_t *) rev->log->data;
@@ -989,18 +1029,19 @@ static int ngx_http_keepalive_handler(ng
     if (n == 0) {
         ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
                       "client %s closed keepalive connection", lctx->client);
-        return NGX_ERROR;  /* to close connection */
+        ngx_http_close_connection(c);
+        return;
     }
 
     c->buffer->last += n;
     rev->log->handler = ngx_http_log_error;
     lctx->action = "reading client request line";
 
-    return ngx_http_init_request(rev);
+    ngx_http_init_request(rev);
 }
 
 
-static int ngx_http_set_lingering_close(ngx_http_request_t *r)
+static void ngx_http_set_lingering_close(ngx_http_request_t *r)
 {
     ngx_event_t               *rev;
     ngx_connection_t          *c;
@@ -1013,7 +1054,7 @@ static int ngx_http_set_lingering_close(
                      ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx);
 
     r->lingering_time = ngx_time() + lcf->lingering_time / 1000;
-    r->connection->read->event_handler = ngx_http_lingering_close_handler;
+    rev->event_handler = ngx_http_lingering_close_handler;
 
     if (rev->timer_set) {
         ngx_del_timer(rev);
@@ -1025,46 +1066,36 @@ static int ngx_http_set_lingering_close(
 
     if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
         if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) {
-            return ngx_http_close_request(r, 0);
+            ngx_http_close_request(r, 0);
+            ngx_http_close_connection(c);
+            return;
         }
         rev->blocked = 0;
     }
 
-#if !(USE_KQUEUE)
-
     if (c->write->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
         if (ngx_del_event(c->write, NGX_WRITE_EVENT, 0) == NGX_ERROR) {
-            return ngx_http_close_request(r, 0);
+            ngx_http_close_request(r, 0);
+            ngx_http_close_connection(c);
+            return;
         }
     }
 
-#endif
-
     if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
         ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno,
                       ngx_shutdown_socket_n " failed");
-        return ngx_http_close_request(r, 0);
-    }
-
-#if (USE_KQUEUE)
-
-    if (rev->ready) {
-        return ngx_http_lingering_close_handler(rev);
+        ngx_http_close_request(r, 0);
+        ngx_http_close_connection(c);
+        return;
     }
 
-#else
-
     if (rev->ready || (ngx_event_flags & NGX_HAVE_AIO_EVENT)) {
-        return ngx_http_lingering_close_handler(rev);
+        ngx_http_lingering_close_handler(rev);
     }
-
-#endif
-
-    return NGX_OK;
 }
 
 
-static int ngx_http_lingering_close_handler(ngx_event_t *rev)
+static void ngx_http_lingering_close_handler(ngx_event_t *rev)
 {
     ssize_t                    n;
     ngx_msec_t                 timer;
@@ -1078,12 +1109,16 @@ static int ngx_http_lingering_close_hand
     ngx_log_debug(c->log, "http lingering close handler");
 
     if (rev->timedout) {
-        return ngx_http_close_request(r, 0);
+        ngx_http_close_request(r, 0);
+        ngx_http_close_connection(c);
+        return;
     }
 
     timer = r->lingering_time - ngx_time();
     if (timer <= 0) {
-        return ngx_http_close_request(r, 0);
+        ngx_http_close_request(r, 0);
+        ngx_http_close_connection(c);
+        return;
     }
 
     lcf = (ngx_http_core_loc_conf_t *)
@@ -1100,9 +1135,13 @@ static int ngx_http_lingering_close_hand
             r->discarded_buffer = r->header_in->last;
 
         } else {
-            ngx_test_null(r->discarded_buffer,
-                          ngx_palloc(c->pool, lcf->discarded_buffer_size),
-                          ngx_http_close_request(r, 0));
+            r->discarded_buffer = ngx_palloc(c->pool,
+                                             lcf->discarded_buffer_size);
+            if (r->discarded_buffer) {
+                ngx_http_close_request(r, 0);
+                ngx_http_close_connection(c);
+                return;
+            }
         }
     }
 
@@ -1112,7 +1151,9 @@ static int ngx_http_lingering_close_hand
         ngx_log_debug(c->log, "lingering read: %d" _ n);
 
         if (n == NGX_ERROR || n == 0) {
-            return ngx_http_close_request(r, 0);
+            ngx_http_close_request(r, 0);
+            ngx_http_close_connection(c);
+            return;
         }
 
     } while (rev->ready);
@@ -1129,15 +1170,48 @@ static int ngx_http_lingering_close_hand
     }
     ngx_add_timer(rev, timer);
 
-    return NGX_OK;
+    return;
 }
 
 
-static void ngx_http_close_connection(ngx_connection_t *c)
+void ngx_http_close_request(ngx_http_request_t *r, int error)
+{
+    ngx_http_log_ctx_t  *ctx;
+
+    ngx_log_debug(r->connection->log, "close http request");
+
+    if (r->pool == NULL) {
+        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                      "http already closed");
+        return;
+    }
+
+    if (error) {
+        r->headers_out.status = error;
+    }
+
+    ngx_http_log_handler(r);
+
+    if (r->file.fd != NGX_INVALID_FILE) {
+        if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) {
+            ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
+                          ngx_close_file_n " \"%s\" failed", r->file.name.data);
+        }
+    }
+
+    /* ctx->url was allocated from r->pool */
+    ctx = (ngx_http_log_ctx_t *) r->connection->log->data;
+    ctx->url = NULL;
+
+    ngx_destroy_pool(r->pool);
+}
+
+
+void ngx_http_close_connection(ngx_connection_t *c)
 {
     ngx_log_debug(c->log, "close connection: %d" _ c->fd);
 
-    if (c->fd == -1) {
+    if (c->pool == NULL) {
         ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed");
         return;
     }
@@ -1168,13 +1242,6 @@ static void ngx_http_close_connection(ng
     c->fd = -1;
 
     ngx_destroy_pool(c->pool);
-
-    return;
-}
-
-static int ngx_http_close_connection0(ngx_event_t *ev)
-{
-    return ngx_event_close_connection(ev);
 }