Mercurial > hg > nginx
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; |