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.
This commit is contained in:
Christopher Faulet 2026-04-03 12:20:20 +02:00
parent ed208b7e0f
commit 8056117e98
4 changed files with 115 additions and 98 deletions

View File

@ -5,6 +5,11 @@
#include <haproxy/http-t.h>
#include <haproxy/obj_type-t.h>
/* 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;

View File

@ -5,7 +5,6 @@
#include <haproxy/hstream-t.h>
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 */

View File

@ -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);

View File

@ -1,8 +1,14 @@
#define _GNU_SOURCE
#include <fcntl.h>
#include <haproxy/api.h>
#include <haproxy/buf.h>
#include <haproxy/chunk.h>
#include <haproxy/errors.h>
#include <haproxy/global.h>
#include <haproxy/hstream.h>
#include <haproxy/pipe.h>
#include <haproxy/tools.h>
#include <haproxy/version.h>
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