mirror of
https://github.com/nginx/nginx.git
synced 2024-12-22 15:13:28 -06:00
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.
This commit is contained in:
parent
96e4e84ce2
commit
5d5f0dcac4
@ -294,7 +294,7 @@ ngx_http_limit_req_delay(ngx_http_request_t *r)
|
|||||||
|
|
||||||
wev = r->connection->write;
|
wev = r->connection->write;
|
||||||
|
|
||||||
if (wev->delayed && !wev->timedout) {
|
if (wev->delayed) {
|
||||||
|
|
||||||
if (ngx_handle_write_event(wev, 0) != NGX_OK) {
|
if (ngx_handle_write_event(wev, 0) != NGX_OK) {
|
||||||
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||||
@ -303,9 +303,6 @@ ngx_http_limit_req_delay(ngx_http_request_t *r)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wev->delayed = 0;
|
|
||||||
wev->timedout = 0;
|
|
||||||
|
|
||||||
if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
|
if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
|
||||||
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||||
return;
|
return;
|
||||||
|
@ -278,7 +278,7 @@ ngx_http_perl_sleep_handler(ngx_http_request_t *r)
|
|||||||
|
|
||||||
wev = r->connection->write;
|
wev = r->connection->write;
|
||||||
|
|
||||||
if (wev->delayed && !wev->timedout) {
|
if (wev->delayed) {
|
||||||
|
|
||||||
if (ngx_handle_write_event(wev, 0) != NGX_OK) {
|
if (ngx_handle_write_event(wev, 0) != NGX_OK) {
|
||||||
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
||||||
@ -287,9 +287,6 @@ ngx_http_perl_sleep_handler(ngx_http_request_t *r)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wev->delayed = 0;
|
|
||||||
wev->timedout = 0;
|
|
||||||
|
|
||||||
ngx_http_perl_handle_request(r);
|
ngx_http_perl_handle_request(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2198,6 +2198,11 @@ ngx_http_request_handler(ngx_event_t *ev)
|
|||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||||
"http run request: \"%V?%V\"", &r->uri, &r->args);
|
"http run request: \"%V?%V\"", &r->uri, &r->args);
|
||||||
|
|
||||||
|
if (ev->delayed && ev->timedout) {
|
||||||
|
ev->delayed = 0;
|
||||||
|
ev->timedout = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (ev->write) {
|
if (ev->write) {
|
||||||
r->write_event_handler(r);
|
r->write_event_handler(r);
|
||||||
|
|
||||||
@ -2621,7 +2626,6 @@ ngx_http_writer(ngx_http_request_t *r)
|
|||||||
clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
|
clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
|
||||||
|
|
||||||
if (wev->timedout) {
|
if (wev->timedout) {
|
||||||
if (!wev->delayed) {
|
|
||||||
ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
|
ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
|
||||||
"client timed out");
|
"client timed out");
|
||||||
c->timedout = 1;
|
c->timedout = 1;
|
||||||
@ -2630,25 +2634,14 @@ ngx_http_writer(ngx_http_request_t *r)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wev->timedout = 0;
|
|
||||||
wev->delayed = 0;
|
|
||||||
|
|
||||||
if (!wev->ready) {
|
|
||||||
ngx_add_timer(wev, clcf->send_timeout);
|
|
||||||
|
|
||||||
if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
|
|
||||||
ngx_http_close_request(r, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wev->delayed || r->aio) {
|
if (wev->delayed || r->aio) {
|
||||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
|
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
|
||||||
"http writer delayed");
|
"http writer delayed");
|
||||||
|
|
||||||
|
if (!wev->delayed) {
|
||||||
|
ngx_add_timer(wev, clcf->send_timeout);
|
||||||
|
}
|
||||||
|
|
||||||
if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
|
if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
|
||||||
ngx_http_close_request(r, 0);
|
ngx_http_close_request(r, 0);
|
||||||
}
|
}
|
||||||
|
@ -1232,6 +1232,11 @@ ngx_http_upstream_handler(ngx_event_t *ev)
|
|||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||||
"http upstream request: \"%V?%V\"", &r->uri, &r->args);
|
"http upstream request: \"%V?%V\"", &r->uri, &r->args);
|
||||||
|
|
||||||
|
if (ev->delayed && ev->timedout) {
|
||||||
|
ev->delayed = 0;
|
||||||
|
ev->timedout = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (ev->write) {
|
if (ev->write) {
|
||||||
u->write_event_handler(r, u);
|
u->write_event_handler(r, u);
|
||||||
|
|
||||||
@ -3796,31 +3801,9 @@ ngx_http_upstream_process_downstream(ngx_http_request_t *r)
|
|||||||
|
|
||||||
if (wev->timedout) {
|
if (wev->timedout) {
|
||||||
|
|
||||||
if (wev->delayed) {
|
|
||||||
|
|
||||||
wev->timedout = 0;
|
|
||||||
wev->delayed = 0;
|
|
||||||
|
|
||||||
if (!wev->ready) {
|
|
||||||
ngx_add_timer(wev, p->send_timeout);
|
|
||||||
|
|
||||||
if (ngx_handle_write_event(wev, p->send_lowat) != NGX_OK) {
|
|
||||||
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ngx_event_pipe(p, wev->write) == NGX_ABORT) {
|
|
||||||
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
p->downstream_error = 1;
|
p->downstream_error = 1;
|
||||||
c->timedout = 1;
|
c->timedout = 1;
|
||||||
ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
|
ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out");
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@ -3865,30 +3848,8 @@ ngx_http_upstream_process_upstream(ngx_http_request_t *r,
|
|||||||
|
|
||||||
if (rev->timedout) {
|
if (rev->timedout) {
|
||||||
|
|
||||||
if (rev->delayed) {
|
|
||||||
|
|
||||||
rev->timedout = 0;
|
|
||||||
rev->delayed = 0;
|
|
||||||
|
|
||||||
if (!rev->ready) {
|
|
||||||
ngx_add_timer(rev, p->read_timeout);
|
|
||||||
|
|
||||||
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
|
|
||||||
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ngx_event_pipe(p, 0) == NGX_ABORT) {
|
|
||||||
ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
p->upstream_error = 1;
|
p->upstream_error = 1;
|
||||||
ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
|
ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user