From 8056117e988a3fde05d46ecc71b2d1a3d802977d Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Fri, 3 Apr 2026 12:20:20 +0200 Subject: [PATCH] BUG/MEDIUM: haterm: Move all init functions of haterm in haterm_init.c Functions used to initialize haterm (the splicing and the response buffers) were defined and registered in haterm.c. The problem is that this file in compiled with haproxy. So it may be an issue. And for the splicing part, warnings may be emitted when haproxy is started. To avoid any issue during haproxy startup and to avoid to initialize some part of haterm, all init functions were moved into haterm_init.c file. No backport needed. --- include/haproxy/hstream-t.h | 5 ++ include/haproxy/hstream.h | 1 - src/haterm.c | 101 ++-------------------------------- src/haterm_init.c | 106 ++++++++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 98 deletions(-) diff --git a/include/haproxy/hstream-t.h b/include/haproxy/hstream-t.h index 2eae26a60..8ac52be64 100644 --- a/include/haproxy/hstream-t.h +++ b/include/haproxy/hstream-t.h @@ -5,6 +5,11 @@ #include #include +/* Size in bytes of the prebuilts response buffers */ +#define RESPSIZE 16384 +/* Number of bytes by body response line */ +#define HS_COMMON_RESPONSE_LINE_SZ 50 + /* hastream stream */ struct hstream { enum obj_type obj_type; diff --git a/include/haproxy/hstream.h b/include/haproxy/hstream.h index 7ba0d4d14..20bffd325 100644 --- a/include/haproxy/hstream.h +++ b/include/haproxy/hstream.h @@ -5,7 +5,6 @@ #include struct task *sc_hstream_io_cb(struct task *t, void *ctx, unsigned int state); -void hstream_shutdown(struct stconn *sc); void *hstream_new(struct session *sess, struct stconn *sc, struct buffer *input); #endif /* _HAPROXY_HSTREAM_H */ diff --git a/src/haterm.c b/src/haterm.c index a3b50aec9..a8c07d41e 100644 --- a/src/haterm.c +++ b/src/haterm.c @@ -63,14 +63,10 @@ const char *HTTP_HELP = " - GET /?r=500?s=0?c=0?t=1000 HTTP/1.0\n" "\n"; -/* Size in bytes of the prebuilts response buffers */ -#define RESPSIZE 16384 -/* Number of bytes by body response line */ -#define HS_COMMON_RESPONSE_LINE_SZ 50 -static char common_response[RESPSIZE]; -static char common_chunk_resp[RESPSIZE]; -static char *random_resp; -static int random_resp_len = RESPSIZE; +char common_response[RESPSIZE]; +char common_chunk_resp[RESPSIZE]; +char *random_resp; +int random_resp_len = RESPSIZE; #if defined(USE_LINUX_SPLICE) struct pipe *master_pipe = NULL; @@ -1167,92 +1163,3 @@ void *hstream_new(struct session *sess, struct stconn *sc, struct buffer *input) TRACE_DEVEL("leaving on error", HS_EV_HSTRM_NEW); return NULL; } - -/* Build the response buffers. - * Return 1 if succeeded, -1 if failed. - */ -static int hstream_build_responses(void) -{ - int i; - - for (i = 0; i < sizeof(common_response); i++) { - if (i % HS_COMMON_RESPONSE_LINE_SZ == HS_COMMON_RESPONSE_LINE_SZ - 1) - common_response[i] = '\n'; - else if (i % 10 == 0) - common_response[i] = '.'; - else - common_response[i] = '0' + i % 10; - } - - /* original haterm chunk mode responses are made of 1-byte chunks - * but the haproxy muxes do not support this. At this time - * these responses are handled the same way as for common - * responses with a pre-built buffer. - */ - for (i = 0; i < sizeof(common_chunk_resp); i++) - common_chunk_resp[i] = '1'; - - random_resp = malloc(random_resp_len); - if (!random_resp) { - ha_alert("not enough memory...\n"); - return -1; - } - - for (i = 0; i < random_resp_len; i++) - random_resp[i] = ha_random32() >> 16; - - return 1; -} - -#if defined(USE_LINUX_SPLICE) -static void hstream_init_splicing(void) -{ - if (!(global.tune.options & GTUNE_USE_SPLICE)) - return; - - if (!global.tune.pipesize) - global.tune.pipesize = 65536 * 5 / 4; - - master_pipe = get_pipe(); - if (master_pipe) { - struct iovec v = { .iov_base = common_response, - .iov_len = sizeof(common_response) }; - int total, ret; - - total = ret = 0; - do { - ret = vmsplice(master_pipe->prod, &v, 1, SPLICE_F_NONBLOCK); - if (ret > 0) - total += ret; - } while (ret > 0 && total < global.tune.pipesize); - master_pipesize = total; - - if (master_pipesize < global.tune.pipesize) { - if (master_pipesize < 60*1024) { - /* Older kernels were limited to around 60-61 kB */ - ha_warning("Failed to vmsplice response buffer after %lu bytes, splicing disabled\n", master_pipesize); - global.tune.options &= ~GTUNE_USE_SPLICE; - put_pipe(master_pipe); - master_pipe = NULL; - } - else - ha_warning("Splicing is limited to %lu bytes (too old kernel)\n", master_pipesize); - } - } - else { - ha_warning("Unable to allocate master pipe for splicing, splicing disabled\n"); - global.tune.options &= ~GTUNE_USE_SPLICE; - } -} - -static void hstream_deinit(void) -{ - if (master_pipe) - put_pipe(master_pipe); -} - -REGISTER_POST_DEINIT(hstream_deinit); -INITCALL0(STG_INIT_2, hstream_init_splicing); -#endif - -REGISTER_POST_CHECK(hstream_build_responses); diff --git a/src/haterm_init.c b/src/haterm_init.c index 06752c4ca..962ae8474 100644 --- a/src/haterm_init.c +++ b/src/haterm_init.c @@ -1,8 +1,14 @@ +#define _GNU_SOURCE +#include + #include #include #include #include #include +#include +#include +#include #include static int haterm_debug; @@ -497,3 +503,103 @@ char **copy_argv(int argc, char **argv) return ret; } + + +#if defined(USE_LINUX_SPLICE) + +extern struct pipe *master_pipe; +extern size_t master_pipesize; + +extern char common_response[RESPSIZE]; +extern char common_chunk_resp[RESPSIZE]; +extern char *random_resp; +extern int random_resp_len; + +static void hstream_init_splicing(void) +{ + if (!(global.tune.options & GTUNE_USE_SPLICE)) + return; + + if (!global.tune.pipesize) + global.tune.pipesize = 65536 * 5 / 4; + + master_pipe = get_pipe(); + if (master_pipe) { + struct iovec v = { .iov_base = common_response, + .iov_len = sizeof(common_response) }; + int total, ret; + + total = ret = 0; + do { + ret = vmsplice(master_pipe->prod, &v, 1, SPLICE_F_NONBLOCK); + if (ret > 0) + total += ret; + } while (ret > 0 && total < global.tune.pipesize); + master_pipesize = total; + + if (master_pipesize < global.tune.pipesize) { + if (master_pipesize < 60*1024) { + /* Older kernels were limited to around 60-61 kB */ + ha_warning("Failed to vmsplice response buffer after %lu bytes, splicing disabled\n", master_pipesize); + global.tune.options &= ~GTUNE_USE_SPLICE; + put_pipe(master_pipe); + master_pipe = NULL; + } + else + ha_warning("Splicing is limited to %lu bytes (too old kernel)\n", master_pipesize); + } + } + else { + ha_warning("Unable to allocate master pipe for splicing, splicing disabled\n"); + global.tune.options &= ~GTUNE_USE_SPLICE; + } +} + +static void hstream_deinit(void) +{ + if (master_pipe) + put_pipe(master_pipe); +} + +REGISTER_POST_DEINIT(hstream_deinit); +INITCALL0(STG_INIT_2, hstream_init_splicing); + +/* Build the response buffers. + * Return 1 if succeeded, -1 if failed. + */ +static int hstream_build_responses(void) +{ + int i; + + for (i = 0; i < sizeof(common_response); i++) { + if (i % HS_COMMON_RESPONSE_LINE_SZ == HS_COMMON_RESPONSE_LINE_SZ - 1) + common_response[i] = '\n'; + else if (i % 10 == 0) + common_response[i] = '.'; + else + common_response[i] = '0' + i % 10; + } + + /* original haterm chunk mode responses are made of 1-byte chunks + * but the haproxy muxes do not support this. At this time + * these responses are handled the same way as for common + * responses with a pre-built buffer. + */ + for (i = 0; i < sizeof(common_chunk_resp); i++) + common_chunk_resp[i] = '1'; + + random_resp = malloc(random_resp_len); + if (!random_resp) { + ha_alert("not enough memory...\n"); + return -1; + } + + for (i = 0; i < random_resp_len; i++) + random_resp[i] = ha_random32() >> 16; + + return 1; +} + +REGISTER_POST_CHECK(hstream_build_responses); + +#endif