MEDIUM: init: set default for fd_hard_limit via DEFAULT_MAXFD

Let's provide a default value for fd_hard_limit, if it's not set in the
configuration. With this patch we could set some specific default via
compile-time variable DEFAULT_MAXFD as well. Hope, this will be helpfull for
haproxy package maintainers.

    make -j 8 TARGET=linux-glibc DEBUG=-DDEFAULT_MAXFD=50000

If haproxy is comipled without DEFAULT_MAXFD defined, the default will be set
to 1048576.

This is done to avoid killing the process by its watchdog, while it started
without any limitations in its configuration or in the command line and the
hard RLIMIT_NOFILE is extremely huge (~1000000000). We use in this case
compute_ideal_maxconn() to calculate maxconn and maxsock, maxsock defines the
size of internal fdtab, which becames very-very large as well. When
the process starts to simply loop over this fdtab (0(n)), this takes a lot of
time, so watchdog does it job.

To avoid this, maxconn now is always reduced to some reasonable value either
by explicit global.fd-hard-limit from configuration, or by its default. The
default may be changed at build-time and overwritten then by
global.fd-hard-limit at runtime. Explicit global.fd-hard-limit from the
configuration has always precedence over DEFAULT_MAXFD, if set.

Must be backported in all stable versions until v2.6.0, including v2.6.0.
This commit is contained in:
Valentine Krasnobaeva
2024-07-03 18:45:35 +02:00
committed by Willy Tarreau
parent bfdf145859
commit 41275a6918
3 changed files with 39 additions and 4 deletions

View File

@@ -1512,7 +1512,19 @@ static int compute_ideal_maxconn()
* - two FDs per connection
*/
if (global.fd_hard_limit && remain > global.fd_hard_limit)
/* on some modern distros for archs like amd64 fs.nr_open (kernel max) could
* be in order of 1 billion, systemd since the version 256~rc3-3 bumped
* fs.nr_open as the hard RLIMIT_NOFILE (rlim_fd_max_at_boot). If we are
* started without global.maxconn or global.rlimit_memmax_all, we risk to
* finish with computed global.maxconn = ~500000000 and computed
* global.maxsock = ~1000000000. So, fdtab will be unnecessary and extremely
* huge and watchdog will kill the process, when it tries to loop over the
* fdtab (see fd_reregister_all).
*/
if (!global.fd_hard_limit)
global.fd_hard_limit = DEFAULT_MAXFD;
if (remain > global.fd_hard_limit)
remain = global.fd_hard_limit;
/* subtract listeners and checks */