From ac776e3819f9fa54e2a005469e5a423a3d179543 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 7 Jun 2026 07:03:06 +0200 Subject: [PATCH] BUG/MEDIUM: regex: initialize the match array earlier during boot As reported by @zhanhb in github issue #3410, since 3.3 with commit fda6dc959 ("MINOR: regex: use a thread-local match pointer for pcre2"), the local_pcre2_match array is initialized too late for use by Lua. If a lua-load makes use of regex, it may segfault (actually using PCRE2 is fine but PCRE2_JIT will crash): Let's change the init sequence so that the first thread's context is initialized early at boot and other threads are initialized when they are created. For lua-load-per-thread, all extra threads will run on the first thread's temporary storage during init but that's not a problem since the sole purpose is to avoid concurrent accesses. Thanks to @zhanbb for the detailed report and quick tests. This needs to be backported to 3.3. --- src/regex.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/regex.c b/src/regex.c index 0f192f725..3e1348e2e 100644 --- a/src/regex.c +++ b/src/regex.c @@ -442,7 +442,7 @@ static void regex_register_build_options(void) INITCALL0(STG_REGISTER, regex_register_build_options); #ifdef USE_PCRE2 -static int init_pcre2_per_thread(void) +static int init_pcre2_one_thread(void) { local_pcre2_match = pcre2_match_data_create(MAX_MATCH, NULL); if (!local_pcre2_match) { @@ -452,13 +452,32 @@ static int init_pcre2_per_thread(void) return 1; } +/* per-thread init for the next threads (first one already done) */ +static int init_pcre2_per_thread(void) +{ + if (!tid) + return 1; + return init_pcre2_one_thread(); +} + +/* per-thread deinit for the next threads */ static void deinit_pcre2_per_thread(void) +{ + if (tid) + pcre2_match_data_free(local_pcre2_match); +} + +/* late deinit for the first thread */ +static void deinit_pcre2_first_thread(void) { pcre2_match_data_free(local_pcre2_match); } +/* early init for the first thread */ +INITCALL0(STG_INIT, init_pcre2_one_thread); REGISTER_PER_THREAD_INIT(init_pcre2_per_thread); REGISTER_PER_THREAD_DEINIT(deinit_pcre2_per_thread); +REGISTER_POST_DEINIT(deinit_pcre2_first_thread); #endif /* -- 2.47.3