mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-21 05:41:26 +02:00
BUG/MINOR: stats: Fully consume large requests in the stats applet
In the stats applet (in HTX and legacy HTTP), after a response is fully sent to a client, the request is consumed. It is done at the end, after all the response was copied into the channel's buffer. But only outgoing data at time the applet is called are consumed. Then the applet is closed. If a request with a huge body is sent, an error is triggerred because a SHUTW is catched for an unfinisehd request. Now, we consume request data until the end. In fact, we don't try to shutdown the request's channel for write anymore. This patch must be backported to 1.9 after some observation period. It should probably be backported in prior versions too. But honnestly, with refactoring on the connection layer and the stream interface in 1.9, it is probably safer to not do so.
This commit is contained in:
parent
adb363135c
commit
3a78aa6e95
@ -38,11 +38,13 @@
|
|||||||
|
|
||||||
/* HTTP stats : applet.st0 */
|
/* HTTP stats : applet.st0 */
|
||||||
enum {
|
enum {
|
||||||
STAT_HTTP_DONE = 0, /* finished */
|
STAT_HTTP_INIT = 0, /* Initial state */
|
||||||
STAT_HTTP_HEAD, /* send headers before dump */
|
STAT_HTTP_HEAD, /* send headers before dump */
|
||||||
STAT_HTTP_DUMP, /* dumping stats */
|
STAT_HTTP_DUMP, /* dumping stats */
|
||||||
STAT_HTTP_POST, /* waiting post data */
|
STAT_HTTP_POST, /* waiting post data */
|
||||||
STAT_HTTP_LAST, /* sending last chunk of response */
|
STAT_HTTP_LAST, /* sending last chunk of response */
|
||||||
|
STAT_HTTP_DONE, /* dump is finished */
|
||||||
|
STAT_HTTP_END, /* finished */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* status codes available for the stats admin page */
|
/* status codes available for the stats admin page */
|
||||||
|
58
src/stats.c
58
src/stats.c
@ -3312,8 +3312,8 @@ static void htx_stats_io_handler(struct appctx *appctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check that the output is not closed */
|
/* check that the output is not closed */
|
||||||
if (res->flags & (CF_SHUTW|CF_SHUTW_NOW))
|
if (res->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_SHUTR))
|
||||||
appctx->st0 = STAT_HTTP_DONE;
|
appctx->st0 = STAT_HTTP_END;
|
||||||
|
|
||||||
/* all states are processed in sequence */
|
/* all states are processed in sequence */
|
||||||
if (appctx->st0 == STAT_HTTP_HEAD) {
|
if (appctx->st0 == STAT_HTTP_HEAD) {
|
||||||
@ -3333,7 +3333,7 @@ static void htx_stats_io_handler(struct appctx *appctx)
|
|||||||
if (appctx->st0 == STAT_HTTP_POST) {
|
if (appctx->st0 == STAT_HTTP_POST) {
|
||||||
if (stats_process_http_post(si))
|
if (stats_process_http_post(si))
|
||||||
appctx->st0 = STAT_HTTP_LAST;
|
appctx->st0 = STAT_HTTP_LAST;
|
||||||
else if (si_oc(si)->flags & CF_SHUTR)
|
else if (req->flags & CF_SHUTR)
|
||||||
appctx->st0 = STAT_HTTP_DONE;
|
appctx->st0 = STAT_HTTP_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3348,25 +3348,24 @@ static void htx_stats_io_handler(struct appctx *appctx)
|
|||||||
si_rx_room_blk(si);
|
si_rx_room_blk(si);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
channel_add_input(&s->res, 1);
|
||||||
|
appctx->st0 = STAT_HTTP_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appctx->st0 == STAT_HTTP_END) {
|
||||||
|
if (!(res->flags & CF_SHUTR)) {
|
||||||
|
res->flags |= CF_READ_NULL;
|
||||||
|
si_shutr(si);
|
||||||
|
}
|
||||||
|
|
||||||
/* eat the whole request */
|
/* eat the whole request */
|
||||||
req_htx = htxbuf(&req->buf);
|
if (co_data(req)) {
|
||||||
htx_reset(req_htx);
|
req_htx = htx_from_buf(&req->buf);
|
||||||
htx_to_buf(req_htx, &req->buf);
|
co_htx_skip(req, req_htx, co_data(req));
|
||||||
co_set_data(req, 0);
|
htx_to_buf(req_htx, &req->buf);
|
||||||
res->flags |= CF_READ_NULL;
|
|
||||||
si_shutr(si);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((res->flags & CF_SHUTR) && (si->state == SI_ST_EST))
|
|
||||||
si_shutw(si);
|
|
||||||
|
|
||||||
if (appctx->st0 == STAT_HTTP_DONE) {
|
|
||||||
if ((req->flags & CF_SHUTW) && (si->state == SI_ST_EST)) {
|
|
||||||
si_shutr(si);
|
|
||||||
res->flags |= CF_READ_NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
/* we have left the request in the buffer for the case where we
|
/* we have left the request in the buffer for the case where we
|
||||||
* process a POST, and this automatically re-enables activity on
|
* process a POST, and this automatically re-enables activity on
|
||||||
@ -3408,8 +3407,8 @@ static void http_stats_io_handler(struct appctx *appctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check that the output is not closed */
|
/* check that the output is not closed */
|
||||||
if (res->flags & (CF_SHUTW|CF_SHUTW_NOW))
|
if (res->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_SHUTR))
|
||||||
appctx->st0 = STAT_HTTP_DONE;
|
appctx->st0 = STAT_HTTP_END;
|
||||||
|
|
||||||
/* all states are processed in sequence */
|
/* all states are processed in sequence */
|
||||||
if (appctx->st0 == STAT_HTTP_HEAD) {
|
if (appctx->st0 == STAT_HTTP_HEAD) {
|
||||||
@ -3493,21 +3492,20 @@ static void http_stats_io_handler(struct appctx *appctx)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* eat the whole request */
|
appctx->st0 = STAT_HTTP_END;
|
||||||
co_skip(si_oc(si), co_data(si_oc(si)));
|
|
||||||
res->flags |= CF_READ_NULL;
|
|
||||||
si_shutr(si);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res->flags & CF_SHUTR) && (si->state == SI_ST_EST))
|
if (appctx->st0 == STAT_HTTP_END) {
|
||||||
si_shutw(si);
|
if (!(res->flags & CF_SHUTR)) {
|
||||||
|
|
||||||
if (appctx->st0 == STAT_HTTP_DONE) {
|
|
||||||
if ((req->flags & CF_SHUTW) && (si->state == SI_ST_EST)) {
|
|
||||||
si_shutr(si);
|
|
||||||
res->flags |= CF_READ_NULL;
|
res->flags |= CF_READ_NULL;
|
||||||
|
si_shutr(si);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* eat the whole request */
|
||||||
|
if (co_data(req))
|
||||||
|
co_skip(si_oc(si), co_data(si_oc(si)));
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
/* we have left the request in the buffer for the case where we
|
/* we have left the request in the buffer for the case where we
|
||||||
* process a POST, and this automatically re-enables activity on
|
* process a POST, and this automatically re-enables activity on
|
||||||
|
Loading…
x
Reference in New Issue
Block a user