MEDIUM: threads/http: Make http_capture_bad_message thread-safe

This is done by passing the right stream's proxy (the frontend or the backend,
depending on the context) to lock the error snapshot used to store the error
info.
This commit is contained in:
Emeric Brun 2017-06-15 11:30:06 +02:00 committed by Willy Tarreau
parent e5c918bcef
commit 8c1aaa201a
2 changed files with 21 additions and 19 deletions

View File

@ -97,7 +97,7 @@ int http_transform_header_str(struct stream* s, struct http_msg *msg, const char
void inet_set_tos(int fd, const struct sockaddr_storage *from, int tos);
void http_perform_server_redirect(struct stream *s, struct stream_interface *si);
void http_return_srv_error(struct stream *s, struct stream_interface *si);
void http_capture_bad_message(struct error_snapshot *es, struct stream *s,
void http_capture_bad_message(struct proxy *proxy, struct error_snapshot *es, struct stream *s,
struct http_msg *msg,
enum h1_state state, struct proxy *other_end);
unsigned int http_get_hdr(const struct http_msg *msg, const char *hname, int hlen,

View File

@ -1731,7 +1731,7 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
/* we cannot return any message on error */
if (msg->err_pos >= 0) {
http_capture_bad_message(&sess->fe->invalid_req, s, msg, msg->err_state, sess->fe);
http_capture_bad_message(sess->fe, &sess->fe->invalid_req, s, msg, msg->err_state, sess->fe);
stream_inc_http_err_ctr(s);
}
@ -1764,7 +1764,7 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
/* read timeout : give up with an error message. */
if (msg->err_pos >= 0) {
http_capture_bad_message(&sess->fe->invalid_req, s, msg, msg->err_state, sess->fe);
http_capture_bad_message(sess->fe, &sess->fe->invalid_req, s, msg, msg->err_state, sess->fe);
stream_inc_http_err_ctr(s);
}
txn->status = 408;
@ -1796,7 +1796,7 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
goto failed_keep_alive;
if (msg->err_pos >= 0)
http_capture_bad_message(&sess->fe->invalid_req, s, msg, msg->err_state, sess->fe);
http_capture_bad_message(sess->fe, &sess->fe->invalid_req, s, msg, msg->err_state, sess->fe);
txn->status = 400;
msg->err_state = msg->msg_state;
msg->msg_state = HTTP_MSG_ERROR;
@ -1889,7 +1889,7 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
* to block on that, so we have to capture it now.
*/
if (unlikely(msg->err_pos >= 0))
http_capture_bad_message(&sess->fe->invalid_req, s, msg, msg->err_state, sess->fe);
http_capture_bad_message(sess->fe, &sess->fe->invalid_req, s, msg, msg->err_state, sess->fe);
/*
* 1: identify the method
@ -2167,7 +2167,7 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
/* we detected a parsing error. We want to archive this request
* in the dedicated proxy area for later troubleshooting.
*/
http_capture_bad_message(&sess->fe->invalid_req, s, msg, msg->err_state, sess->fe);
http_capture_bad_message(sess->fe, &sess->fe->invalid_req, s, msg, msg->err_state, sess->fe);
}
txn->req.err_state = txn->req.msg_state;
@ -3584,7 +3584,7 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s
/* we detected a parsing error. We want to archive this request
* in the dedicated proxy area for later troubleshooting.
*/
http_capture_bad_message(&sess->fe->invalid_req, s, msg, msg->err_state, sess->fe);
http_capture_bad_message(sess->fe, &sess->fe->invalid_req, s, msg, msg->err_state, sess->fe);
}
txn->req.err_state = txn->req.msg_state;
@ -3921,7 +3921,7 @@ int http_process_request(struct stream *s, struct channel *req, int an_bit)
/* we detected a parsing error. We want to archive this request
* in the dedicated proxy area for later troubleshooting.
*/
http_capture_bad_message(&sess->fe->invalid_req, s, msg, msg->err_state, sess->fe);
http_capture_bad_message(sess->fe, &sess->fe->invalid_req, s, msg, msg->err_state, sess->fe);
}
txn->req.err_state = txn->req.msg_state;
@ -4851,7 +4851,7 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
goto aborted_xfer;
}
if (msg->err_pos >= 0)
http_capture_bad_message(&sess->fe->invalid_req, s, msg, msg->err_state, s->be);
http_capture_bad_message(sess->fe, &sess->fe->invalid_req, s, msg, msg->err_state, s->be);
goto return_bad_req;
}
return 1;
@ -5086,7 +5086,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
*/
hdr_response_bad:
if (msg->msg_state == HTTP_MSG_ERROR || msg->err_pos >= 0)
http_capture_bad_message(&s->be->invalid_rep, s, msg, msg->err_state, sess->fe);
http_capture_bad_message(s->be, &s->be->invalid_rep, s, msg, msg->err_state, sess->fe);
HA_ATOMIC_ADD(&s->be->be_counters.failed_resp, 1);
if (objt_server(s->target)) {
@ -5119,7 +5119,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
/* read error */
else if (rep->flags & CF_READ_ERROR) {
if (msg->err_pos >= 0)
http_capture_bad_message(&s->be->invalid_rep, s, msg, msg->err_state, sess->fe);
http_capture_bad_message(s->be, &s->be->invalid_rep, s, msg, msg->err_state, sess->fe);
else if (txn->flags & TX_NOT_FIRST)
goto abort_keep_alive;
@ -5146,7 +5146,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
/* read timeout : return a 504 to the client. */
else if (rep->flags & CF_READ_TIMEOUT) {
if (msg->err_pos >= 0)
http_capture_bad_message(&s->be->invalid_rep, s, msg, msg->err_state, sess->fe);
http_capture_bad_message(s->be, &s->be->invalid_rep, s, msg, msg->err_state, sess->fe);
HA_ATOMIC_ADD(&s->be->be_counters.failed_resp, 1);
if (objt_server(s->target)) {
@ -5194,7 +5194,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
/* close from server, capture the response if the server has started to respond */
else if (rep->flags & CF_SHUTR) {
if (msg->msg_state >= HTTP_MSG_RPVER || msg->err_pos >= 0)
http_capture_bad_message(&s->be->invalid_rep, s, msg, msg->err_state, sess->fe);
http_capture_bad_message(s->be, &s->be->invalid_rep, s, msg, msg->err_state, sess->fe);
else if (txn->flags & TX_NOT_FIRST)
goto abort_keep_alive;
@ -5221,7 +5221,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
/* write error to client (we don't send any message then) */
else if (rep->flags & CF_WRITE_ERROR) {
if (msg->err_pos >= 0)
http_capture_bad_message(&s->be->invalid_rep, s, msg, msg->err_state, sess->fe);
http_capture_bad_message(s->be, &s->be->invalid_rep, s, msg, msg->err_state, sess->fe);
else if (txn->flags & TX_NOT_FIRST)
goto abort_keep_alive;
@ -5249,7 +5249,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
*/
if (unlikely(msg->err_pos >= 0))
http_capture_bad_message(&s->be->invalid_rep, s, msg, msg->err_state, sess->fe);
http_capture_bad_message(s->be, &s->be->invalid_rep, s, msg, msg->err_state, sess->fe);
/*
* 1: get the status code
@ -6024,7 +6024,7 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit
goto aborted_xfer;
}
if (msg->err_pos >= 0)
http_capture_bad_message(&s->be->invalid_rep, s, msg, msg->err_state, strm_fe(s));
http_capture_bad_message(s->be, &s->be->invalid_rep, s, msg, msg->err_state, strm_fe(s));
goto return_bad_res;
}
return 1;
@ -6334,10 +6334,10 @@ http_msg_forward_chunked_body(struct stream *s, struct http_msg *msg)
chunk_parsing_error:
if (msg->err_pos >= 0) {
if (chn->flags & CF_ISRESP)
http_capture_bad_message(&s->be->invalid_rep, s, msg,
http_capture_bad_message(s->be, &s->be->invalid_rep, s, msg,
msg->msg_state, strm_fe(s));
else
http_capture_bad_message(&strm_fe(s)->invalid_req, s,
http_capture_bad_message(strm_fe(s), &strm_fe(s)->invalid_req, s,
msg, msg->msg_state, s->be);
}
error:
@ -7732,7 +7732,7 @@ int stats_check_uri(struct stream_interface *si, struct http_txn *txn, struct pr
* parsing point. The function is able to deal with wrapping buffers. It always
* displays buffers as a contiguous area starting at buf->p.
*/
void http_capture_bad_message(struct error_snapshot *es, struct stream *s,
void http_capture_bad_message(struct proxy *proxy, struct error_snapshot *es, struct stream *s,
struct http_msg *msg,
enum h1_state state, struct proxy *other_end)
{
@ -7740,6 +7740,7 @@ void http_capture_bad_message(struct error_snapshot *es, struct stream *s,
struct channel *chn = msg->chn;
int len1, len2;
SPIN_LOCK(PROXY_LOCK, &proxy->lock);
es->len = MIN(chn->buf->i, global.tune.bufsize);
len1 = chn->buf->data + chn->buf->size - chn->buf->p;
len1 = MIN(len1, es->len);
@ -7779,6 +7780,7 @@ void http_capture_bad_message(struct error_snapshot *es, struct stream *s,
es->b_tot = chn->total;
es->m_clen = msg->chunk_len;
es->m_blen = msg->body_len;
SPIN_UNLOCK(PROXY_LOCK, &proxy->lock);
}
/* Return in <vptr> and <vlen> the pointer and length of occurrence <occ> of