mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-01 19:13:36 +00:00
OPTIM/MINOR: session: abort if possible before connecting to the backend
Depending on the path that led to sess_update_stream_int(), it's possible that we had a read error on the frontend, but that we haven't checked if we may abort the connection. This was seen in particular the following setup: tcp mode, with abortonclose set, frontend using ssl. If the ssl connection had a first successful read, but the second read failed, we would stil try to open a connection to the backend, although we had enough information to close the connection early. sess_update_stream_int() had some logic to handle that case in the SI_ST_QUE and SI_ST_TAR, but that was missing in the SI_ST_ASS case. This patches addresses the issue by verifying the state of the req channel (and the abortonclose option) right before opening the connection to the backend, so we have the opportunity to close the connection there, and factorizes the shared SI_ST_{QUE,TAR,ASS} code.
This commit is contained in:
parent
bb137a8af7
commit
6cd8d13c05
53
src/stream.c
53
src/stream.c
@ -774,6 +774,14 @@ static void sess_establish(struct stream *s)
|
||||
req->wex = TICK_ETERNITY;
|
||||
}
|
||||
|
||||
/* Check if the connection request is in such a state that it can be aborted. */
|
||||
static int check_req_may_abort(struct channel *req, struct stream *s)
|
||||
{
|
||||
return ((req->flags & (CF_READ_ERROR)) ||
|
||||
((req->flags & CF_SHUTW_NOW) && /* empty and client aborted */
|
||||
(channel_is_empty(req) || s->be->options & PR_O_ABRT_CLOSE)));
|
||||
}
|
||||
|
||||
/* Update back stream interface status for input states SI_ST_ASS, SI_ST_QUE,
|
||||
* SI_ST_TAR. Other input states are simply ignored.
|
||||
* Possible output states are SI_ST_CLO, SI_ST_TAR, SI_ST_ASS, SI_ST_REQ, SI_ST_CON
|
||||
@ -798,6 +806,14 @@ static void sess_update_stream_int(struct stream *s)
|
||||
/* Server assigned to connection request, we have to try to connect now */
|
||||
int conn_err;
|
||||
|
||||
/* Before we try to initiate the connection, see if the
|
||||
* request may be aborted instead.
|
||||
*/
|
||||
if (check_req_may_abort(req, s)) {
|
||||
si->err_type |= SI_ET_CONN_ABRT;
|
||||
goto abort_connection;
|
||||
}
|
||||
|
||||
conn_err = connect_server(s);
|
||||
srv = objt_server(s->target);
|
||||
|
||||
@ -893,19 +909,10 @@ static void sess_update_stream_int(struct stream *s)
|
||||
}
|
||||
|
||||
/* Connection remains in queue, check if we have to abort it */
|
||||
if ((req->flags & (CF_READ_ERROR)) ||
|
||||
((req->flags & CF_SHUTW_NOW) && /* empty and client aborted */
|
||||
(channel_is_empty(req) || s->be->options & PR_O_ABRT_CLOSE))) {
|
||||
/* give up */
|
||||
si->exp = TICK_ETERNITY;
|
||||
if (check_req_may_abort(req, s)) {
|
||||
s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
|
||||
si_shutr(si);
|
||||
si_shutw(si);
|
||||
si->err_type |= SI_ET_QUEUE_ABRT;
|
||||
si->state = SI_ST_CLO;
|
||||
if (s->srv_error)
|
||||
s->srv_error(s, si);
|
||||
return;
|
||||
goto abort_connection;
|
||||
}
|
||||
|
||||
/* Nothing changed */
|
||||
@ -913,18 +920,9 @@ static void sess_update_stream_int(struct stream *s)
|
||||
}
|
||||
else if (si->state == SI_ST_TAR) {
|
||||
/* Connection request might be aborted */
|
||||
if ((req->flags & (CF_READ_ERROR)) ||
|
||||
((req->flags & CF_SHUTW_NOW) && /* empty and client aborted */
|
||||
(channel_is_empty(req) || s->be->options & PR_O_ABRT_CLOSE))) {
|
||||
/* give up */
|
||||
si->exp = TICK_ETERNITY;
|
||||
si_shutr(si);
|
||||
si_shutw(si);
|
||||
if (check_req_may_abort(req, s)) {
|
||||
si->err_type |= SI_ET_CONN_ABRT;
|
||||
si->state = SI_ST_CLO;
|
||||
if (s->srv_error)
|
||||
s->srv_error(s, si);
|
||||
return;
|
||||
goto abort_connection;
|
||||
}
|
||||
|
||||
if (!(si->flags & SI_FL_EXP))
|
||||
@ -942,6 +940,17 @@ static void sess_update_stream_int(struct stream *s)
|
||||
si->state = SI_ST_REQ;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
abort_connection:
|
||||
/* give up */
|
||||
si->exp = TICK_ETERNITY;
|
||||
si_shutr(si);
|
||||
si_shutw(si);
|
||||
si->state = SI_ST_CLO;
|
||||
if (s->srv_error)
|
||||
s->srv_error(s, si);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set correct stream termination flags in case no analyser has done it. It
|
||||
|
Loading…
Reference in New Issue
Block a user