changeset 6959:7fcf209d40c8

Limit req: fixed delaying subrequests. Since limit_req uses connection's write event to delay request processing, it can conflict with timers in other subrequests. In particular, even if applied to an active subrequest, it can break things if wev->delayed is already set (due to limit_rate or sendfile_max_chunk), since after limit_req finishes the wev->delayed flag will be set and no timer will be active. Fix is to use the wev->delayed flag in limit_req as well. This ensures that wev->delayed won't be set after limit_req finishes, and also ensures that limit_req's timers will be properly handled by other subrequests if the one delayed by limit_req is not active.
author Maxim Dounin <mdounin@mdounin.ru>
date Sun, 02 Apr 2017 14:32:26 +0300
parents 28dc369899ea
children 1c5e5e5b008d
files src/http/modules/ngx_http_limit_req_module.c
diffstat 1 files changed, 4 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/modules/ngx_http_limit_req_module.c
+++ b/src/http/modules/ngx_http_limit_req_module.c
@@ -276,6 +276,8 @@ ngx_http_limit_req_handler(ngx_http_requ
 
     r->read_event_handler = ngx_http_test_reading;
     r->write_event_handler = ngx_http_limit_req_delay;
+
+    r->connection->write->delayed = 1;
     ngx_add_timer(r->connection->write, delay);
 
     return NGX_AGAIN;
@@ -292,7 +294,7 @@ ngx_http_limit_req_delay(ngx_http_reques
 
     wev = r->connection->write;
 
-    if (!wev->timedout) {
+    if (wev->delayed && !wev->timedout) {
 
         if (ngx_handle_write_event(wev, 0) != NGX_OK) {
             ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
@@ -301,6 +303,7 @@ ngx_http_limit_req_delay(ngx_http_reques
         return;
     }
 
+    wev->delayed = 0;
     wev->timedout = 0;
 
     if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {