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