From 6be51e769ab042e5ba4f6c0b4308a5a7693c4928 Mon Sep 17 00:00:00 2001 From: "Yichun Zhang (agentzh)" Date: Thu, 12 Feb 2015 17:19:02 -0800 Subject: [PATCH] bugfix: applied the upstream_filter_finalize patch to the nginx core to fix corrupted $upstream_response_time values when filter_finalize and error_page are both used. thanks Daniel Bento for the report. --- ...ginx-1.7.10-upstream_filter_finalize.patch | 66 +++++++++++++++++++ util/mirror-tarballs | 4 ++ 2 files changed, 70 insertions(+) create mode 100644 patches/nginx-1.7.10-upstream_filter_finalize.patch diff --git a/patches/nginx-1.7.10-upstream_filter_finalize.patch b/patches/nginx-1.7.10-upstream_filter_finalize.patch new file mode 100644 index 0000000..0f5cd6c --- /dev/null +++ b/patches/nginx-1.7.10-upstream_filter_finalize.patch @@ -0,0 +1,66 @@ +# HG changeset patch +# User Yichun Zhang +# Date 1423789183 28800 +# Thu Feb 12 16:59:43 2015 -0800 +# Node ID 8b3d7171f35e74c8bea3234e88d8977b4f11f815 +# Parent f3f25ad09deee27485050a75732e5f46ab1b18b3 +Upstream: fixed $upstream_response_time for filter_finalize + error_page. + +ngx_http_upstream_finalize_request() is always called twice when an +output filter module calls ngx_http_filter_finalize_request() *and* +a custom error page is configured by the error_page directive. This +is because + +1. ngx_http_filter_finalize_request() triggers + calling ngx_http_terminate_request + => calling ngx_http_upstream_cleanup + => calling ngx_http_upstream_finalize_request + +2. ngx_http_internal_redirect() returns NGX_DONE + ==> ngx_http_special_response_handler() returns NGX_DONE + ==> ngx_http_filter_finalize_request() returns NGX_ERROR + ==> ngx_http_send_header() returns NGX_ERROR + ==> ngx_http_upstream_send_response() calls + ngx_http_upstream_finalize_request() again in the same + ngx_http_upstream_send_response() call as 1). + +This might result in corrupted $upstream_response_time values (close +to the absolute timestamp value) when u->state->response_sec happens +to be non-zero. + +This patch ensures that the $upstream_response_time value is only +calculated upon the first ngx_http_upstream_finalize_request() +invocation. + +diff -r f3f25ad09dee -r 8b3d7171f35e src/http/ngx_http_upstream.c +--- a/src/http/ngx_http_upstream.c Wed Feb 11 20:18:55 2015 +0300 ++++ b/src/http/ngx_http_upstream.c Thu Feb 12 16:59:43 2015 -0800 +@@ -3738,7 +3738,7 @@ static void + ngx_http_upstream_finalize_request(ngx_http_request_t *r, + ngx_http_upstream_t *u, ngx_int_t rc) + { +- ngx_uint_t flush; ++ ngx_uint_t flush, cleaned; + ngx_time_t *tp; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, +@@ -3747,6 +3747,10 @@ ngx_http_upstream_finalize_request(ngx_h + if (u->cleanup) { + *u->cleanup = NULL; + u->cleanup = NULL; ++ cleaned = 0; ++ ++ } else { ++ cleaned = 1; + } + + if (u->resolved && u->resolved->ctx) { +@@ -3754,7 +3758,7 @@ ngx_http_upstream_finalize_request(ngx_h + u->resolved->ctx = NULL; + } + +- if (u->state && u->state->response_sec) { ++ if (!cleaned && u->state && u->state->response_sec) { + tp = ngx_timeofday(); + u->state->response_sec = tp->sec - u->state->response_sec; + u->state->response_msec = tp->msec - u->state->response_msec; diff --git a/util/mirror-tarballs b/util/mirror-tarballs index b9a6f31..edbcded 100755 --- a/util/mirror-tarballs +++ b/util/mirror-tarballs @@ -251,6 +251,10 @@ echo "$info_txt applying the pcre_conf_opt patch for nginx $ver" patch -p1 < $root/patches/nginx-$ver-pcre_conf_opt.patch || exit 1 echo +echo "$info_txt applying the upstream_filter_finalize patch for nginx" +patch -p1 < $root/patches/nginx-$main_ver-upstream_filter_finalize.patch || exit 1 +echo + answer=`$root/util/ver-ge "$main_ver" 1.5.9` if [ "$answer" = "N" ]; then echo "$info_txt applying the resolve-names-with-a-trailing-dot patch for nginx $ver"