From ecb83e13eb31cbcf76c6f8aa46eccf8aca4e7b71 Mon Sep 17 00:00:00 2001 From: William Lallemand Date: Tue, 28 Sep 2021 11:00:43 +0200 Subject: [PATCH] MINOR: httpclient: stop_and_destroy() ask the applet to autokill httpclient_stop_and_destroy() tries to destroy the httpclient structure if the client was stopped. In the case the client wasn't stopped, it ask the client to stop itself and to destroy the httpclient structure itself during the release of the applet. --- include/haproxy/http_client-t.h | 7 +++++- include/haproxy/http_client.h | 3 ++- src/http_client.c | 40 +++++++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/include/haproxy/http_client-t.h b/include/haproxy/http_client-t.h index 611d56829..df25de397 100644 --- a/include/haproxy/http_client-t.h +++ b/include/haproxy/http_client-t.h @@ -30,7 +30,12 @@ struct httpclient { unsigned int flags; /* other flags */ }; -#define HTTPCLIENT_F_ENDED 0x00000001 +/* Action (FA) to do */ +#define HTTPCLIENT_FA_STOP 0x00000001 /* stops the httpclient at the next IO handler call */ +#define HTTPCLIENT_FA_AUTOKILL 0x00000002 /* sets the applet to destroy the httpclient struct itself */ + +/* status (FS) */ +#define HTTPCLIENT_FS_ENDED 0x00010000 /* the httpclient is stopped */ /* States of the HTTP Client Appctx */ enum { diff --git a/include/haproxy/http_client.h b/include/haproxy/http_client.h index e4f6fb04c..c0d544781 100644 --- a/include/haproxy/http_client.h +++ b/include/haproxy/http_client.h @@ -4,6 +4,7 @@ #include void httpclient_destroy(struct httpclient *hc); +void httpclient_stop_and_destroy(struct httpclient *hc); struct httpclient *httpclient_new(void *caller, enum http_meth_t meth, struct ist url); struct appctx *httpclient_start(struct httpclient *hc); @@ -20,7 +21,7 @@ static inline int httpclient_data(struct httpclient *hc) /* Return 1 if the httpclient ended and won't receive any new data */ static inline int httpclient_ended(struct httpclient *hc) { - return !!(hc->flags & HTTPCLIENT_F_ENDED); + return !!(hc->flags & HTTPCLIENT_FS_ENDED); } #endif /* ! _HAPROXY_HTTCLIENT_H */ diff --git a/src/http_client.c b/src/http_client.c index 3ea86c21e..6055a01cc 100644 --- a/src/http_client.c +++ b/src/http_client.c @@ -228,7 +228,7 @@ static void hc_cli_release(struct appctx *appctx) struct httpclient *hc = appctx->ctx.cli.p0; /* Everything possible was printed on the CLI, we can destroy the client */ - httpclient_destroy(hc); + httpclient_stop_and_destroy(hc); return; } @@ -407,6 +407,27 @@ out: return NULL; } +/* + * This function tries to destroy the httpclient if it wasn't running. + * If it was running, stop the client and ask it to autodestroy itself. + * + * Once this fonction is used, all pointer sto the client must be removed + * + */ +void httpclient_stop_and_destroy(struct httpclient *hc) +{ + + /* The httpclient was already stopped, we can safely destroy it */ + if (hc->flags & HTTPCLIENT_FS_ENDED) { + httpclient_destroy(hc); + } else { + /* if the client wasn't stopped, ask for a stop and destroy */ + hc->flags |= (HTTPCLIENT_FA_AUTOKILL | HTTPCLIENT_FA_STOP); + if (hc->appctx) + appctx_wakeup(hc->appctx); + } +} + /* Free the httpclient */ void httpclient_destroy(struct httpclient *hc) { @@ -415,6 +436,10 @@ void httpclient_destroy(struct httpclient *hc) if (!hc) return; + + /* we should never destroy a client which was not stopped */ + BUG_ON(!httpclient_ended(hc)); + /* request */ istfree(&hc->req.url); b_free(&hc->req.buf); @@ -480,6 +505,11 @@ static void httpclient_applet_io_handler(struct appctx *appctx) while (1) { + + /* required to stop */ + if (hc->flags & HTTPCLIENT_FA_STOP) + goto end; + switch(appctx->st0) { case HTTPCLIENT_S_REQ: @@ -667,11 +697,17 @@ static void httpclient_applet_release(struct appctx *appctx) struct httpclient *hc = appctx->ctx.httpclient.ptr; /* mark the httpclient as ended */ - hc->flags |= HTTPCLIENT_F_ENDED; + hc->flags |= HTTPCLIENT_FS_ENDED; /* the applet is leaving, remove the ptr so we don't try to call it * again from the caller */ hc->appctx = NULL; + + /* destroy the httpclient when set to autotokill */ + if (hc->flags & HTTPCLIENT_FA_AUTOKILL) { + httpclient_destroy(hc); + } + return; }