comparison src/http/ngx_http_upstream.c @ 6961:903fb1ddc07f

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.
author Maxim Dounin <mdounin@mdounin.ru>
date Sun, 02 Apr 2017 14:32:29 +0300
parents 4cb4ffe06785
children fa56ab75cffc
comparison
equal deleted inserted replaced
6960:1c5e5e5b008d 6961:903fb1ddc07f
1230 ngx_http_set_log_request(c->log, r); 1230 ngx_http_set_log_request(c->log, r);
1231 1231
1232 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, 1232 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
1233 "http upstream request: \"%V?%V\"", &r->uri, &r->args); 1233 "http upstream request: \"%V?%V\"", &r->uri, &r->args);
1234 1234
1235 if (ev->delayed && ev->timedout) {
1236 ev->delayed = 0;
1237 ev->timedout = 0;
1238 }
1239
1235 if (ev->write) { 1240 if (ev->write) {
1236 u->write_event_handler(r, u); 1241 u->write_event_handler(r, u);
1237 1242
1238 } else { 1243 } else {
1239 u->read_event_handler(r, u); 1244 u->read_event_handler(r, u);
3794 p->aio = r->aio; 3799 p->aio = r->aio;
3795 #endif 3800 #endif
3796 3801
3797 if (wev->timedout) { 3802 if (wev->timedout) {
3798 3803
3799 if (wev->delayed) { 3804 p->downstream_error = 1;
3800 3805 c->timedout = 1;
3801 wev->timedout = 0; 3806 ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
3802 wev->delayed = 0;
3803
3804 if (!wev->ready) {
3805 ngx_add_timer(wev, p->send_timeout);
3806
3807 if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) {
3808 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
3809 }
3810
3811 return;
3812 }
3813
3814 if (ngx_event_pipe(p, wev->write) == NGX_ABORT) {
3815 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
3816 return;
3817 }
3818
3819 } else {
3820 p->downstream_error = 1;
3821 c->timedout = 1;
3822 ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
3823 }
3824 3807
3825 } else { 3808 } else {
3826 3809
3827 if (wev->delayed) { 3810 if (wev->delayed) {
3828 3811
3863 3846
3864 c->log->action = "reading upstream"; 3847 c->log->action = "reading upstream";
3865 3848
3866 if (rev->timedout) { 3849 if (rev->timedout) {
3867 3850
3868 if (rev->delayed) { 3851 p->upstream_error = 1;
3869 3852 ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
3870 rev->timedout = 0;
3871 rev->delayed = 0;
3872
3873 if (!rev->ready) {
3874 ngx_add_timer(rev, p->read_timeout);
3875
3876 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3877 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
3878 }
3879
3880 return;
3881 }
3882
3883 if (ngx_event_pipe(p, 0) == NGX_ABORT) {
3884 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
3885 return;
3886 }
3887
3888 } else {
3889 p->upstream_error = 1;
3890 ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
3891 }
3892 3853
3893 } else { 3854 } else {
3894 3855
3895 if (rev->delayed) { 3856 if (rev->delayed) {
3896 3857