From 5f10176e2c9eca3bbae39a7707ef226f3e2abe0d Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 11 Jul 2023 18:42:53 +0200 Subject: [PATCH] MEDIUM: init: initialize the trash earlier More and more utility functions rely on the trash while most of the init code doesn't have access to it because it's initialized very late (in PRE_CHECK for the initial one). It's a pool, and it purposely supports being reallocated, so let's initialize it in STG_POOL so that early STG_INIT code can at least use it. --- doc/internals/api/initcalls.txt | 14 ++++++++++---- src/chunk.c | 10 ++++++++++ src/haproxy.c | 12 +++++++----- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/doc/internals/api/initcalls.txt b/doc/internals/api/initcalls.txt index 30d873720..a341edc1d 100644 --- a/doc/internals/api/initcalls.txt +++ b/doc/internals/api/initcalls.txt @@ -122,10 +122,11 @@ make sure to respect this ordering when adding new ones. parsing and where the initialization should continue in the configuration check. It could be used for example to generate a proxy with multiple servers using - the configuration parser itself. At this step the trash buffers are allocated. - Threads are not yet started so no protection is required. The function is - expected to return non-zero on success, or zero on failure. A failure will make - the process emit a succinct error message and immediately exit. + the configuration parser itself. At this step the final trash buffers are + allocated. Threads are not yet started so no protection is required. The + function is expected to return non-zero on success, or zero on failure. A + failure will make the process emit a succinct error message and immediately + exit. - void hap_register_post_check(int (*fct)()) @@ -244,6 +245,11 @@ compose the executable. Keywords, protocols and various other elements that are local known to each compilation unit can will be appended into common lists at boot time. This is why this call is placed just before STG_ALLOC. +Note that trash is needed in various functions. Trash is a pool and is +allocated during STG_POOL, so it's not permitted to use it before STG_INIT, +where it will only use the default size, and may be reallocated later with a +different size. + Example: register a very early call to init_log() with no argument, and another call to cli_register_kw(&cli_kws) much later: diff --git a/src/chunk.c b/src/chunk.c index b9728e1c9..c5b74fc5e 100644 --- a/src/chunk.c +++ b/src/chunk.c @@ -98,6 +98,15 @@ int init_trash_buffers(int first) return 1; } +/* This is called during STG_POOL to allocate trash buffers early. They will + * be reallocated later once their final size is known. It returns 0 if an + * error occurred. + */ +static int alloc_early_trash(void) +{ + return init_trash_buffers(1); +} + /* * Does an snprintf() at the beginning of chunk , respecting the limit of * at most chk->size chars. If the chk->len is over, nothing is added. Returns @@ -289,6 +298,7 @@ int chunk_strcasecmp(const struct buffer *chk, const char *str) return diff; } +INITCALL0(STG_POOL, alloc_early_trash); REGISTER_PER_THREAD_ALLOC(alloc_trash_buffers_per_thread); REGISTER_PER_THREAD_FREE(free_trash_buffers_per_thread); REGISTER_POST_DEINIT(free_trash_buffers_per_thread); diff --git a/src/haproxy.c b/src/haproxy.c index 1b5be8857..18308bc59 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -1976,11 +1976,6 @@ static void init(int argc, char **argv) startup_logs_init(); - if (!init_trash_buffers(1)) { - ha_alert("failed to initialize trash buffers.\n"); - exit(1); - } - if (init_acl() != 0) exit(1); @@ -3303,6 +3298,13 @@ int main(int argc, char **argv) RUN_INITCALLS(STG_ALLOC); RUN_INITCALLS(STG_POOL); + + /* some code really needs to have the trash properly allocated */ + if (!trash.area) { + ha_alert("failed to initialize trash buffers.\n"); + exit(1); + } + RUN_INITCALLS(STG_INIT); /* this is the late init where the config is parsed */