From b603dd4b43b8c4b2cf8a1e74a87fd5799ab537b6 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Wed, 26 Aug 2009 16:04:05 +0000 Subject: [PATCH] request reference counter --- src/http/ngx_http_core_module.c | 8 +- src/http/ngx_http_request.c | 127 +++++++++++++++++++++++++------ src/http/ngx_http_request.h | 1 + src/http/ngx_http_request_body.c | 2 + 4 files changed, 110 insertions(+), 28 deletions(-) diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index e79dd1cd2..988d8f0e8 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1260,10 +1260,6 @@ ngx_http_core_content_phase(ngx_http_request_t *r, rc = ph->handler(r); - if (rc == NGX_DONE) { - return NGX_OK; - } - if (rc != NGX_DECLINED) { ngx_http_finalize_request(r, rc); return NGX_OK; @@ -2126,6 +2122,7 @@ ngx_http_subrequest(ngx_http_request_t *r, sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1; r->main->subrequests++; + r->main->count++; *psr = sr; @@ -2178,6 +2175,7 @@ ngx_http_internal_redirect(ngx_http_request_t *r, #endif r->internal = 1; + r->main->count++; ngx_http_handler(r); @@ -2192,6 +2190,8 @@ ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name) ngx_http_core_loc_conf_t **clcfp; ngx_http_core_main_conf_t *cmcf; + r->main->count++; + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); if (cscf->named_locations) { diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index 4cd1d8f61..f071cf523 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -36,6 +36,9 @@ static ngx_int_t ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len); static void ngx_http_request_handler(ngx_event_t *ev); +static void ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc); +static void ngx_http_terminate_handler(ngx_http_request_t *r); +static void ngx_http_finalize_connection(ngx_http_request_t *r); static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r); static void ngx_http_writer(ngx_http_request_t *r); static void ngx_http_request_finalizer(ngx_http_request_t *r); @@ -46,7 +49,7 @@ static void ngx_http_set_lingering_close(ngx_http_request_t *r); static void ngx_http_lingering_close_handler(ngx_event_t *ev); static ngx_int_t ngx_http_post_action(ngx_http_request_t *r); static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error); -static void ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error); +static void ngx_http_free_request(ngx_http_request_t *r, ngx_int_t error); static void ngx_http_log_request(ngx_http_request_t *r); static void ngx_http_close_connection(ngx_connection_t *c); @@ -478,6 +481,7 @@ ngx_http_init_request(ngx_event_t *rev) c->destroyed = 0; r->main = r; + r->count = 1; tp = ngx_timeofday(); r->start_sec = tp->sec; @@ -1828,16 +1832,16 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) ngx_http_request_t *pr; ngx_http_core_loc_conf_t *clcf; - if (rc == NGX_DONE) { - /* the request pool may be already destroyed */ - return; - } - c = r->connection; - ngx_log_debug4(NGX_LOG_DEBUG_HTTP, c->log, 0, - "http finalize request: %d, \"%V?%V\" %d", - rc, &r->uri, &r->args, r == c->data); + ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http finalize request: %d, \"%V?%V\" a:%d, c:%d", + rc, &r->uri, &r->args, r == c->data, r->main->count); + + if (rc == NGX_DONE) { + ngx_http_finalize_connection(r); + return; + } if (rc == NGX_OK && r->filter_finalize) { c->error = 1; @@ -1860,15 +1864,11 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST || c->error) { - if (rc > 0 && r->headers_out.status == 0) { - r->headers_out.status = rc; - } - if (ngx_http_post_action(r) == NGX_OK) { return; } - ngx_http_close_request(r, 0); + ngx_http_terminate_request(r, rc); return; } @@ -1877,7 +1877,7 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) || rc == NGX_HTTP_NO_CONTENT) { if (rc == NGX_HTTP_CLOSE) { - ngx_http_close_request(r, rc); + ngx_http_terminate_request(r, rc); return; } @@ -1903,7 +1903,7 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) if (r->buffered || r->postponed) { if (ngx_http_set_write_handler(r) != NGX_OK) { - ngx_http_close_request(r->main, 0); + ngx_http_terminate_request(r, 0); } return; @@ -1921,6 +1921,8 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) if (r == c->data) { + r->main->count--; + if (!r->logged) { clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); @@ -1955,7 +1957,8 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) } if (ngx_http_post_request(pr) != NGX_OK) { - ngx_http_close_request(r->main, 0); + r->main->count++; + ngx_http_terminate_request(r, 0); return; } @@ -1969,7 +1972,7 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) if (r->buffered || c->buffered || r->postponed) { if (ngx_http_set_write_handler(r) != NGX_OK) { - ngx_http_close_request(r, 0); + ngx_http_terminate_request(r, 0); } return; @@ -2010,6 +2013,68 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc) return; } + ngx_http_finalize_connection(r); +} + + +static void +ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc) +{ + ngx_http_cleanup_t *cln; + ngx_http_request_t *mr; + + mr = r->main; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http terminate request count: %d", mr->count); + + cln = mr->cleanup; + mr->cleanup = NULL; + + while (cln) { + if (cln->handler) { + cln->handler(cln->data); + } + + cln = cln->next; + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http terminate cleanup count: %d", mr->count); + + if (mr->write_event_handler) { + mr->posted_requests = NULL; + mr->write_event_handler = ngx_http_terminate_handler; + (void) ngx_http_post_request(mr); + return; + } + + ngx_http_close_request(mr, rc); +} + + +static void +ngx_http_terminate_handler(ngx_http_request_t *r) +{ + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http terminate handler count: %d", r->count); + + r->count = 1; + + ngx_http_close_request(r, 0); +} + + +static void +ngx_http_finalize_connection(ngx_http_request_t *r) +{ + ngx_http_core_loc_conf_t *clcf; + + if (r->main->count != 1) { + ngx_http_close_request(r, 0); + return; + } + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (!ngx_terminate @@ -2319,7 +2384,7 @@ ngx_http_set_keepalive(ngx_http_request_t *r) } } - ngx_http_request_done(r, 0); + ngx_http_free_request(r, 0); c->data = hc; @@ -2766,19 +2831,33 @@ ngx_http_post_action(ngx_http_request_t *r) static void -ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error) +ngx_http_close_request(ngx_http_request_t *r, ngx_int_t rc) { ngx_connection_t *c; + r = r->main; c = r->connection; - ngx_http_request_done(r->main, error); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http request count: %d", r->count); + + if (r->count == 0) { + ngx_log_error(NGX_LOG_ALERT, c->log, 0, "http request count is zero"); + } + + r->count--; + + if (r->count) { + return; + } + + ngx_http_free_request(r, rc); ngx_http_close_connection(c); } static void -ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error) +ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc) { ngx_log_t *log; struct linger linger; @@ -2813,8 +2892,8 @@ ngx_http_request_done(ngx_http_request_t *r, ngx_int_t error) #endif - if (error && r->headers_out.status == 0) { - r->headers_out.status = error; + if (rc > 0 && (r->headers_out.status == 0 || r->connection->sent == 0)) { + r->headers_out.status = rc; } log->action = "logging request"; diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h index 51f8419b4..7b984fb27 100644 --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -502,6 +502,7 @@ struct ngx_http_request_s { #endif unsigned subrequests:8; + unsigned count:8; /* used to parse HTTP headers */ diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c index 9d47300f5..775bb2642 100644 --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -37,6 +37,8 @@ ngx_http_read_client_request_body(ngx_http_request_t *r, ngx_http_request_body_t *rb; ngx_http_core_loc_conf_t *clcf; + r->main->count++; + if (r->request_body || r->discard_body) { post_handler(r); return NGX_OK;