]> git.kaiwu.me - haproxy.git/commitdiff
MINOR: ssl: Factorize ckch instance rebuild process
authorRemi Tricot-Le Breton <rlebreton@haproxy.com>
Thu, 23 Apr 2026 14:23:50 +0000 (16:23 +0200)
committerWilliam Lallemand <wlallemand@haproxy.com>
Tue, 5 May 2026 15:08:14 +0000 (17:08 +0200)
The ckch instances for a given ckch_store have to be rebuilt when a
certificate is updated during runtime (via cli or lua). The code was
duplicated in lua so factorizing the actual loop avoids future errors
if the code changes. The new 'ckch_store_rebuild_instances' will have a
dedicated 0 return code if it needs to be called again (because of the
yielding logic since ckch instance rebuild might take some time).

src/hlua.c
src/ssl_ckch.c

index 97c290ec5c54e6b8eaa890707745c3493a2f89f7..cde144ab21bfc86f9197da10aa82bd3cb94cc607 100644 (file)
@@ -13686,40 +13686,25 @@ __LJMP static int hlua_ckch_commit_yield(lua_State *L, int status, lua_KContext
 {
        struct ckch_inst **lua_ckchi = lua_touserdata(L, -1);
        struct ckch_store **lua_ckchs = lua_touserdata(L, -2);
-       struct ckch_inst *ckchi = *lua_ckchi;
        struct ckch_store *old_ckchs = lua_ckchs[0];
        struct ckch_store *new_ckchs = lua_ckchs[1];
        struct hlua *hlua;
        char *err = NULL;
        int y = 1;
+       int retval = 0;
 
        hlua = hlua_gethlua(L);
 
-       /* get the first ckchi to copy */
-       if (ckchi == NULL)
-               ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
-
        /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
-       list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
-               struct ckch_inst *new_inst;
-
-               /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances
-                * during runtime
-                */
-               if (hlua && (y % 10) == 0) {
-
-                       *lua_ckchi = ckchi;
-
-                       task_wakeup(hlua->task, TASK_WOKEN_MSG);
-                       MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_ckch_commit_yield, TICK_ETERNITY, 0));
-               }
+       retval = ckch_store_rebuild_instances(old_ckchs, new_ckchs, lua_ckchi,
+                                             hlua ? 10 : -1, &y, &err);
 
-               if (ckch_inst_rebuild(new_ckchs, ckchi, &new_inst, &err))
-                       goto error;
-
-               /* link the new ckch_inst to the duplicate */
-               LIST_APPEND(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
-               y++;
+       if (retval < 0)
+               goto error;
+       else if (retval == 0) {
+               /* yield */
+               task_wakeup(hlua->task, TASK_WOKEN_MSG);
+               MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_ckch_commit_yield, TICK_ETERNITY, 0));
        }
 
        /* The generation is finished, we can insert everything */
index 23fd62785be0b25488156a523964f6d179724170..d499d1b1e677b8867a43ba97443161e2c487a60b 100644 (file)
@@ -2900,6 +2900,51 @@ void ckch_store_replace(struct ckch_store *old_ckchs, struct ckch_store *new_ckc
 }
 
 
+/*
+ * Rebuild all the ckch instances from <old_ckchs> into <new_ckchs>, using
+ * <ckchi> as the first instance to manage (in case of reentry), and process at
+ * most <max> instances at a time. <count> will be the actual amount of
+ * instances rebuilt.
+ * Return -1 in case of error, 1 if all the instances were rebuilt, 0 if <max>
+ * instances were built and the function should be called again.
+ */
+int ckch_store_rebuild_instances(struct ckch_store *old_ckchs, struct ckch_store *new_ckchs,
+                                 struct ckch_inst **ckchi, int max, int *count, char **err)
+{
+
+       if (!count)
+               return -1;
+
+       *count = 0;
+
+       /* we didn't start yet, set it to the first elem */
+       if (*ckchi == NULL)
+               *ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, struct ckch_inst*, by_ckchs);
+
+       /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
+       list_for_each_entry_from((*ckchi), &old_ckchs->ckch_inst, by_ckchs) {
+               struct ckch_inst *new_inst;
+
+               /* it takes a lot of CPU to creates SSL_CTXs, so we yield every <max> CKCH instances */
+               if (max > 0 && *count >= max) {
+                       /* yield */
+                       return 0;
+               }
+
+               if (ckch_inst_rebuild(new_ckchs, *ckchi, &new_inst, err)) {
+                       /* error */
+                       return -1;
+               }
+
+               /* link the new ckch_inst to the duplicate */
+               LIST_APPEND(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
+               (*count)++;
+       }
+
+       return 1;
+}
+
+
 /*
  * This function tries to create the new ckch_inst and their SNIs
  *
@@ -2910,7 +2955,7 @@ static int cli_io_handler_commit_cert(struct appctx *appctx)
        struct commit_cert_ctx *ctx = appctx->svcctx;
        int y = 0;
        struct ckch_store *old_ckchs, *new_ckchs = NULL;
-       struct ckch_inst *ckchi;
+       int retval = 0;
 
        usermsgs_clr("CLI");
        while (1) {
@@ -2935,39 +2980,30 @@ static int cli_io_handler_commit_cert(struct appctx *appctx)
                                old_ckchs = ctx->old_ckchs;
                                new_ckchs = ctx->new_ckchs;
 
-                               /* get the next ckchi to regenerate */
-                               ckchi = ctx->next_ckchi;
-                               /* we didn't start yet, set it to the first elem */
-                               if (ckchi == NULL)
-                                       ckchi = LIST_ELEM(old_ckchs->ckch_inst.n, typeof(ckchi), by_ckchs);
-
-                               /* walk through the old ckch_inst and creates new ckch_inst using the updated ckchs */
-                               list_for_each_entry_from(ckchi, &old_ckchs->ckch_inst, by_ckchs) {
-                                       struct ckch_inst *new_inst;
-
-                                       /* save the next ckchi to compute in case of yield */
-                                       ctx->next_ckchi = ckchi;
+                               /* Rebuild at most 10 ckch instances before yielding */
+                               retval = ckch_store_rebuild_instances(old_ckchs, new_ckchs, &ctx->next_ckchi,
+                                                                     10, &y, &ctx->err);
 
-                                       /* it takes a lot of CPU to creates SSL_CTXs, so we yield every 10 CKCH instances */
-                                       if (y >= 10) {
-                                               applet_have_more_data(appctx); /* let's come back later */
-                                               goto yield;
+                               if (retval < 0) {
+                                       ctx->state = CERT_ST_ERROR;
+                                       goto error;
+                               } else {
+                                       while (y != 0) {
+                                               /* display one dot per new instance */
+                                               if (applet_putstr(appctx, ".") == -1)
+                                                       /* We might not display the proper number of
+                                                        * dots but the instances were actually rebuilt. */
+                                                       goto yield;
+                                               --y;
                                        }
 
-                                       /* display one dot per new instance */
-                                       if (applet_putstr(appctx, ".") == -1)
+                                       if (retval == 0) {
+                                               /* yield */
+                                               applet_have_more_data(appctx); /* let's come back later */
                                                goto yield;
-
-                                       ctx->err = NULL;
-                                       if (ckch_inst_rebuild(new_ckchs, ckchi, &new_inst, &ctx->err)) {
-                                               ctx->state = CERT_ST_ERROR;
-                                               goto error;
                                        }
-
-                                       /* link the new ckch_inst to the duplicate */
-                                       LIST_APPEND(&new_ckchs->ckch_inst, &new_inst->by_ckchs);
-                                       y++;
                                }
+
                                ctx->state = CERT_ST_INSERT;
                                __fallthrough;
                        case CERT_ST_INSERT: