From: Willy Tarreau Date: Sun, 12 Jul 2009 06:27:39 +0000 (+0200) Subject: [MINOR] prepare callers of session_set_backend to handle errors X-Git-Tag: v1.4-dev1~29 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bedb9bad6768babdbe7fea5f79c19a710321cc9b;p=thirdparty%2Fhaproxy.git [MINOR] prepare callers of session_set_backend to handle errors session_set_backend will soon have to allocate areas for HTTP headers. We must ensure that the callers can handle an allocation error. --- diff --git a/include/proto/proxy.h b/include/proto/proxy.h index 36360e5cf5..0ad1e7fe8b 100644 --- a/include/proto/proxy.h +++ b/include/proto/proxy.h @@ -35,7 +35,7 @@ void pause_proxy(struct proxy *p); void stop_proxy(struct proxy *p); void pause_proxies(void); void listen_proxies(void); -void session_set_backend(struct session *s, struct proxy *be); +int session_set_backend(struct session *s, struct proxy *be); const char *proxy_cap_str(int cap); const char *proxy_mode_str(int mode); diff --git a/src/proxy.c b/src/proxy.c index dcfb12d879..2dfc93b3b1 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -635,11 +635,12 @@ void listen_proxies(void) * session already had a backend assigned, which is indicated by * s->flags & SN_BE_ASSIGNED. * All flags, stats and counters which need be updated are updated. + * Returns 1 if done, 0 in case of internal error, eg: lack of resource. */ -void session_set_backend(struct session *s, struct proxy *be) +int session_set_backend(struct session *s, struct proxy *be) { if (s->flags & SN_BE_ASSIGNED) - return; + return 1; s->be = be; be->beconn++; if (be->beconn > be->beconn_max) @@ -653,6 +654,7 @@ void session_set_backend(struct session *s, struct proxy *be) if (be->options2 & PR_O2_RSPBUG_OK) s->txn.rsp.err_pos = -1; /* let buggy responses pass */ s->flags |= SN_BE_ASSIGNED; + return 1; } static struct cfg_kw_list cfg_kws = {{ },{ diff --git a/src/session.c b/src/session.c index d4817ac2c3..7d95669fb4 100644 --- a/src/session.c +++ b/src/session.c @@ -586,7 +586,8 @@ int process_switching_rules(struct session *s, struct buffer *req, int an_bit) ret = !ret; if (ret) { - session_set_backend(s, rule->be.backend); + if (!session_set_backend(s, rule->be.backend)) + goto sw_failed; break; } } @@ -597,7 +598,8 @@ int process_switching_rules(struct session *s, struct buffer *req, int an_bit) * backend if any. */ if (!(s->flags & SN_BE_ASSIGNED)) - session_set_backend(s, s->fe->defbe.be ? s->fe->defbe.be : s->be); + if (!session_set_backend(s, s->fe->defbe.be ? s->fe->defbe.be : s->be)) + goto sw_failed; } /* we don't want to run the HTTP filters again if the backend has not changed */ @@ -605,6 +607,21 @@ int process_switching_rules(struct session *s, struct buffer *req, int an_bit) s->req->analysers &= ~AN_REQ_HTTP_PROCESS_BE; return 1; + + sw_failed: + /* immediately abort this request in case of allocation failure */ + buffer_abort(s->req); + buffer_abort(s->rep); + + if (!(s->flags & SN_ERR_MASK)) + s->flags |= SN_ERR_RESOURCE; + if (!(s->flags & SN_FINST_MASK)) + s->flags |= SN_FINST_R; + + s->txn.status = 500; + s->req->analysers = 0; + s->req->analyse_exp = TICK_ETERNITY; + return 0; } /* Processes the client, server, request and response jobs of a session task,