Klaus Demo nginx / 5d5f0dc
Moved handling of wev->delayed to the connection event handler. With post_action or subrequests, it is possible that the timer set for wev->delayed will expire while the active subrequest write event handler is not ready to handle this. This results in request hangs as observed with limit_rate / sendfile_max_chunk and post_action (ticket #776) or subrequests (ticket #1228). Moving the handling to the connection event handler fixes the hangs observed, and also slightly simplifies the code. Maxim Dounin 2 years ago
4 changed file(s) with 27 addition(s) and 79 deletion(s). Raw diff Collapse all Expand all
293293
294294 wev = r->connection->write;
295295
296 if (wev->delayed && !wev->timedout) {
296 if (wev->delayed) {
297297
298298 if (ngx_handle_write_event(wev, 0) != NGX_OK) {
299299 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
301301
302302 return;
303303 }
304
305 wev->delayed = 0;
306 wev->timedout = 0;
307304
308305 if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
309306 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
277277
278278 wev = r->connection->write;
279279
280 if (wev->delayed && !wev->timedout) {
280 if (wev->delayed) {
281281
282282 if (ngx_handle_write_event(wev, 0) != NGX_OK) {
283283 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
285285
286286 return;
287287 }
288
289 wev->delayed = 0;
290 wev->timedout = 0;
291288
292289 ngx_http_perl_handle_request(r);
293290 }
21972197 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
21982198 "http run request: \"%V?%V\"", &r->uri, &r->args);
21992199
2200 if (ev->delayed && ev->timedout) {
2201 ev->delayed = 0;
2202 ev->timedout = 0;
2203 }
2204
22002205 if (ev->write) {
22012206 r->write_event_handler(r);
22022207
26202625 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
26212626
26222627 if (wev->timedout) {
2623 if (!wev->delayed) {
2624 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
2625 "client timed out");
2626 c->timedout = 1;
2627
2628 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
2629 return;
2630 }
2631
2632 wev->timedout = 0;
2633 wev->delayed = 0;
2634
2635 if (!wev->ready) {
2636 ngx_add_timer(wev, clcf->send_timeout);
2637
2638 if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2639 ngx_http_close_request(r, 0);
2640 }
2641
2642 return;
2643 }
2644
2628 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
2629 "client timed out");
2630 c->timedout = 1;
2631
2632 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
2633 return;
26452634 }
26462635
26472636 if (wev->delayed || r->aio) {
26482637 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
26492638 "http writer delayed");
2639
2640 if (!wev->delayed) {
2641 ngx_add_timer(wev, clcf->send_timeout);
2642 }
26502643
26512644 if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
26522645 ngx_http_close_request(r, 0);
12311231 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
12321232 "http upstream request: \"%V?%V\"", &r->uri, &r->args);
12331233
1234 if (ev->delayed && ev->timedout) {
1235 ev->delayed = 0;
1236 ev->timedout = 0;
1237 }
1238
12341239 if (ev->write) {
12351240 u->write_event_handler(r, u);
12361241
37953800
37963801 if (wev->timedout) {
37973802
3798 if (wev->delayed) {
3799
3800 wev->timedout = 0;
3801 wev->delayed = 0;
3802
3803 if (!wev->ready) {
3804 ngx_add_timer(wev, p->send_timeout);
3805
3806 if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) {
3807 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
3808 }
3809
3810 return;
3811 }
3812
3813 if (ngx_event_pipe(p, wev->write) == NGX_ABORT) {
3814 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
3815 return;
3816 }
3817
3818 } else {
3819 p->downstream_error = 1;
3820 c->timedout = 1;
3821 ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
3822 }
3803 p->downstream_error = 1;
3804 c->timedout = 1;
3805 ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
38233806
38243807 } else {
38253808
38643847
38653848 if (rev->timedout) {
38663849
3867 if (rev->delayed) {
3868
3869 rev->timedout = 0;
3870 rev->delayed = 0;
3871
3872 if (!rev->ready) {
3873 ngx_add_timer(rev, p->read_timeout);
3874
3875 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3876 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
3877 }
3878
3879 return;
3880 }
3881
3882 if (ngx_event_pipe(p, 0) == NGX_ABORT) {
3883 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
3884 return;
3885 }
3886
3887 } else {
3888 p->upstream_error = 1;
3889 ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
3890 }
3850 p->upstream_error = 1;
3851 ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
38913852
38923853 } else {
38933854