MINOR: startup: split main: add step_init_3

The first part of main(), just after calling the former init() and before
trying to bind listeners, need to be also encapsulated into a separate
step_init_3() as it is. It contains important blocks to register signals, to
apply memory and nofile limits, etc. The order of these blocks should be also
preserved (especially the signals part).

For the moment step_init_3() must be also executed for all runtime modes.
This commit is contained in:
Valentine Krasnobaeva 2024-10-07 10:37:01 +02:00 committed by Willy Tarreau
parent 49772c55e3
commit c4795e4019

View File

@ -2755,6 +2755,88 @@ static void step_init_2(int argc, char** argv)
post_mortem_add_component("haproxy", haproxy_version, cc, cflags, opts, argv[0]);
}
/* This is a third part of the late init sequence, where we register signals for
* process in worker and in standalone modes. We also check here, if the
* global.maxsock calculated in step_init_2() could be applied as the nofile limit
* for the process. Memory limit, if set, will be applied here as well. If some
* capabilities were set on the haproxy binary by administrator, we will try to
* put it into the process Effective capabilities set.
*/
static void step_init_3(void)
{
struct rlimit limit;
signal_register_fct(SIGQUIT, dump, SIGQUIT);
signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
signal_register_fct(SIGUSR2, NULL, 0);
/* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
* Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
* was defined there, so let's stay on the safe side.
*/
signal_register_fct(SIGPIPE, NULL, 0);
/* ulimits */
if (!global.rlimit_nofile)
global.rlimit_nofile = global.maxsock;
if (global.rlimit_nofile) {
limit.rlim_cur = global.rlimit_nofile;
limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
if ((global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit) ||
raise_rlim_nofile(NULL, &limit) != 0) {
getrlimit(RLIMIT_NOFILE, &limit);
if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
limit.rlim_cur = global.fd_hard_limit;
if (global.tune.options & GTUNE_STRICT_LIMITS) {
ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
progname, global.rlimit_nofile, (int)limit.rlim_cur);
exit(1);
}
else {
/* try to set it to the max possible at least */
limit.rlim_cur = limit.rlim_max;
if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
limit.rlim_cur = global.fd_hard_limit;
if (raise_rlim_nofile(&limit, &limit) == 0)
getrlimit(RLIMIT_NOFILE, &limit);
ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
progname, global.rlimit_nofile, (int)limit.rlim_cur);
global.rlimit_nofile = limit.rlim_cur;
}
}
}
if (global.rlimit_memmax) {
limit.rlim_cur = limit.rlim_max =
global.rlimit_memmax * 1048576ULL;
if (setrlimit(RLIMIT_DATA, &limit) == -1) {
if (global.tune.options & GTUNE_STRICT_LIMITS) {
ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
progname, global.rlimit_memmax);
exit(1);
}
else
ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
progname, global.rlimit_memmax);
}
}
#if defined(USE_LINUX_CAP)
/* If CAP_NET_BIND_SERVICE is in binary file permitted set and process
* is started and run under the same non-root user, this allows
* binding to privileged ports.
*/
if (!master)
prepare_caps_from_permitted_set(geteuid(), global.uid, progname);
#endif
}
void deinit(void)
{
struct proxy *p = proxies_list, *p0;
@ -3456,75 +3538,10 @@ int main(int argc, char **argv)
*/
step_init_2(argc, argv);
signal_register_fct(SIGQUIT, dump, SIGQUIT);
signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
signal_register_fct(SIGUSR2, NULL, 0);
/* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
* Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
* was defined there, so let's stay on the safe side.
/* Late init step: register signals for worker and standalon modes, apply
* nofile and memory limits, apply capabilities from binary, if any.
*/
signal_register_fct(SIGPIPE, NULL, 0);
/* ulimits */
if (!global.rlimit_nofile)
global.rlimit_nofile = global.maxsock;
if (global.rlimit_nofile) {
limit.rlim_cur = global.rlimit_nofile;
limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
if ((global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit) ||
raise_rlim_nofile(NULL, &limit) != 0) {
getrlimit(RLIMIT_NOFILE, &limit);
if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
limit.rlim_cur = global.fd_hard_limit;
if (global.tune.options & GTUNE_STRICT_LIMITS) {
ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
exit(1);
}
else {
/* try to set it to the max possible at least */
limit.rlim_cur = limit.rlim_max;
if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
limit.rlim_cur = global.fd_hard_limit;
if (raise_rlim_nofile(&limit, &limit) == 0)
getrlimit(RLIMIT_NOFILE, &limit);
ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
global.rlimit_nofile = limit.rlim_cur;
}
}
}
if (global.rlimit_memmax) {
limit.rlim_cur = limit.rlim_max =
global.rlimit_memmax * 1048576ULL;
if (setrlimit(RLIMIT_DATA, &limit) == -1) {
if (global.tune.options & GTUNE_STRICT_LIMITS) {
ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
argv[0], global.rlimit_memmax);
exit(1);
}
else
ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
argv[0], global.rlimit_memmax);
}
}
#if defined(USE_LINUX_CAP)
/* If CAP_NET_BIND_SERVICE is in binary file permitted set and process
* is started and run under the same non-root user, this allows
* binding to privileged ports.
*/
if (!master)
prepare_caps_from_permitted_set(geteuid(), global.uid, argv[0]);
#endif
step_init_3();
/* Try to get the listeners FD from the previous process using
* _getsocks on the stat socket, it must never been done in wait mode