]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: httpclient: stop_and_destroy() ask the applet to autokill
authorWilliam Lallemand <wlallemand@haproxy.org>
Tue, 28 Sep 2021 09:00:43 +0000 (11:00 +0200)
committerWilliam Lallemand <wlallemand@haproxy.org>
Wed, 6 Oct 2021 13:15:03 +0000 (15:15 +0200)
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
include/haproxy/http_client.h
src/http_client.c

index 611d56829d0c0f35cf87150e8c029caec6073ed1..df25de397eedf016e650fa045688c417460a7086 100644 (file)
@@ -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 {
index e4f6fb04c440f0e2c1e94439c28a555661c191fe..c0d5447815258a03637eec0c40a72819d05c55d0 100644 (file)
@@ -4,6 +4,7 @@
 #include <haproxy/http_client-t.h>
 
 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 */
index 3ea86c21e5cdd25be30b8b8da0fc722f577b8597..6055a01cc38fbdd901b8915c9e2a6d4f74b465e1 100644 (file)
@@ -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;
 }