comparison src/http/modules/ngx_http_limit_req_module.c @ 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 7a6456398fc3
children 903fb1ddc07f
comparison
equal deleted inserted replaced
6958:28dc369899ea 6959:7fcf209d40c8
274 return NGX_HTTP_INTERNAL_SERVER_ERROR; 274 return NGX_HTTP_INTERNAL_SERVER_ERROR;
275 } 275 }
276 276
277 r->read_event_handler = ngx_http_test_reading; 277 r->read_event_handler = ngx_http_test_reading;
278 r->write_event_handler = ngx_http_limit_req_delay; 278 r->write_event_handler = ngx_http_limit_req_delay;
279
280 r->connection->write->delayed = 1;
279 ngx_add_timer(r->connection->write, delay); 281 ngx_add_timer(r->connection->write, delay);
280 282
281 return NGX_AGAIN; 283 return NGX_AGAIN;
282 } 284 }
283 285
290 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 292 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
291 "limit_req delay"); 293 "limit_req delay");
292 294
293 wev = r->connection->write; 295 wev = r->connection->write;
294 296
295 if (!wev->timedout) { 297 if (wev->delayed && !wev->timedout) {
296 298
297 if (ngx_handle_write_event(wev, 0) != NGX_OK) { 299 if (ngx_handle_write_event(wev, 0) != NGX_OK) {
298 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 300 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
299 } 301 }
300 302
301 return; 303 return;
302 } 304 }
303 305
306 wev->delayed = 0;
304 wev->timedout = 0; 307 wev->timedout = 0;
305 308
306 if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { 309 if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
307 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); 310 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
308 return; 311 return;