[BUG] http: fix for capture memory leak was incorrect

That patch was incorrect because under some circumstances, the
capture memory could be freed by session_free() and then again
by http_end_txn(), causing a double free and an eventual segfault.
The pool use count was also reported wrong due to this bug.

The cleanup code was removed from session_free() to remain only
in http_end_txn().
This commit is contained in:
Willy Tarreau 2010-01-07 22:51:47 +01:00
parent 6fe60182aa
commit 4602363f6a
2 changed files with 21 additions and 25 deletions

View File

@ -6310,19 +6310,11 @@ void http_init_txn(struct session *s)
if (fe->options2 & PR_O2_REQBUG_OK)
txn->req.err_pos = -1; /* let buggy requests pass */
if (txn->req.cap) {
struct cap_hdr *h;
for (h = fe->req_cap; h; h = h->next)
pool_free2(h->pool, txn->req.cap[h->index]);
if (txn->req.cap)
memset(txn->req.cap, 0, fe->nb_req_cap * sizeof(void *));
}
if (txn->rsp.cap) {
struct cap_hdr *h;
for (h = fe->rsp_cap; h; h = h->next)
pool_free2(h->pool, txn->rsp.cap[h->index]);
if (txn->rsp.cap)
memset(txn->rsp.cap, 0, fe->nb_rsp_cap * sizeof(void *));
}
if (txn->hdr_idx.v)
hdr_idx_init(&txn->hdr_idx);
@ -6340,6 +6332,21 @@ void http_end_txn(struct session *s)
txn->uri = NULL;
txn->srv_cookie = NULL;
txn->cli_cookie = NULL;
if (txn->req.cap) {
struct cap_hdr *h;
for (h = s->fe->req_cap; h; h = h->next)
pool_free2(h->pool, txn->req.cap[h->index]);
memset(txn->req.cap, 0, s->fe->nb_req_cap * sizeof(void *));
}
if (txn->rsp.cap) {
struct cap_hdr *h;
for (h = s->fe->rsp_cap; h; h = h->next)
pool_free2(h->pool, txn->rsp.cap[h->index]);
memset(txn->rsp.cap, 0, s->fe->nb_rsp_cap * sizeof(void *));
}
}
/* to be used at the end of a transaction to prepare a new one */

View File

@ -81,25 +81,14 @@ void session_free(struct session *s)
if (s->sessid)
pool_free2(apools.sessid, s->sessid);
http_end_txn(s);
if (fe) {
pool_free2(fe->hdr_idx_pool, txn->hdr_idx.v);
if (txn->rsp.cap != NULL) {
struct cap_hdr *h;
for (h = fe->rsp_cap; h; h = h->next)
pool_free2(h->pool, txn->rsp.cap[h->index]);
pool_free2(fe->rsp_cap_pool, txn->rsp.cap);
}
if (txn->req.cap != NULL) {
struct cap_hdr *h;
for (h = fe->req_cap; h; h = h->next)
pool_free2(h->pool, txn->req.cap[h->index]);
pool_free2(fe->req_cap_pool, txn->req.cap);
}
pool_free2(fe->rsp_cap_pool, txn->rsp.cap);
pool_free2(fe->req_cap_pool, txn->req.cap);
}
http_end_txn(s);
list_for_each_entry_safe(bref, back, &s->back_refs, users) {
/* we have to unlink all watchers. We must not relink them if
* this session was the last one in the list.