blob: 68c78427d5a53a0b1f5fdf9fbc638d3947f37a0e [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
Willy Tarreaua5357cd2021-05-09 06:14:25 +02002 * HAProxy : High Availability-enabled HTTP/TCP proxy
Willy Tarreau2454d6e2022-02-01 18:06:59 +01003 * Copyright 2000-2022 Willy Tarreau <willy@haproxy.org>.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
Ilya Shipitsin46a030c2020-07-05 16:36:08 +050010 * Please refer to RFC7230 - RFC7235 information about HTTP protocol, and
11 * RFC6265 for information about cookies usage. More generally, the IETF HTTP
Willy Tarreaubaaee002006-06-26 02:48:02 +020012 * Working Group's web site should be consulted for protocol related changes :
13 *
14 * http://ftp.ics.uci.edu/pub/ietf/http/
15 *
16 * Pending bugs (may be not fixed because never reproduced) :
17 * - solaris only : sometimes, an HTTP proxy with only a dispatch address causes
18 * the proxy to terminate (no core) if the client breaks the connection during
19 * the response. Seen on 1.1.8pre4, but never reproduced. May not be related to
20 * the snprintf() bug since requests were simple (GET / HTTP/1.0), but may be
21 * related to missing setsid() (fixed in 1.1.15)
22 * - a proxy with an invalid config will prevent the startup even if disabled.
23 *
24 * ChangeLog has moved to the CHANGELOG file.
25 *
Willy Tarreaubaaee002006-06-26 02:48:02 +020026 */
27
David Carlier7ece0962015-12-08 21:43:09 +000028#define _GNU_SOURCE
Willy Tarreaubaaee002006-06-26 02:48:02 +020029#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <string.h>
33#include <ctype.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020034#include <dirent.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020035#include <sys/stat.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <sys/time.h>
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <netinet/tcp.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42#include <netdb.h>
43#include <fcntl.h>
44#include <errno.h>
45#include <signal.h>
46#include <stdarg.h>
47#include <sys/resource.h>
Tim Duesterhusdfad6a42020-04-18 16:02:47 +020048#include <sys/utsname.h>
Marc-Antoine Perennou992709b2013-02-12 10:53:52 +010049#include <sys/wait.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <time.h>
51#include <syslog.h>
Michael Schererab012dd2013-01-12 18:35:19 +010052#include <grp.h>
Willy Tarreaud10385a2021-10-06 22:22:40 +020053
Willy Tarreau5e03dfa2021-10-06 22:53:51 +020054#ifdef USE_THREAD
55#include <pthread.h>
56#endif
57
Willy Tarreaufc6c0322012-11-16 16:12:27 +010058#ifdef USE_CPU_AFFINITY
Willy Tarreaufc6c0322012-11-16 16:12:27 +010059#include <sched.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000060#if defined(__FreeBSD__) || defined(__DragonFly__)
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020061#include <sys/param.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000062#ifdef __FreeBSD__
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020063#include <sys/cpuset.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000064#endif
David Carlier5e4c8e22019-09-13 05:12:58 +010065#endif
Willy Tarreaufc6c0322012-11-16 16:12:27 +010066#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020067
Willy Tarreau636848a2019-04-15 19:38:50 +020068#if defined(USE_PRCTL)
69#include <sys/prctl.h>
70#endif
71
devnexen@gmail.com21185972021-08-21 09:13:10 +010072#if defined(USE_PROCCTL)
73#include <sys/procctl.h>
74#endif
75
Willy Tarreaubaaee002006-06-26 02:48:02 +020076#ifdef DEBUG_FULL
77#include <assert.h>
78#endif
Tim Duesterhusd6942c82017-11-20 15:58:35 +010079#if defined(USE_SYSTEMD)
80#include <systemd/sd-daemon.h>
81#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020082
Willy Tarreau6c3a6812020-03-06 18:57:15 +010083#include <import/sha1.h>
84
Willy Tarreaub2551052020-06-09 09:07:15 +020085#include <haproxy/acl.h>
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +010086#include <haproxy/action.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020087#include <haproxy/activity.h>
88#include <haproxy/api.h>
89#include <haproxy/arg.h>
90#include <haproxy/auth.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020091#include <haproxy/base64.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020092#include <haproxy/capture-t.h>
Willy Tarreau66243b42021-07-16 15:39:28 +020093#include <haproxy/cfgcond.h>
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +020094#include <haproxy/cfgdiag.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020095#include <haproxy/cfgparse.h>
Willy Tarreauc13ed532020-06-02 10:22:45 +020096#include <haproxy/chunk.h>
Willy Tarreau83487a82020-06-04 20:19:54 +020097#include <haproxy/cli.h>
Willy Tarreau55542642021-10-08 09:33:24 +020098#include <haproxy/clock.h>
Willy Tarreau7ea393d2020-06-04 18:02:10 +020099#include <haproxy/connection.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200100#ifdef USE_CPU_AFFINITY
Amaury Denoyelle982fb532021-04-21 18:39:58 +0200101#include <haproxy/cpuset.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200102#endif
Willy Tarreaueb92deb2020-06-04 10:53:16 +0200103#include <haproxy/dns.h>
Willy Tarreau2741c8c2020-06-02 11:28:02 +0200104#include <haproxy/dynbuf.h>
Willy Tarreau8d366972020-05-27 16:10:29 +0200105#include <haproxy/errors.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200106#include <haproxy/fd.h>
Willy Tarreauc7babd82020-06-04 21:29:29 +0200107#include <haproxy/filters.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200108#include <haproxy/global.h>
Willy Tarreau86416052020-06-04 09:20:54 +0200109#include <haproxy/hlua.h>
Willy Tarreauc761f842020-06-04 11:40:28 +0200110#include <haproxy/http_rules.h>
Willy Tarreau853b2972020-05-27 18:01:47 +0200111#include <haproxy/list.h>
Willy Tarreau213e9902020-06-04 14:58:24 +0200112#include <haproxy/listener.h>
Willy Tarreauaeed4a82020-06-04 22:01:04 +0200113#include <haproxy/log.h>
Willy Tarreaub5abe5b2020-06-04 14:07:37 +0200114#include <haproxy/mworker.h>
Willy Tarreau7a00efb2020-06-02 17:02:59 +0200115#include <haproxy/namespace.h>
Willy Tarreau6131d6a2020-06-02 16:48:09 +0200116#include <haproxy/net_helper.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +0200117#include <haproxy/openssl-compat.h>
Amaury Denoyelle92fa63f2022-09-30 18:11:13 +0200118#include <haproxy/quic_conn-t.h>
Frédéric Lécaille1d96d6e2022-05-23 16:38:14 +0200119#include <haproxy/quic_tp-t.h>
Willy Tarreau225a90a2020-06-04 15:06:28 +0200120#include <haproxy/pattern.h>
Willy Tarreau3c2a7c22020-06-04 18:38:21 +0200121#include <haproxy/peers.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200122#include <haproxy/pool.h>
123#include <haproxy/protocol.h>
Willy Tarreaubf3b06b2020-08-26 10:23:40 +0200124#include <haproxy/proto_tcp.h>
Willy Tarreaua264d962020-06-04 22:29:18 +0200125#include <haproxy/proxy.h>
Willy Tarreau7cd8b6e2020-06-02 17:32:26 +0200126#include <haproxy/regex.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200127#include <haproxy/sample.h>
Willy Tarreau1e56f922020-06-04 23:20:13 +0200128#include <haproxy/server.h>
Willy Tarreau48d25b32020-06-04 18:58:52 +0200129#include <haproxy/session.h>
Willy Tarreau3727a8a2020-06-04 17:37:26 +0200130#include <haproxy/signal.h>
Willy Tarreau063d47d2020-08-28 16:29:53 +0200131#include <haproxy/sock.h>
Willy Tarreau25140cc2020-08-28 15:40:33 +0200132#include <haproxy/sock_inet.h>
Willy Tarreau209108d2020-06-04 20:30:20 +0200133#include <haproxy/ssl_sock.h>
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +0200134#include <haproxy/stats-t.h>
Willy Tarreaudfd3de82020-06-04 23:46:14 +0200135#include <haproxy/stream.h>
Willy Tarreaucea0e1b2020-06-04 17:25:40 +0200136#include <haproxy/task.h>
Willy Tarreau3f567e42020-05-28 15:29:19 +0200137#include <haproxy/thread.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200138#include <haproxy/time.h>
139#include <haproxy/tools.h>
140#include <haproxy/uri_auth-t.h>
Willy Tarreaua1718922020-06-04 16:25:31 +0200141#include <haproxy/vars.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200142#include <haproxy/version.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200143
Willy Tarreaubaaee002006-06-26 02:48:02 +0200144
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100145/* array of init calls for older platforms */
146DECLARE_INIT_STAGES;
147
Willy Tarreauf4596402021-04-10 16:53:05 +0200148/* create a read_mostly section to hold variables which are accessed a lot
149 * but which almost never change. The purpose is to isolate them in their
150 * own cache lines where they don't risk to be perturbated by write accesses
151 * to neighbor variables. We need to create an empty aligned variable for
152 * this. The fact that the variable is of size zero means that it will be
153 * eliminated at link time if no other variable uses it, but alignment will
154 * be respected.
155 */
156empty_t __read_mostly_align HA_SECTION("read_mostly") ALIGNED(64);
157
Willy Tarreauf0d3b732021-05-06 16:30:32 +0200158#ifdef BUILD_FEATURES
159const char *build_features = BUILD_FEATURES;
160#else
161const char *build_features = "";
162#endif
163
Willy Tarreau477ecd82010-01-03 21:12:30 +0100164/* list of config files */
165static struct list cfg_cfgfiles = LIST_HEAD_INIT(cfg_cfgfiles);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166int pid; /* current process id */
167
Willy Tarreauef422ce2022-06-28 19:29:29 +0200168static unsigned long stopping_tgroup_mask; /* Thread groups acknowledging stopping */
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100169
Willy Tarreaubaaee002006-06-26 02:48:02 +0200170/* global options */
171struct global global = {
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100172 .hard_stop_after = TICK_ETERNITY,
Remi Tricot-Le Bretonb5d968d2022-04-08 18:04:18 +0200173 .close_spread_time = TICK_ETERNITY,
174 .close_spread_end = TICK_ETERNITY,
Amaury Denoyelle0f50cb92021-03-26 18:50:33 +0100175 .numa_cpu_mapping = 1,
Willy Tarreau149ab772019-01-26 14:27:06 +0100176 .nbthread = 0,
William Lallemand5f232402012-04-05 18:02:55 +0200177 .req_count = 0,
William Lallemand0f99e342011-10-12 17:50:54 +0200178 .logsrvs = LIST_HEAD_INIT(global.logsrvs),
Willy Tarreau197715a2022-04-25 19:29:10 +0200179 .maxzlibmem = DEFAULT_MAXZLIBMEM * 1024U * 1024U,
William Lallemandd85f9172012-11-09 17:05:39 +0100180 .comp_rate_lim = 0,
Emeric Brun850efd52014-01-29 12:24:34 +0100181 .ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED,
Emeric Bruned760922010-10-22 17:59:25 +0200182 .unix_bind = {
183 .ux = {
184 .uid = -1,
185 .gid = -1,
186 .mode = 0,
187 }
188 },
Willy Tarreau27a674e2009-08-17 07:23:33 +0200189 .tune = {
Willy Tarreau7ac908b2019-02-27 12:02:18 +0100190 .options = GTUNE_LISTENER_MQ,
Willy Tarreauc77d3642018-12-12 06:19:42 +0100191 .bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
Christopher Faulet546c4692020-01-22 14:31:21 +0100192 .maxrewrite = MAXREWRITE,
Willy Tarreaua24adf02014-11-27 01:11:56 +0100193 .reserved_bufs = RESERVED_BUFS,
Willy Tarreauf3045d22015-04-29 16:24:50 +0200194 .pattern_cache = DEFAULT_PAT_LRU_SIZE,
Olivier Houchard88698d92019-04-16 19:07:22 +0200195 .pool_low_ratio = 20,
196 .pool_high_ratio = 25,
Christopher Faulet41ba36f2019-07-19 09:36:45 +0200197 .max_http_hdr = MAX_HTTP_HDR,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200198#ifdef USE_OPENSSL
Emeric Brun46635772012-11-14 11:32:56 +0100199 .sslcachesize = SSLCACHESIZE,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200200#endif
William Lallemandf3747832012-11-09 12:33:10 +0100201 .comp_maxlevel = 1,
Willy Tarreau7e312732014-02-12 16:35:14 +0100202#ifdef DEFAULT_IDLE_TIMER
203 .idle_timer = DEFAULT_IDLE_TIMER,
204#else
205 .idle_timer = 1000, /* 1 second */
206#endif
Amaury Denoyelle97e84c62022-04-19 18:26:55 +0200207#ifdef USE_QUIC
Frédéric Lécailleaee67572022-05-23 18:29:39 +0200208 .quic_backend_max_idle_timeout = QUIC_TP_DFLT_BACK_MAX_IDLE_TIMEOUT,
209 .quic_frontend_max_idle_timeout = QUIC_TP_DFLT_FRONT_MAX_IDLE_TIMEOUT,
210 .quic_frontend_max_streams_bidi = QUIC_TP_DFLT_FRONT_MAX_STREAMS_BIDI,
Frédéric Lécaille92862102022-05-20 16:29:10 +0200211 .quic_retry_threshold = QUIC_DFLT_RETRY_THRESHOLD,
Amaury Denoyelle97e84c62022-04-19 18:26:55 +0200212 .quic_streams_buf = 30,
213#endif /* USE_QUIC */
Willy Tarreau27a674e2009-08-17 07:23:33 +0200214 },
Emeric Brun76d88952012-10-05 15:47:31 +0200215#ifdef USE_OPENSSL
216#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200217 .maxsslconn = DEFAULT_MAXSSLCONN,
218#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200219#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220 /* others NULL OK */
221};
222
223/*********************************************************************/
224
225int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100226int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200227int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100228int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100229int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100230int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreau392524d2022-02-17 18:10:36 +0100231int arg_mode = 0; /* MODE_DEBUG etc as passed on command line ... */
232char *change_dir = NULL; /* set when -C is passed */
233char *check_condition = NULL; /* check condition passed to -cc */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500235/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236 * or kill. We will send them a signal every 10 ms until we can bind to all
237 * our ports. With 200 retries, that's about 2 seconds.
238 */
239#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240static int *oldpids = NULL;
241static int oldpids_sig; /* use USR1 or TERM */
242
Olivier Houchardf73629d2017-04-05 22:33:04 +0200243/* Path to the unix socket we use to retrieve listener sockets from the old process */
244static const char *old_unixsocket;
245
William Lallemandcb11fd22017-06-01 17:38:52 +0200246int atexit_flag = 0;
247
Willy Tarreaubb545b42010-08-25 12:58:59 +0200248int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249const int zero = 0;
250const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200251const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100253char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200254char *localpeer = NULL;
Willy Tarreau76871a42022-03-08 16:01:40 +0100255static char *kwd_dump = NULL; // list of keyword dumps to produce
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256
William Lallemand00417412020-06-05 14:08:41 +0200257static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200258
William Lallemandbc193052018-09-11 10:06:26 +0200259struct list proc_list = LIST_HEAD_INIT(proc_list);
260
261int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100262unsigned int rlim_fd_cur_at_boot = 0;
263unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200264
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100265/* per-boot randomness */
266unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
267
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200268/* takes the thread config in argument or NULL for any thread */
William Lallemandb3f2be32018-09-11 10:06:18 +0200269static void *run_thread_poll_loop(void *data);
270
Willy Tarreauff055502014-04-28 22:27:06 +0200271/* bitfield of a few warnings to emit just once (WARN_*) */
272unsigned int warned = 0;
273
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200274/* set if experimental features have been used for the current process */
Willy Tarreauedd42682022-02-25 10:10:00 +0100275unsigned int tainted = 0;
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200276
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200277unsigned int experimental_directives_allowed = 0;
278
279int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
280 char **errmsg)
281{
282 if (kw->flags & KWF_EXPERIMENTAL) {
283 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200284 memprintf(errmsg, "parsing [%s:%d] : '%s' directive is experimental, must be allowed via a global 'expose-experimental-directives'",
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200285 file, linenum, kw->kw);
286 return 1;
287 }
288 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
289 }
290
291 return 0;
292}
293
William Lallemande7361152018-10-26 14:47:36 +0200294/* master CLI configuration (-S flag) */
295struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100296
297/* These are strings to be reported in the output of "haproxy -vv". They may
298 * either be constants (in which case must_free must be zero) or dynamically
299 * allocated strings to pass to free() on exit, and in this case must_free
300 * must be non-zero.
301 */
302struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
303struct build_opts_str {
304 struct list list;
305 const char *str;
306 int must_free;
307};
308
Willy Tarreaubaaee002006-06-26 02:48:02 +0200309/*********************************************************************/
310/* general purpose functions ***************************************/
311/*********************************************************************/
312
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100313/* used to register some build option strings at boot. Set must_free to
314 * non-zero if the string must be freed upon exit.
315 */
316void hap_register_build_opts(const char *str, int must_free)
317{
318 struct build_opts_str *b;
319
320 b = calloc(1, sizeof(*b));
321 if (!b) {
322 fprintf(stderr, "out of memory\n");
323 exit(1);
324 }
325 b->str = str;
326 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200327 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100328}
329
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200330#define VERSION_MAX_ELTS 7
331
332/* This function splits an haproxy version string into an array of integers.
333 * The syntax of the supported version string is the following:
334 *
335 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
336 *
337 * This validates for example:
338 * 1.2.1-pre2, 1.2.1, 1.2.10.1, 1.3.16-rc1, 1.4-dev3, 1.5-dev18, 1.5-dev18-43
339 * 2.4-dev18-f6818d-20
340 *
341 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
342 * one fixed place in the array. The tags take a numeric value called <e> which
343 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
344 * considered as zero (henxe 1.5 and 1.5.0 are the same).
345 *
346 * The resulting values are:
347 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
348 * 1.2.1 1, 2, 1, 0, 3, 0, 0
349 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
350 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
351 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
352 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
353 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
354 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
355 *
356 * The function returns non-zero if the conversion succeeded, or zero if it
357 * failed.
358 */
359int split_version(const char *version, unsigned int *value)
360{
361 const char *p, *s;
362 char *error;
363 int nelts;
364
365 /* Initialize array with zeroes */
366 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
367 value[nelts] = 0;
368 value[4] = 3;
369
370 p = version;
371
372 /* If the version number is empty, return false */
373 if (*p == '\0')
374 return 0;
375
376 /* Convert first number <a> */
377 value[0] = strtol(p, &error, 10);
378 p = error + 1;
379 if (*error == '\0')
380 return 1;
381 if (*error == '-')
382 goto split_version_tag;
383 if (*error != '.')
384 return 0;
385
386 /* Convert first number <b> */
387 value[1] = strtol(p, &error, 10);
388 p = error + 1;
389 if (*error == '\0')
390 return 1;
391 if (*error == '-')
392 goto split_version_tag;
393 if (*error != '.')
394 return 0;
395
396 /* Convert first number <c> */
397 value[2] = strtol(p, &error, 10);
398 p = error + 1;
399 if (*error == '\0')
400 return 1;
401 if (*error == '-')
402 goto split_version_tag;
403 if (*error != '.')
404 return 0;
405
406 /* Convert first number <d> */
407 value[3] = strtol(p, &error, 10);
408 p = error + 1;
409 if (*error == '\0')
410 return 1;
411 if (*error != '-')
412 return 0;
413
414 split_version_tag:
415 /* Check for commit number */
416 if (*p >= '0' && *p <= '9')
417 goto split_version_commit;
418
419 /* Read tag */
420 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
421 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
422 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
423 else
424 goto split_version_commit;
425
426 /* Convert tag number */
427 value[5] = strtol(p, &error, 10);
428 p = error + 1;
429 if (*error == '\0')
430 return 1;
431 if (*error != '-')
432 return 0;
433
434 split_version_commit:
435 /* Search the last "-" */
436 s = strrchr(p, '-');
437 if (s) {
438 s++;
439 if (*s == '\0')
440 return 0;
441 value[6] = strtol(s, &error, 10);
442 if (*error != '\0')
443 value[6] = 0;
444 return 1;
445 }
446
447 /* convert the version */
448 value[6] = strtol(p, &error, 10);
449 if (*error != '\0')
450 value[6] = 0;
451
452 return 1;
453}
454
455/* This function compares the current haproxy version with an arbitrary version
456 * string. It returns:
457 * -1 : the version in argument is older than the current haproxy version
458 * 0 : the version in argument is the same as the current haproxy version
459 * 1 : the version in argument is newer than the current haproxy version
460 *
461 * Or some errors:
462 * -2 : the current haproxy version is not parsable
463 * -3 : the version in argument is not parsable
464 */
465int compare_current_version(const char *version)
466{
467 unsigned int loc[VERSION_MAX_ELTS];
468 unsigned int mod[VERSION_MAX_ELTS];
469 int i;
470
471 /* split versions */
472 if (!split_version(haproxy_version, loc))
473 return -2;
474 if (!split_version(version, mod))
475 return -3;
476
477 /* compare versions */
478 for (i = 0; i < VERSION_MAX_ELTS; i++) {
479 if (mod[i] < loc[i])
480 return -1;
481 else if (mod[i] > loc[i])
482 return 1;
483 }
484 return 0;
485}
486
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100487static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200488{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200489 struct utsname utsname;
490
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200491 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100492 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100493
494 if (strlen(PRODUCT_URL_BUGS) > 0) {
495 char base_version[20];
496 int dots = 0;
497 char *del;
498
499 /* only retrieve the base version without distro-specific extensions */
500 for (del = haproxy_version; *del; del++) {
501 if (*del == '.')
502 dots++;
503 else if (*del < '0' || *del > '9')
504 break;
505 }
506
507 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
508 if (dots < 2)
509 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
510 else
511 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
512 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200513
514 if (uname(&utsname) == 0) {
515 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
516 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200517}
518
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100519static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100520{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100521 struct build_opts_str *item;
522
Willy Tarreau7b066db2007-12-02 11:28:59 +0100523 printf("Build options :"
524#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100525 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100526#endif
527#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100528 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100529#endif
530#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100531 "\n CC = " BUILD_CC
532#endif
533#ifdef BUILD_CFLAGS
534 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100535#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100536#ifdef BUILD_OPTIONS
537 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100538#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100539#ifdef BUILD_DEBUG
540 "\n DEBUG = " BUILD_DEBUG
541#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100542#ifdef BUILD_FEATURES
543 "\n\nFeature list : " BUILD_FEATURES
544#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200545 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100546 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200547 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100548 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200549
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100550 list_for_each_entry(item, &build_opts_list, list) {
551 puts(item->str);
552 }
553
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100554 putchar('\n');
555
Willy Tarreaube5b6852009-10-03 18:57:08 +0200556 list_pollers(stdout);
557 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200558 list_mux_proto(stdout);
559 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100560 list_services(stdout);
561 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100562 list_filters(stdout);
563 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100564}
565
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566/*
567 * This function prints the command line usage and exits
568 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100569static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200570{
571 display_version();
572 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200573 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200574 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200575 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100576 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreauf4b79c42022-02-23 15:20:53 +0100578 " -dM[<byte>,help,...] debug memory (default: poison with <byte>/0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200580 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200581 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100582#if defined(USE_SYSTEMD)
583 " -Ws master-worker mode with systemd notify support.\n"
584#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200586 " -c check mode : only check config files and exit\n"
Maximilian Maderfc0cceb2021-06-06 00:50:22 +0200587 " -cc check condition : evaluate a condition and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100588 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 " -m limits the usable amount of memory (in MB)\n"
590 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200591 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200592 " -p writes pids of all children to this file\n"
Erwan Le Goasf30c5d72022-09-29 10:34:04 +0200593 " -dC[[key],line] display the configuration file, if there is a key, the file will be anonymised\n"
Willy Tarreaue5733232019-05-22 19:24:06 +0200594#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 " -de disables epoll() usage even when available\n"
596#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200597#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200598 " -dk disables kqueue() usage even when available\n"
599#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200600#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000601 " -dv disables event ports usage even when available\n"
602#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200603#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200604 " -dp disables poll() usage even when available\n"
605#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200606#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100607 " -dS disables splice usage (broken on old kernels)\n"
608#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200609#if defined(USE_GETADDRINFO)
610 " -dG disables getaddrinfo() usage\n"
611#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000612#if defined(SO_REUSEPORT)
613 " -dR disables SO_REUSEPORT usage\n"
614#endif
Willy Tarreau654726d2021-12-28 15:43:11 +0100615#if defined(HA_HAVE_DUMP_LIBS)
616 " -dL dumps loaded object files after config checks\n"
617#endif
Willy Tarreau76871a42022-03-08 16:01:40 +0100618 " -dK{class[,...]} dump registered keywords (use 'help' for list)\n"
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100619 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100620 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200621 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200622 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200623 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200624 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200625 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100627 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 exit(1);
629}
630
631
632
633/*********************************************************************/
634/* more specific functions ***************************************/
635/*********************************************************************/
636
William Lallemand73b85e72017-06-01 17:38:51 +0200637/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
638 * pids the signal was correctly delivered to.
639 */
William Lallemande25473c2019-04-01 11:29:56 +0200640int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200641{
642 int p;
643 int ret = 0;
644 for (p = 0; p < nb_oldpids; p++)
645 if (kill(oldpids[p], sig) == 0)
646 ret++;
647 return ret;
648}
649
William Lallemand75ea0a02017-11-15 19:02:58 +0100650/*
William Lallemand73b85e72017-06-01 17:38:51 +0200651 * remove a pid forom the olpid array and decrease nb_oldpids
652 * return 1 pid was found otherwise return 0
653 */
654
655int delete_oldpid(int pid)
656{
657 int i;
658
659 for (i = 0; i < nb_oldpids; i++) {
660 if (oldpids[i] == pid) {
661 oldpids[i] = oldpids[nb_oldpids - 1];
662 oldpids[nb_oldpids - 1] = 0;
663 nb_oldpids--;
664 return 1;
665 }
666 }
667 return 0;
668}
669
William Lallemand85b0bd92017-06-01 17:38:53 +0200670
William Lallemand73b85e72017-06-01 17:38:51 +0200671/*
672 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800673 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200674 */
William Lallemandfab0fdc2021-11-09 18:01:22 +0100675static void mworker_reexec()
William Lallemand73b85e72017-06-01 17:38:51 +0200676{
William Lallemand00417412020-06-05 14:08:41 +0200677 char **next_argv = NULL;
678 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200679 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200680 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200681 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100682 struct rlimit limit;
William Lallemand2be557f2021-11-24 18:45:37 +0100683 struct mworker_proc *current_child = NULL;
William Lallemand73b85e72017-06-01 17:38:51 +0200684
685 mworker_block_signals();
William Lallemand73b85e72017-06-01 17:38:51 +0200686 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
687
William Lallemand55a921c2022-01-28 21:17:30 +0100688 mworker_cleanup_proc();
William Lallemandbc193052018-09-11 10:06:26 +0200689 mworker_proc_list_to_env(); /* put the children description in the env */
690
William Lallemandc4810b82021-11-18 10:51:30 +0100691 /* ensure that we close correctly every listeners before reexecuting */
692 mworker_cleanlisteners();
693
William Lallemand7c756a82018-11-26 11:53:40 +0100694 /* during the reload we must ensure that every FDs that can't be
695 * reuse (ie those that are not referenced in the proc_list)
696 * are closed or they will leak. */
697
698 /* close the listeners FD */
699 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200700
William Lallemand67e371e2021-11-25 10:03:44 +0100701 if (fdtab)
702 deinit_pollers();
William Lallemandefd95472021-11-26 14:43:57 +0100703
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500704#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200705 /* close random device FDs */
706 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100707#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100708
Willy Tarreau8dca1952019-03-01 10:21:55 +0100709 /* restore the initial FD limits */
710 limit.rlim_cur = rlim_fd_cur_at_boot;
711 limit.rlim_max = rlim_fd_max_at_boot;
Willy Tarreauc06557c2022-09-22 16:12:08 +0200712 if (raise_rlim_nofile(&limit, &limit) != 0) {
Willy Tarreau8dca1952019-03-01 10:21:55 +0100713 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
714 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
715 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
716 }
717
William Lallemand73b85e72017-06-01 17:38:51 +0200718 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200719 while (old_argv[old_argc])
720 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200721
William Lallemand85b0bd92017-06-01 17:38:53 +0200722 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200723 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200724 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200725 if (next_argv == NULL)
726 goto alloc_error;
727
William Lallemand00417412020-06-05 14:08:41 +0200728 /* copy the program name */
729 next_argv[next_argc++] = old_argv[0];
730
731 /* insert the new options just after argv[0] in case we have a -- */
732
William Lallemandbefab9e2021-11-25 00:49:19 +0100733 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
734 /* add -sf <PID>* to argv */
735 if (mworker_child_nb() > 0) {
736 struct mworker_proc *child;
William Lallemand3f128872019-04-01 11:29:59 +0200737
William Lallemandbefab9e2021-11-25 00:49:19 +0100738 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200739
William Lallemandbefab9e2021-11-25 00:49:19 +0100740 list_for_each_entry(child, &proc_list, list) {
741 if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
742 current_child = child;
William Lallemand2be557f2021-11-24 18:45:37 +0100743
William Lallemandbefab9e2021-11-25 00:49:19 +0100744 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
745 continue;
746 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
747 goto alloc_error;
748 msg = NULL;
749 }
William Lallemand73b85e72017-06-01 17:38:51 +0200750 }
William Lallemand2be557f2021-11-24 18:45:37 +0100751
752 if (current_child) {
753 /* add the -x option with the socketpair of the current worker */
754 next_argv[next_argc++] = "-x";
755 if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
756 goto alloc_error;
757 msg = NULL;
758 }
William Lallemand85b0bd92017-06-01 17:38:53 +0200759 }
760
William Lallemand00417412020-06-05 14:08:41 +0200761 /* copy the previous options */
762 for (i = 1; i < old_argc; i++)
763 next_argv[next_argc++] = old_argv[i];
764
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200765 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100766 execvp(next_argv[0], next_argv);
Christopher Faulet767a84b2017-11-24 16:50:31 +0100767 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100768 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100769 return;
770
William Lallemand73b85e72017-06-01 17:38:51 +0200771alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100772 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800773 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200774 return;
775}
776
William Lallemandfab0fdc2021-11-09 18:01:22 +0100777/* reexec haproxy in waitmode */
778static void mworker_reexec_waitmode()
779{
780 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
781 mworker_reexec();
782}
783
784/* reload haproxy and emit a warning */
785void mworker_reload()
786{
William Lallemandad221f42021-11-09 18:43:59 +0100787 struct mworker_proc *child;
William Lallemandefd95472021-11-26 14:43:57 +0100788 struct per_thread_deinit_fct *ptdf;
William Lallemandad221f42021-11-09 18:43:59 +0100789
William Lallemand836bda22021-11-09 18:16:47 +0100790 ha_notice("Reloading HAProxy\n");
William Lallemandad221f42021-11-09 18:43:59 +0100791
William Lallemandefd95472021-11-26 14:43:57 +0100792 /* close the poller FD and the thread waker pipe FD */
793 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
794 ptdf->fct();
795
William Lallemandad221f42021-11-09 18:43:59 +0100796 /* increment the number of reloads */
797 list_for_each_entry(child, &proc_list, list) {
798 child->reloads++;
799 }
800
William Lallemanda46a99e2022-07-07 14:00:36 +0200801#if defined(USE_SYSTEMD)
802 if (global.tune.options & GTUNE_USE_SYSTEMD)
803 sd_notify(0, "RELOADING=1\nSTATUS=Reloading Configuration.\n");
804#endif
William Lallemandfab0fdc2021-11-09 18:01:22 +0100805 mworker_reexec();
806}
807
William Lallemandb3f2be32018-09-11 10:06:18 +0200808static void mworker_loop()
809{
810
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200811 /* Busy polling makes no sense in the master :-) */
812 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200813
William Lallemandbc193052018-09-11 10:06:26 +0200814
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100815 signal_unregister(SIGTTIN);
816 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100817 signal_unregister(SIGUSR1);
818 signal_unregister(SIGHUP);
819 signal_unregister(SIGQUIT);
820
William Lallemandb3f2be32018-09-11 10:06:18 +0200821 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
822 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100823 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
824 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200825 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
826 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
827 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
828 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
829
830 mworker_unblock_signals();
William Lallemand27f3fa52018-12-06 14:05:20 +0100831 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200832
William Lallemandbc193052018-09-11 10:06:26 +0200833 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
834 some SIGCHLD were lost */
835
William Lallemandb3f2be32018-09-11 10:06:18 +0200836 jobs++; /* this is the "master" job, we want to take care of the
837 signals even if there is no listener so the poll loop don't
838 leave */
839
840 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200841 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200842}
William Lallemandcb11fd22017-06-01 17:38:52 +0200843
844/*
845 * Reexec the process in failure mode, instead of exiting
846 */
847void reexec_on_failure()
848{
William Lallemand68836742021-11-10 10:49:06 +0100849 struct mworker_proc *child;
850
William Lallemandcb11fd22017-06-01 17:38:52 +0200851 if (!atexit_flag)
852 return;
William Lallemand68836742021-11-10 10:49:06 +0100853
854 /* get the info of the children in the env */
855 if (mworker_env_to_proc_list() < 0) {
856 exit(EXIT_FAILURE);
857 }
858
859 /* increment the number of failed reloads */
860 list_for_each_entry(child, &proc_list, list) {
861 child->failedreloads++;
862 }
863
Willy Tarreaue08acae2022-01-28 18:40:06 +0100864 /* do not keep unused FDs retrieved from the previous process */
865 sock_drop_unused_old_sockets();
866
William Lallemandfab0fdc2021-11-09 18:01:22 +0100867 usermsgs_clr(NULL);
William Lallemand68192b22022-09-24 15:44:42 +0200868 setenv("HAPROXY_LOAD_SUCCESS", "0", 1);
William Lallemand836bda22021-11-09 18:16:47 +0100869 ha_warning("Loading failure!\n");
William Lallemanda46a99e2022-07-07 14:00:36 +0200870#if defined(USE_SYSTEMD)
871 /* the sd_notify API is not able to send a reload failure signal. So
872 * the READY=1 signal still need to be sent */
873 if (global.tune.options & GTUNE_USE_SYSTEMD)
874 sd_notify(0, "READY=1\nSTATUS=Reload failed!\n");
875#endif
876
William Lallemandfab0fdc2021-11-09 18:01:22 +0100877 mworker_reexec_waitmode();
William Lallemandcb11fd22017-06-01 17:38:52 +0200878}
William Lallemand73b85e72017-06-01 17:38:51 +0200879
William Lallemand40db4ae2022-12-07 15:03:55 +0100880/*
881 * Exit with an error message upon a wait-mode failure.
882 */
883void exit_on_waitmode_failure()
884{
885 if (!atexit_flag)
886 return;
887
888 ha_alert("Non-recoverable mworker wait-mode error, exiting.\n");
889}
890
William Lallemand73b85e72017-06-01 17:38:51 +0200891
892/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200893 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
894 * a signal zero to all subscribers. This means that it's as easy as
895 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200896 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100897static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898{
899 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200900 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100901 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902}
903
904/*
905 * upon SIGTTOU, we pause everything
906 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100907static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908{
Willy Tarreau775e0012020-09-24 16:36:26 +0200909 if (protocol_pause_all() & ERR_FATAL) {
910 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200911 ha_warning("%s", msg);
912 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200913 soft_stop();
914 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100915 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916}
917
918/*
919 * upon SIGTTIN, let's have a soft stop.
920 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100921static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922{
Willy Tarreau775e0012020-09-24 16:36:26 +0200923 if (protocol_resume_all() & ERR_FATAL) {
924 const char *msg = "Some proxies refused to resume, probably due to a conflict on a listening port. You may want to try again after the conflicting application is stopped, otherwise a restart might be needed to resume safe operations.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200925 ha_warning("%s", msg);
926 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200927 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200928}
929
930/*
931 * this function dumps every server's state when the process receives SIGHUP.
932 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100933static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200934{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100935 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936
Christopher Faulet767a84b2017-11-24 16:50:31 +0100937 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938 while (p) {
939 struct server *s = p->srv;
940
941 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
942 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100943 chunk_printf(&trash,
944 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
945 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200946 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200947 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200948 ha_warning("%s\n", trash.area);
949 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950 s = s->next;
951 }
952
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200953 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
954 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100955 chunk_printf(&trash,
956 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
957 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200958 p->feconn, p->beconn, p->totpend, p->queue.length, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200959 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100960 chunk_printf(&trash,
961 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
962 p->id,
963 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200964 p->feconn, p->beconn, p->totpend, p->queue.length, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200965 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100966 chunk_printf(&trash,
967 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
968 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
969 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200970 p->feconn, p->beconn, p->totpend, p->queue.length, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200971 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200972 ha_warning("%s\n", trash.area);
973 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974
975 p = p->next;
976 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200977}
978
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100979static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200980{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200981 /* dump memory usage then free everything possible */
982 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100983 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200984}
985
William Lallemande1340412017-12-28 16:09:36 +0100986/*
987 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
988 * If <fd> < 0, it opens /dev/null and use it to dup
989 *
990 * In the case of chrooting, you have to open /dev/null before the chroot, and
991 * pass the <fd> to this function
992 */
993static void stdio_quiet(int fd)
994{
995 if (fd < 0)
996 fd = open("/dev/null", O_RDWR, 0);
997
998 if (fd > -1) {
999 fclose(stdin);
1000 fclose(stdout);
1001 fclose(stderr);
1002
1003 dup2(fd, 0);
1004 dup2(fd, 1);
1005 dup2(fd, 2);
1006 if (fd > 2)
1007 close(fd);
1008 return;
1009 }
1010
1011 ha_alert("Cannot open /dev/null\n");
1012 exit(EXIT_FAILURE);
1013}
1014
1015
Joseph Herlant03420902018-11-15 10:41:50 -08001016/* This function checks if cfg_cfgfiles contains directories.
1017 * If it finds one, it adds all the files (and only files) it contains
1018 * in cfg_cfgfiles in place of the directory (and removes the directory).
1019 * It adds the files in lexical order.
1020 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001021 * It doesn't add files with name starting with '.'
1022 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001023static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001024{
1025 struct wordlist *wl, *wlb;
1026 char *err = NULL;
1027
1028 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1029 struct stat file_stat;
1030 struct dirent **dir_entries = NULL;
1031 int dir_entries_nb;
1032 int dir_entries_it;
1033
1034 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001035 ha_alert("Cannot open configuration file/directory %s : %s\n",
1036 wl->s,
1037 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001038 exit(1);
1039 }
1040
1041 if (!S_ISDIR(file_stat.st_mode))
1042 continue;
1043
1044 /* from this point wl->s is a directory */
1045
1046 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1047 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001048 ha_alert("Cannot open configuration directory %s : %s\n",
1049 wl->s,
1050 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001051 exit(1);
1052 }
1053
1054 /* for each element in the directory wl->s */
1055 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1056 struct dirent *dir_entry = dir_entries[dir_entries_it];
1057 char *filename = NULL;
1058 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1059
1060 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001061 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001062 */
1063 if (dir_entry->d_name[0] == '.' ||
1064 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1065 goto next_dir_entry;
1066
1067 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001068 ha_alert("Cannot load configuration files %s : out of memory.\n",
1069 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001070 exit(1);
1071 }
1072
1073 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001074 ha_alert("Cannot open configuration file %s : %s\n",
1075 wl->s,
1076 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001077 exit(1);
1078 }
1079
1080 /* don't add anything else than regular file in cfg_cfgfiles
1081 * this way we avoid loops
1082 */
1083 if (!S_ISREG(file_stat.st_mode))
1084 goto next_dir_entry;
1085
1086 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001087 ha_alert("Cannot load configuration files %s : %s\n",
1088 filename,
1089 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001090 exit(1);
1091 }
1092
1093next_dir_entry:
1094 free(filename);
1095 free(dir_entry);
1096 }
1097
1098 free(dir_entries);
1099
1100 /* remove the current directory (wl) from cfg_cfgfiles */
1101 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001102 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001103 free(wl);
1104 }
1105
1106 free(err);
1107}
1108
Willy Tarreaubaaee002006-06-26 02:48:02 +02001109/*
William Lallemand73b85e72017-06-01 17:38:51 +02001110 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001111 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001112 * Return an allocated copy of argv
1113 */
1114
1115static char **copy_argv(int argc, char **argv)
1116{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001117 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001118
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001119 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001120 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001121 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001122 return NULL;
1123 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001124 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001125
William Lallemanddf6c5a82020-06-04 17:40:23 +02001126 /* first copy argv[0] */
1127 *newargv++ = *argv++;
1128 argc--;
1129
1130 while (argc > 0) {
1131 if (**argv != '-') {
1132 /* non options are copied but will fail in the argument parser */
1133 *newargv++ = *argv++;
1134 argc--;
1135
1136 } else {
1137 char *flag;
1138
1139 flag = *argv + 1;
1140
1141 if (flag[0] == '-' && flag[1] == 0) {
1142 /* "--\0" copy every arguments till the end of argv */
1143 *newargv++ = *argv++;
1144 argc--;
1145
1146 while (argc > 0) {
1147 *newargv++ = *argv++;
1148 argc--;
1149 }
1150 } else {
1151 switch (*flag) {
1152 case 's':
1153 /* -sf / -st and their parameters are ignored */
1154 if (flag[1] == 'f' || flag[1] == 't') {
1155 argc--;
1156 argv++;
1157 /* The list can't contain a negative value since the only
1158 way to know the end of this list is by looking for the
1159 next option or the end of the options */
1160 while (argc > 0 && argv[0][0] != '-') {
1161 argc--;
1162 argv++;
1163 }
William Lallemand398da622020-09-02 16:12:23 +02001164 } else {
1165 argc--;
1166 argv++;
1167
William Lallemanddf6c5a82020-06-04 17:40:23 +02001168 }
1169 break;
1170
1171 case 'x':
1172 /* this option and its parameter are ignored */
1173 argc--;
1174 argv++;
1175 if (argc > 0) {
1176 argc--;
1177 argv++;
1178 }
1179 break;
1180
1181 case 'C':
1182 case 'n':
1183 case 'm':
1184 case 'N':
1185 case 'L':
1186 case 'f':
1187 case 'p':
1188 case 'S':
1189 /* these options have only 1 parameter which must be copied and can start with a '-' */
1190 *newargv++ = *argv++;
1191 argc--;
1192 if (argc == 0)
1193 goto error;
1194 *newargv++ = *argv++;
1195 argc--;
1196 break;
1197 default:
1198 /* for other options just copy them without parameters, this is also done
1199 * for options like "--foo", but this will fail in the argument parser.
1200 * */
1201 *newargv++ = *argv++;
1202 argc--;
1203 break;
1204 }
William Lallemand73b85e72017-06-01 17:38:51 +02001205 }
1206 }
William Lallemand73b85e72017-06-01 17:38:51 +02001207 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001208
William Lallemanddf6c5a82020-06-04 17:40:23 +02001209 return retargv;
1210
1211error:
1212 free(retargv);
1213 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001214}
1215
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001216
1217/* Performs basic random seed initialization. The main issue with this is that
1218 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1219 * which means that there will only be 4 billion possible random sequences once
1220 * srandom() is called, regardless of the internal state. Not calling it is
1221 * even worse as we'll always produce the same randoms sequences. What we do
1222 * here is to create an initial sequence from various entropy sources, hash it
1223 * using SHA1 and keep the resulting 160 bits available globally.
1224 *
1225 * We initialize the current process with the first 32 bits before starting the
1226 * polling loop, where all this will be changed to have process specific and
1227 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001228 *
1229 * Before starting threads, it's still possible to call random() as srandom()
1230 * is initialized from this, but after threads and/or processes are started,
1231 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001232 */
1233static void ha_random_boot(char *const *argv)
1234{
1235 unsigned char message[256];
1236 unsigned char *m = message;
1237 struct timeval tv;
1238 blk_SHA_CTX ctx;
1239 unsigned long l;
1240 int fd;
1241 int i;
1242
1243 /* start with current time as pseudo-random seed */
1244 gettimeofday(&tv, NULL);
1245 write_u32(m, tv.tv_sec); m += 4;
1246 write_u32(m, tv.tv_usec); m += 4;
1247
1248 /* PID and PPID add some OS-based randomness */
1249 write_u16(m, getpid()); m += 2;
1250 write_u16(m, getppid()); m += 2;
1251
1252 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1253 fd = open("/dev/urandom", O_RDONLY);
1254 if (fd >= 0) {
1255 i = read(fd, m, 20);
1256 if (i > 0)
1257 m += i;
1258 close(fd);
1259 }
1260
1261 /* take up to 160 bits bytes from openssl (non-blocking) */
1262#ifdef USE_OPENSSL
1263 if (RAND_bytes(m, 20) == 1)
1264 m += 20;
1265#endif
1266
1267 /* take 160 bits from existing random in case it was already initialized */
1268 for (i = 0; i < 5; i++) {
1269 write_u32(m, random());
1270 m += 4;
1271 }
1272
1273 /* stack address (benefit form operating system's ASLR) */
1274 l = (unsigned long)&m;
1275 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1276
1277 /* argv address (benefit form operating system's ASLR) */
1278 l = (unsigned long)&argv;
1279 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1280
1281 /* use tv_usec again after all the operations above */
1282 gettimeofday(&tv, NULL);
1283 write_u32(m, tv.tv_usec); m += 4;
1284
1285 /*
1286 * At this point, ~84-92 bytes have been used
1287 */
1288
1289 /* finish with the hostname */
1290 strncpy((char *)m, hostname, message + sizeof(message) - m);
1291 m += strlen(hostname);
1292
1293 /* total message length */
1294 l = m - message;
1295
1296 memset(&ctx, 0, sizeof(ctx));
1297 blk_SHA1_Init(&ctx);
1298 blk_SHA1_Update(&ctx, message, l);
1299 blk_SHA1_Final(boot_seed, &ctx);
1300
1301 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001302 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001303}
1304
Willy Tarreau5a023f02019-03-01 14:19:31 +01001305/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1306 * setting, and returns it. It may return -1 meaning "unlimited" if some
1307 * unlimited proxies have been found and the global.maxconn value is not yet
1308 * set. It may also return a value greater than maxconn if it's not yet set.
1309 * Note that a value of zero means there is no need for pipes. -1 is never
1310 * returned if global.maxconn is valid.
1311 */
1312static int compute_ideal_maxpipes()
1313{
1314 struct proxy *cur;
1315 int nbfe = 0, nbbe = 0;
1316 int unlimited = 0;
1317 int pipes;
1318 int max;
1319
1320 for (cur = proxies_list; cur; cur = cur->next) {
1321 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1322 if (cur->cap & PR_CAP_FE) {
1323 max = cur->maxconn;
1324 nbfe += max;
1325 if (!max) {
1326 unlimited = 1;
1327 break;
1328 }
1329 }
1330 if (cur->cap & PR_CAP_BE) {
1331 max = cur->fullconn ? cur->fullconn : global.maxconn;
1332 nbbe += max;
1333 if (!max) {
1334 unlimited = 1;
1335 break;
1336 }
1337 }
1338 }
1339 }
1340
1341 pipes = MAX(nbfe, nbbe);
1342 if (global.maxconn) {
1343 if (pipes > global.maxconn || unlimited)
1344 pipes = global.maxconn;
1345 } else if (unlimited) {
1346 pipes = -1;
1347 }
1348
1349 return pipes >= 4 ? pipes / 4 : pipes;
1350}
1351
Willy Tarreauac350932019-03-01 15:43:14 +01001352/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1353 * rlimits and computes an ideal maxconn. It's meant to be called only when
1354 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001355 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1356 * default 100) is returned as it is expected that it will even run on tight
1357 * environments, and will maintain compatibility with previous packages that
1358 * used to rely on this value as the default one. The system will emit a
1359 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001360 */
1361static int compute_ideal_maxconn()
1362{
1363 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1364 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1365 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001366 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001367 int maxconn;
1368
1369 /* we have to take into account these elements :
1370 * - number of engine_fds, which inflates the number of FD needed per
1371 * connection by this number.
1372 * - number of pipes per connection on average : for the unlimited
1373 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1374 * fixed value of 2*pipes.
1375 * - two FDs per connection
1376 */
1377
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02001378 if (global.fd_hard_limit && remain > global.fd_hard_limit)
1379 remain = global.fd_hard_limit;
1380
Willy Tarreauac350932019-03-01 15:43:14 +01001381 /* subtract listeners and checks */
1382 remain -= global.maxsock;
1383
Willy Tarreau3f200852019-03-14 19:13:17 +01001384 /* one epoll_fd/kqueue_fd per thread */
1385 remain -= global.nbthread;
1386
1387 /* one wake-up pipe (2 fd) per thread */
1388 remain -= 2 * global.nbthread;
1389
Willy Tarreauac350932019-03-01 15:43:14 +01001390 /* Fixed pipes values : we only subtract them if they're not larger
1391 * than the remaining FDs because pipes are optional.
1392 */
1393 if (pipes >= 0 && pipes * 2 < remain)
1394 remain -= pipes * 2;
1395
1396 if (pipes < 0) {
1397 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1398 * = maxconn * (2 + 0.5 + engine_fds)
1399 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1400 */
1401 maxconn = 2 * remain / (5 + 2 * engine_fds);
1402 } else {
1403 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1404 * = maxconn * (2 + engine_fds)
1405 */
1406 maxconn = remain / (2 + engine_fds);
1407 }
1408
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001409 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001410}
1411
Willy Tarreaua409f302020-03-10 17:08:53 +01001412/* computes the estimated maxsock value for the given maxconn based on the
1413 * possibly set global.maxpipes and existing partial global.maxsock. It may
1414 * temporarily change global.maxconn for the time needed to propagate the
1415 * computations, and will reset it.
1416 */
1417static int compute_ideal_maxsock(int maxconn)
1418{
1419 int maxpipes = global.maxpipes;
1420 int maxsock = global.maxsock;
1421
1422
1423 if (!maxpipes) {
1424 int old_maxconn = global.maxconn;
1425
1426 global.maxconn = maxconn;
1427 maxpipes = compute_ideal_maxpipes();
1428 global.maxconn = old_maxconn;
1429 }
1430
1431 maxsock += maxconn * 2; /* each connection needs two sockets */
1432 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1433 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1434 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1435
1436 /* compute fd used by async engines */
1437 if (global.ssl_used_async_engines) {
1438 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1439
1440 maxsock += maxconn * sides * global.ssl_used_async_engines;
1441 }
1442 return maxsock;
1443}
1444
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001445/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001446 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1447 * value is accepted, non-zero otherwise. This is used to determine if an
1448 * automatic limit may be applied or not. When it is not, the caller knows that
1449 * the highest we can do is the rlim_max at boot. In case of error, we return
1450 * that the setting is possible, so that we defer the error processing to the
1451 * final stage in charge of enforcing this.
1452 */
1453static int check_if_maxsock_permitted(int maxsock)
1454{
1455 struct rlimit orig_limit, test_limit;
1456 int ret;
1457
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02001458 if (global.fd_hard_limit && maxsock > global.fd_hard_limit)
1459 return 0;
1460
Willy Tarreau304e17e2020-03-10 17:54:54 +01001461 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1462 return 1;
1463
1464 /* don't go further if we can't even set to what we have */
Willy Tarreauc06557c2022-09-22 16:12:08 +02001465 if (raise_rlim_nofile(NULL, &orig_limit) != 0)
Willy Tarreau304e17e2020-03-10 17:54:54 +01001466 return 1;
1467
1468 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1469 test_limit.rlim_cur = test_limit.rlim_max;
Willy Tarreauc06557c2022-09-22 16:12:08 +02001470 ret = raise_rlim_nofile(NULL, &test_limit);
Willy Tarreau304e17e2020-03-10 17:54:54 +01001471
Willy Tarreauc06557c2022-09-22 16:12:08 +02001472 if (raise_rlim_nofile(NULL, &orig_limit) != 0)
Willy Tarreau304e17e2020-03-10 17:54:54 +01001473 return 1;
1474
1475 return ret == 0;
1476}
1477
Willy Tarreau34527d52022-02-17 17:45:58 +01001478/* This performs th every basic early initialization at the end of the PREPARE
1479 * init stage. It may only assume that list heads are initialized, but not that
1480 * anything else is correct. It will initialize a number of variables that
1481 * depend on command line and will pre-parse the command line. If it fails, it
1482 * directly exits.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001483 */
Willy Tarreau34527d52022-02-17 17:45:58 +01001484static void init_early(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001485{
Kevinm48936af2010-12-22 16:08:21 +00001486 char *progname;
Willy Tarreau34527d52022-02-17 17:45:58 +01001487 char *tmp;
1488 int len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001489
Willy Tarreau34527d52022-02-17 17:45:58 +01001490 /* First, let's initialize most global variables */
1491 totalconn = actconn = listeners = stopping = 0;
1492 killed = pid = 0;
1493
1494 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
1495 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Christopher Faulete3a5e352017-10-24 13:53:54 +02001496 global.mode = MODE_STARTING;
William Lallemand73b85e72017-06-01 17:38:51 +02001497
Willy Tarreau34527d52022-02-17 17:45:58 +01001498 /* if we were in mworker mode, we should restart in mworker mode */
1499 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1500 global.mode |= MODE_MWORKER;
David du Colombier7af46052012-05-16 14:16:48 +02001501
Willy Tarreau34527d52022-02-17 17:45:58 +01001502 /* initialize date, time, and pid */
1503 tzset();
1504 clock_init_process_date();
1505 start_date = now;
1506 pid = getpid();
1507
1508 /* Set local host name and adjust some environment variables.
1509 * NB: POSIX does not make it mandatory for gethostname() to
1510 * NULL-terminate the string in case of truncation, and at least
1511 * FreeBSD appears not to do it.
Emeric Brun2b920a12010-09-23 18:30:22 +02001512 */
1513 memset(hostname, 0, sizeof(hostname));
1514 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001515
Willy Tarreau34527d52022-02-17 17:45:58 +01001516 /* preset some environment variables */
1517 localpeer = strdup(hostname);
1518 if (!localpeer || setenv("HAPROXY_LOCALPEER", localpeer, 1) < 0) {
Dragan Dosen4f014152020-06-18 16:56:47 +02001519 ha_alert("Cannot allocate memory for local peer.\n");
1520 exit(EXIT_FAILURE);
1521 }
Emeric Brun2b920a12010-09-23 18:30:22 +02001522
Willy Tarreau34527d52022-02-17 17:45:58 +01001523 /* Some CPU affinity stuff may have to be initialized */
1524#ifdef USE_CPU_AFFINITY
1525 {
Willy Tarreau5b093412022-07-08 09:38:30 +02001526 int g, i;
1527
1528 for (g = 0; g < MAX_TGROUPS; g++) {
1529 ha_cpuset_zero(&cpu_map[g].proc);
1530 ha_cpuset_zero(&cpu_map[g].proc_t1);
1531 for (i = 0; i < MAX_THREADS_PER_GROUP; ++i) {
1532 ha_cpuset_zero(&cpu_map[g].thread[i]);
1533 }
Willy Tarreau34527d52022-02-17 17:45:58 +01001534 }
1535 }
1536#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001537
Willy Tarreau34527d52022-02-17 17:45:58 +01001538 /* extract the program name from argv[0], it will be used for the logs
1539 * and error messages.
1540 */
1541 progname = *argv;
1542 while ((tmp = strchr(progname, '/')) != NULL)
1543 progname = tmp + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001544
Willy Tarreau34527d52022-02-17 17:45:58 +01001545 len = strlen(progname);
1546 progname = strdup(progname);
1547 if (!progname) {
1548 ha_alert("Cannot allocate memory for log_tag.\n");
1549 exit(EXIT_FAILURE);
1550 }
Willy Tarreau84310e22014-02-14 11:59:04 +01001551
Willy Tarreau34527d52022-02-17 17:45:58 +01001552 chunk_initlen(&global.log_tag, progname, len, len);
1553}
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001554
Willy Tarreau392524d2022-02-17 18:10:36 +01001555/* handles program arguments. Very minimal parsing is performed, variables are
1556 * fed with some values, and lists are completed with other ones. In case of
1557 * error, it will exit.
Willy Tarreau34527d52022-02-17 17:45:58 +01001558 */
Willy Tarreau392524d2022-02-17 18:10:36 +01001559static void init_args(int argc, char **argv)
Willy Tarreau34527d52022-02-17 17:45:58 +01001560{
Willy Tarreau34527d52022-02-17 17:45:58 +01001561 char *progname = global.log_tag.area;
Willy Tarreau392524d2022-02-17 18:10:36 +01001562 char *err_msg = NULL;
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001563
Willy Tarreau34527d52022-02-17 17:45:58 +01001564 /* pre-fill in the global tuning options before we let the cmdline
1565 * change them.
1566 */
Willy Tarreau43b78992009-01-25 15:42:27 +01001567 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001568#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001569 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001571#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001572 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001573#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001574#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001575 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001576#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001577#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001578 global.tune.options |= GTUNE_USE_EVPORTS;
1579#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001580#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001581 global.tune.options |= GTUNE_USE_SPLICE;
1582#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001583#if defined(USE_GETADDRINFO)
1584 global.tune.options |= GTUNE_USE_GAI;
1585#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001586#if defined(SO_REUSEPORT)
1587 global.tune.options |= GTUNE_USE_REUSEPORT;
1588#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001589#ifdef USE_THREAD
1590 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1591#endif
Amaury Denoyellee30f3782022-11-21 11:54:13 +01001592#ifdef USE_QUIC
1593 global.tune.options |= GTUNE_QUIC_SOCK_PER_CONN;
1594#endif
William Dauchya5194602020-03-28 19:29:58 +01001595 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596
Willy Tarreau392524d2022-02-17 18:10:36 +01001597 /* keep a copy of original arguments for the master process */
1598 old_argv = copy_argv(argc, argv);
1599 if (!old_argv) {
1600 ha_alert("failed to copy argv.\n");
1601 exit(EXIT_FAILURE);
1602 }
1603
1604 /* skip program name and start */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 argc--; argv++;
1606 while (argc > 0) {
1607 char *flag;
1608
1609 if (**argv == '-') {
1610 flag = *argv+1;
1611
1612 /* 1 arg */
1613 if (*flag == 'v') {
1614 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001615 if (flag[1] == 'v') /* -vv */
1616 display_build_opts();
Tim Duesterhus77b3db02022-04-27 00:08:11 +02001617 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001618 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001619#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001621 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001623#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001624 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001625 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001626#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001627#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001628 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001629 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001630#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001631#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001632 else if (*flag == 'd' && flag[1] == 'v')
1633 global.tune.options &= ~GTUNE_USE_EVPORTS;
1634#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001635#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001636 else if (*flag == 'd' && flag[1] == 'S')
1637 global.tune.options &= ~GTUNE_USE_SPLICE;
1638#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001639#if defined(USE_GETADDRINFO)
1640 else if (*flag == 'd' && flag[1] == 'G')
1641 global.tune.options &= ~GTUNE_USE_GAI;
1642#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001643#if defined(SO_REUSEPORT)
1644 else if (*flag == 'd' && flag[1] == 'R')
1645 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1646#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001647 else if (*flag == 'd' && flag[1] == 'V')
1648 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 else if (*flag == 'V')
1650 arg_mode |= MODE_VERBOSE;
Erwan Le Goasb0c05012022-09-14 17:51:55 +02001651 else if (*flag == 'd' && flag[1] == 'C') {
Erwan Le Goasf30c5d72022-09-29 10:34:04 +02001652 char *end;
1653 char *key;
1654
1655 key = flag + 2;
1656 for (;key && *key; key = end) {
1657 end = strchr(key, ',');
1658 if (end)
1659 *(end++) = 0;
1660
1661 if (strcmp(key, "line") == 0)
1662 arg_mode |= MODE_DUMP_NB_L;
1663
1664 }
Erwan Le Goasb0c05012022-09-14 17:51:55 +02001665 arg_mode |= MODE_DUMP_CFG;
1666 HA_ATOMIC_STORE(&global.anon_key, atoll(flag + 2));
1667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001668 else if (*flag == 'd' && flag[1] == 'b')
1669 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001670 else if (*flag == 'd' && flag[1] == 'D')
1671 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001672 else if (*flag == 'd' && flag[1] == 'W')
1673 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreauef301b72022-02-23 14:15:18 +01001674 else if (*flag == 'd' && flag[1] == 'M') {
Willy Tarreau1408b1f2022-02-18 18:54:40 +01001675 int ret = pool_parse_debugging(flag + 2, &err_msg);
1676
1677 if (ret <= -1) {
1678 if (ret < -1)
1679 ha_alert("-dM: %s\n", err_msg);
1680 else
1681 printf("%s\n", err_msg);
1682 ha_free(&err_msg);
1683 exit(ret < -1 ? EXIT_FAILURE : 0);
1684 } else if (ret == 0) {
1685 ha_warning("-dM: %s\n", err_msg);
1686 ha_free(&err_msg);
1687 }
Willy Tarreauef301b72022-02-23 14:15:18 +01001688 }
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001689 else if (*flag == 'd' && flag[1] == 'r')
1690 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreau654726d2021-12-28 15:43:11 +01001691#if defined(HA_HAVE_DUMP_LIBS)
1692 else if (*flag == 'd' && flag[1] == 'L')
1693 arg_mode |= MODE_DUMP_LIBS;
1694#endif
Willy Tarreau76871a42022-03-08 16:01:40 +01001695 else if (*flag == 'd' && flag[1] == 'K') {
1696 arg_mode |= MODE_DUMP_KWD;
1697 kwd_dump = flag + 2;
1698 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001699 else if (*flag == 'd')
1700 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001701 else if (*flag == 'c' && flag[1] == 'c') {
1702 arg_mode |= MODE_CHECK_CONDITION;
1703 argv++;
1704 argc--;
1705 check_condition = *argv;
1706 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001707 else if (*flag == 'c')
1708 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001709 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001710 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001711 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001712 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001713#if defined(USE_SYSTEMD)
1714 global.tune.options |= GTUNE_USE_SYSTEMD;
1715#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001716 ha_alert("master-worker mode with systemd support (-Ws) requested, but not compiled. Use master-worker mode (-W) if you are not using Type=notify in your unit file or recompile with USE_SYSTEMD=1.\n\n");
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001717 usage(progname);
1718#endif
1719 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001720 else if (*flag == 'W')
1721 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001722 else if (*flag == 'q')
1723 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001724 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001725 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001726 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001727 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001728 }
William Lallemand4fc09692017-06-19 16:37:19 +02001729 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001730 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001731 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001732
Olivier Houchardf73629d2017-04-05 22:33:04 +02001733 argv++;
1734 argc--;
1735 }
William Lallemande7361152018-10-26 14:47:36 +02001736 else if (*flag == 'S') {
1737 struct wordlist *c;
1738
William Lallemanda6b32492020-06-04 23:49:20 +02001739 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001740 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1741 usage(progname);
1742 }
1743 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1744 ha_alert("Cannot allocate memory\n");
1745 exit(EXIT_FAILURE);
1746 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001747 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001748
1749 argv++;
1750 argc--;
1751 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1753 /* list of pids to finish ('f') or terminate ('t') */
1754
1755 if (flag[1] == 'f')
1756 oldpids_sig = SIGUSR1; /* finish then exit */
1757 else
1758 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001759 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001760 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001761 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1762 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001763 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001764 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001765 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001766 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001767 errno = 0;
1768 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1769 if (errno) {
1770 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1771 flag,
1772 *argv, strerror(errno));
1773 exit(1);
1774 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001775 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001776 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001777 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1778 flag, endptr);
1779 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001780 }
Chris Lane236062f2018-02-05 23:15:44 +00001781 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001782 if (oldpids[nb_oldpids] <= 0)
1783 usage(progname);
1784 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001785 }
1786 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001787 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1788 /* now that's a cfgfile list */
1789 argv++; argc--;
1790 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001791 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001792 ha_alert("Cannot load configuration file/directory %s : %s\n",
1793 *argv,
1794 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001795 exit(1);
1796 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001797 argv++; argc--;
1798 }
1799 break;
1800 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001801 else { /* >=2 args */
1802 argv++; argc--;
1803 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001804 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001805
1806 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001807 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001808 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001809 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001810 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001811 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001812 free(localpeer);
1813 if ((localpeer = strdup(*argv)) == NULL) {
1814 ha_alert("Cannot allocate memory for local peer.\n");
1815 exit(EXIT_FAILURE);
1816 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001817 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001818 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001819 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001820 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001821 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001822 ha_alert("Cannot load configuration file/directory %s : %s\n",
1823 *argv,
1824 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001825 exit(1);
1826 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001827 break;
Willy Tarreau392524d2022-02-17 18:10:36 +01001828 case 'p' :
1829 free(global.pidfile);
1830 if ((global.pidfile = strdup(*argv)) == NULL) {
1831 ha_alert("Cannot allocate memory for pidfile.\n");
1832 exit(EXIT_FAILURE);
1833 }
1834 break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001835 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001836 }
1837 }
1838 }
1839 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001840 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001841 argv++; argc--;
1842 }
Willy Tarreau392524d2022-02-17 18:10:36 +01001843 free(err_msg);
1844}
1845
Willy Tarreau76871a42022-03-08 16:01:40 +01001846/* call the various keyword dump functions based on the comma-delimited list of
1847 * classes in kwd_dump.
1848 */
1849static void dump_registered_keywords(void)
1850{
1851 char *end;
1852 int all __maybe_unused = 0;
1853
1854 for (; kwd_dump && *kwd_dump; kwd_dump = end) {
1855 end = strchr(kwd_dump, ',');
1856 if (end)
1857 *(end++) = 0;
1858
1859 if (strcmp(kwd_dump, "help") == 0) {
1860 printf("# List of supported keyword classes:\n");
1861 printf("all: list all keywords\n");
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001862 printf("acl: ACL keywords\n");
Willy Tarreauca1acd62022-03-29 15:02:44 +02001863 printf("cfg: configuration keywords\n");
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001864 printf("cli: CLI keywords\n");
Willy Tarreau29d799d2022-03-29 16:59:49 +02001865 printf("cnv: sample converter keywords\n");
Willy Tarreau3b65e142022-03-29 15:03:09 +02001866 printf("flt: filter names\n");
Willy Tarreauf78813f2022-03-29 16:51:29 +02001867 printf("smp: sample fetch functions\n");
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001868 printf("svc: service names\n");
Willy Tarreau76871a42022-03-08 16:01:40 +01001869 continue;
1870 }
1871 else if (strcmp(kwd_dump, "all") == 0) {
1872 all = 1;
1873 }
Willy Tarreauca1acd62022-03-29 15:02:44 +02001874
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001875 if (all || strcmp(kwd_dump, "acl") == 0) {
1876 printf("# List of registered ACL keywords:\n");
1877 acl_dump_kwd();
1878 }
1879
Willy Tarreauca1acd62022-03-29 15:02:44 +02001880 if (all || strcmp(kwd_dump, "cfg") == 0) {
1881 printf("# List of registered configuration keywords:\n");
1882 cfg_dump_registered_keywords();
1883 }
Willy Tarreau3b65e142022-03-29 15:03:09 +02001884
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001885 if (all || strcmp(kwd_dump, "cli") == 0) {
1886 printf("# List of registered CLI keywords:\n");
1887 cli_list_keywords();
1888 }
1889
Willy Tarreau29d799d2022-03-29 16:59:49 +02001890 if (all || strcmp(kwd_dump, "cnv") == 0) {
1891 printf("# List of registered sample converter functions:\n");
1892 smp_dump_conv_kw();
1893 }
1894
Willy Tarreau3b65e142022-03-29 15:03:09 +02001895 if (all || strcmp(kwd_dump, "flt") == 0) {
1896 printf("# List of registered filter names:\n");
1897 flt_dump_kws(NULL);
1898 }
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001899
Willy Tarreauf78813f2022-03-29 16:51:29 +02001900 if (all || strcmp(kwd_dump, "smp") == 0) {
1901 printf("# List of registered sample fetch functions:\n");
1902 smp_dump_fetch_kw();
1903 }
1904
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001905 if (all || strcmp(kwd_dump, "svc") == 0) {
1906 printf("# List of registered service names:\n");
1907 list_services(NULL);
1908 }
Willy Tarreau76871a42022-03-08 16:01:40 +01001909 }
1910}
1911
Amaury Denoyelle28ea31c2022-11-14 16:18:46 +01001912/* Generate a random cluster-secret in case the setting is not provided in the
1913 * configuration. This allows to use features which rely on it albeit with some
1914 * limitations.
1915 */
1916static void generate_random_cluster_secret()
1917{
1918 /* used as a default random cluster-secret if none defined. */
1919 uint64_t rand = ha_random64();
1920
1921 /* The caller must not overwrite an already defined secret. */
1922 BUG_ON(global.cluster_secret);
1923
1924 global.cluster_secret = malloc(8);
1925 if (!global.cluster_secret)
1926 return;
1927
1928 memcpy(global.cluster_secret, &rand, sizeof(rand));
1929 global.cluster_secret[7] = '\0';
1930}
1931
Willy Tarreau392524d2022-02-17 18:10:36 +01001932/*
1933 * This function initializes all the necessary variables. It only returns
1934 * if everything is OK. If something fails, it exits.
1935 */
1936static void init(int argc, char **argv)
1937{
1938 char *progname = global.log_tag.area;
1939 int err_code = 0;
1940 struct wordlist *wl;
1941 struct proxy *px;
1942 struct post_check_fct *pcf;
William Lallemandb53eb872022-04-21 18:02:53 +02001943 struct pre_check_fct *prcf;
Willy Tarreau392524d2022-02-17 18:10:36 +01001944 int ideal_maxconn;
1945
William Lallemand151dbbe2022-12-02 17:17:43 +01001946#ifdef USE_OPENSSL
1947#ifdef USE_OPENSSL_WOLFSSL
1948 wolfSSL_Init();
1949 wolfSSL_Debugging_ON();
1950#endif
1951#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
William Lallemand44c80ce2022-12-02 17:06:59 +01001952 /* Initialize the error strings of OpenSSL
1953 * It only needs to be done explicitly with older versions of the SSL
1954 * library. On newer versions, errors strings are loaded during start
1955 * up. */
1956 SSL_load_error_strings();
1957#endif
William Lallemand151dbbe2022-12-02 17:17:43 +01001958#endif
William Lallemand44c80ce2022-12-02 17:06:59 +01001959
William Lallemandeba6a542022-09-26 12:54:39 +02001960 startup_logs_init();
1961
Willy Tarreau392524d2022-02-17 18:10:36 +01001962 if (!init_trash_buffers(1)) {
1963 ha_alert("failed to initialize trash buffers.\n");
1964 exit(1);
1965 }
1966
1967 if (init_acl() != 0)
1968 exit(1);
1969
1970 /* Initialise lua. */
1971 hlua_init();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001972
Christopher Faulete3a5e352017-10-24 13:53:54 +02001973 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001974 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Erwan Le Goasf30c5d72022-09-29 10:34:04 +02001975 | MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS | MODE_DUMP_KWD
1976 | MODE_DUMP_CFG | MODE_DUMP_NB_L));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001977
William Lallemand944e6192018-11-21 15:48:31 +01001978 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001979 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001980 global.mode |= MODE_MWORKER_WAIT;
1981 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001982 }
1983
William Lallemand40db4ae2022-12-07 15:03:55 +01001984 /* set the atexit functions when not doing configuration check */
1985 if (!(global.mode & (MODE_CHECK | MODE_CHECK_CONDITION))
1986 && (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
1987
1988 if (global.mode & MODE_MWORKER) {
1989 atexit_flag = 1;
1990 atexit(reexec_on_failure);
1991 } else if (global.mode & MODE_MWORKER_WAIT) {
1992 atexit_flag = 1;
1993 atexit(exit_on_waitmode_failure);
1994 }
William Lallemandcb11fd22017-06-01 17:38:52 +02001995 }
1996
Willy Tarreau576132e2011-09-10 19:26:56 +02001997 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001998 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001999 exit(1);
2000 }
2001
Amaury Denoyelle11124302021-06-04 18:22:08 +02002002 usermsgs_clr("config");
2003
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002004 if (global.mode & MODE_CHECK_CONDITION) {
2005 int result;
2006
2007 uint32_t err;
2008 const char *errptr;
2009 char *errmsg = NULL;
2010
2011 char *args[MAX_LINE_ARGS+1];
2012 int arg = sizeof(args) / sizeof(*args);
William Lallemand89e236f2022-05-06 17:22:36 +02002013 size_t outlen;
Willy Tarreauc8194c32021-07-16 16:38:58 +02002014 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002015
William Lallemand89e236f2022-05-06 17:22:36 +02002016 if (!check_condition)
2017 usage(progname);
2018
2019 outlen = strlen(check_condition) + 1;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002020 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02002021 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002022 &errptr);
2023
2024 if (err & PARSE_ERR_QUOTE) {
2025 ha_alert("Syntax Error in condition: Unmatched quote.\n");
2026 exit(2);
2027 }
2028
2029 if (err & PARSE_ERR_HEX) {
2030 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
2031 exit(2);
2032 }
2033
2034 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
2035 ha_alert("Error in condition: Line too long.\n");
2036 exit(2);
2037 }
2038
Willy Tarreauc8194c32021-07-16 16:38:58 +02002039 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002040 ha_alert("Error in condition: Too many words.\n");
2041 exit(2);
2042 }
2043
2044 if (err) {
2045 ha_alert("Unhandled error in condition, please report this to the developers.\n");
2046 exit(2);
2047 }
2048
Willy Tarreauc8194c32021-07-16 16:38:58 +02002049 /* remerge all words into a single expression */
2050 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
2051 ;
2052
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002053 result = cfg_eval_condition(args, &errmsg, &errptr);
2054
2055 if (result < 0) {
2056 if (errmsg)
2057 ha_alert("Failed to evaluate condition: %s\n", errmsg);
2058
2059 exit(2);
2060 }
2061
2062 exit(result ? 0 : 1);
2063 }
2064
William Lallemand944e6192018-11-21 15:48:31 +01002065 /* in wait mode, we don't try to read the configuration files */
2066 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01002067 char *env_cfgfiles = NULL;
2068 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01002069
William Lallemand944e6192018-11-21 15:48:31 +01002070 /* handle cfgfiles that are actually directories */
2071 cfgfiles_expand_directories();
2072
2073 if (LIST_ISEMPTY(&cfg_cfgfiles))
2074 usage(progname);
2075
2076
2077 list_for_each_entry(wl, &cfg_cfgfiles, list) {
2078 int ret;
2079
Christopher Faulet4e366822021-01-12 18:57:38 +01002080 if (env_err == 0) {
2081 if (!memprintf(&env_cfgfiles, "%s%s%s",
2082 (env_cfgfiles ? env_cfgfiles : ""),
2083 (env_cfgfiles ? ";" : ""), wl->s))
2084 env_err = 1;
2085 }
William Lallemand7b302d82019-05-20 11:15:37 +02002086
William Lallemand944e6192018-11-21 15:48:31 +01002087 ret = readcfgfile(wl->s);
2088 if (ret == -1) {
2089 ha_alert("Could not open configuration file %s : %s\n",
2090 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01002091 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002092 exit(1);
2093 }
2094 if (ret & (ERR_ABORT|ERR_FATAL))
2095 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
2096 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01002097 if (err_code & ERR_ABORT) {
2098 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002099 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01002100 }
Willy Tarreauc4382422009-12-06 13:10:44 +01002101 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02002102
William Lallemand944e6192018-11-21 15:48:31 +01002103 /* do not try to resolve arguments nor to spot inconsistencies when
2104 * the configuration contains fatal errors caused by files not found
2105 * or failed memory allocations.
2106 */
2107 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2108 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01002109 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002110 exit(1);
2111 }
Christopher Faulet4e366822021-01-12 18:57:38 +01002112 if (env_err) {
2113 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
2114 exit(1);
2115 }
2116 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
2117 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02002118
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02002119 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002120 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01002121 struct mworker_proc *tmproc;
2122
William Lallemand482f9a92019-04-12 16:15:00 +02002123 setenv("HAPROXY_MWORKER", "1", 1);
2124
William Lallemand16dd1b32018-11-19 18:46:18 +01002125 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
2126
William Lallemand56be0e02022-01-28 21:11:41 +01002127 tmproc = mworker_proc_new();
William Lallemand16dd1b32018-11-19 18:46:18 +01002128 if (!tmproc) {
2129 ha_alert("Cannot allocate process structures.\n");
2130 exit(EXIT_FAILURE);
2131 }
William Lallemand8f7069a2019-04-12 16:09:23 +02002132 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01002133 tmproc->pid = pid;
2134 tmproc->timestamp = start_date.tv_sec;
William Lallemand16dd1b32018-11-19 18:46:18 +01002135 proc_self = tmproc;
2136
Willy Tarreau2b718102021-04-21 07:32:39 +02002137 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01002138 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002139
William Lallemand56be0e02022-01-28 21:11:41 +01002140 tmproc = mworker_proc_new();
Willy Tarreau6185a032021-06-15 08:02:06 +02002141 if (!tmproc) {
2142 ha_alert("Cannot allocate process structures.\n");
2143 exit(EXIT_FAILURE);
2144 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002145 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
William Lallemandce83b4a2018-10-26 14:47:30 +02002146
Willy Tarreau6185a032021-06-15 08:02:06 +02002147 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
2148 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02002149 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002150
2151 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01002152 }
Willy Tarreau53bfac82022-07-22 17:35:49 +02002153
2154 if (global.mode & MODE_MWORKER_WAIT) {
2155 /* in exec mode, there's always exactly one thread. Failure to
2156 * set these ones now will result in nbthread being detected
2157 * automatically.
2158 */
2159 global.nbtgroups = 1;
2160 global.nbthread = 1;
2161 }
2162
William Lallemand944e6192018-11-21 15:48:31 +01002163 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
2164 struct wordlist *it, *c;
2165
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02002166 /* get the info of the children in the env */
2167 if (mworker_env_to_proc_list() < 0) {
2168 exit(EXIT_FAILURE);
2169 }
William Lallemande7361152018-10-26 14:47:36 +02002170
William Lallemand550db6d2018-11-06 17:37:12 +01002171 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemandec059c22022-09-22 17:26:23 +02002172 char *path = NULL;
William Lallemande7361152018-10-26 14:47:36 +02002173
William Lallemand550db6d2018-11-06 17:37:12 +01002174 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02002175 ha_alert("Can't create the master's CLI.\n");
2176 exit(EXIT_FAILURE);
2177 }
William Lallemande7361152018-10-26 14:47:36 +02002178
William Lallemand550db6d2018-11-06 17:37:12 +01002179 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
2180
William Lallemand21623b52022-09-24 15:51:27 +02002181 if (mworker_cli_proxy_new_listener(c->s) == NULL) {
William Lallemand550db6d2018-11-06 17:37:12 +01002182 ha_alert("Can't create the master's CLI.\n");
2183 exit(EXIT_FAILURE);
2184 }
Willy Tarreau2b718102021-04-21 07:32:39 +02002185 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01002186 free(c->s);
2187 free(c);
2188 }
William Lallemande57b7022022-12-07 14:25:41 +01002189 /* Creates the mcli_reload listener, which is the listener used
2190 * to retrieve the master CLI session which asked for the reload.
2191 *
2192 * ipc_fd[1] will be used as a listener, and ipc_fd[0]
2193 * will be used to send the FD of the session.
2194 *
2195 * Both FDs will be kept in the master. The sockets are
2196 * created only if they weren't inherited.
2197 */
2198 if ((proc_self->ipc_fd[1] == -1) &&
2199 socketpair(AF_UNIX, SOCK_STREAM, 0, proc_self->ipc_fd) < 0) {
2200 ha_alert("cannot create the mcli_reload socketpair.\n");
2201 exit(EXIT_FAILURE);
2202 }
2203
William Lallemandec059c22022-09-22 17:26:23 +02002204 /* Create the mcli_reload listener from the proc_self struct */
2205 memprintf(&path, "sockpair@%d", proc_self->ipc_fd[1]);
William Lallemand56f73b22022-09-24 15:56:25 +02002206 mcli_reload_bind_conf = mworker_cli_proxy_new_listener(path);
2207 if (mcli_reload_bind_conf == NULL) {
William Lallemandec059c22022-09-22 17:26:23 +02002208 ha_alert("Cannot create the mcli_reload listener.\n");
2209 exit(EXIT_FAILURE);
2210 }
2211 ha_free(&path);
William Lallemand550db6d2018-11-06 17:37:12 +01002212 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002213 }
2214
Eric Salama5ba83352021-03-16 15:11:17 +01002215 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
2216 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
2217 }
2218
Christopher Faulet27c8d202021-10-13 09:50:53 +02002219 /* destroy unreferenced defaults proxies */
2220 proxy_destroy_all_unref_defaults();
2221
William Lallemandb53eb872022-04-21 18:02:53 +02002222 list_for_each_entry(prcf, &pre_check_list, list)
2223 err_code |= prcf->fct();
Willy Tarreaue90904d2021-02-12 14:08:31 +01002224
William Lallemand8b9a2df2022-05-04 14:29:46 +02002225 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2226 ha_alert("Fatal errors found in configuration.\n");
2227 exit(1);
2228 }
2229
Willy Tarreau57c3e752022-12-08 08:13:20 +01002230 /* Note: global.nbthread will be initialized as part of this call */
Willy Tarreaubb925012009-07-23 13:36:36 +02002231 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02002232 for (px = proxies_list; px; px = px->next) {
2233 struct server *srv;
2234 struct post_proxy_check_fct *ppcf;
2235 struct post_server_check_fct *pscf;
2236
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002237 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002238 continue;
2239
Christopher Fauletc1692962019-08-12 09:51:07 +02002240 list_for_each_entry(pscf, &post_server_check_list, list) {
2241 for (srv = px->srv; srv; srv = srv->next)
2242 err_code |= pscf->fct(srv);
2243 }
2244 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2245 err_code |= ppcf->fct(px);
2246 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002247 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002248 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002249 exit(1);
2250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002251
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002252 err_code |= pattern_finalize_config();
2253 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2254 ha_alert("Failed to finalize pattern config.\n");
2255 exit(1);
2256 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002257
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002258 if (global.rlimit_memmax_all)
2259 global.rlimit_memmax = global.rlimit_memmax_all;
2260
Willy Tarreaue5733232019-05-22 19:24:06 +02002261#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002262 err_code |= netns_init();
2263 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002264 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002265 exit(1);
2266 }
2267#endif
2268
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002269 /* Apply server states */
2270 apply_server_state();
2271
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002272 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002273 srv_compute_all_admin_states(px);
2274
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002275 /* Apply servers' configured address */
2276 err_code |= srv_init_addr();
2277 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002278 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002279 exit(1);
2280 }
2281
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002282 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2283 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2284 exit(1);
2285 }
2286
Willy Tarreau654726d2021-12-28 15:43:11 +01002287#if defined(HA_HAVE_DUMP_LIBS)
2288 if (global.mode & MODE_DUMP_LIBS) {
2289 qfprintf(stdout, "List of loaded object files:\n");
2290 chunk_reset(&trash);
2291 if (dump_libs(&trash, 0))
2292 printf("%s", trash.area);
2293 }
2294#endif
2295
Willy Tarreau76871a42022-03-08 16:01:40 +01002296 if (global.mode & MODE_DUMP_KWD)
2297 dump_registered_keywords();
2298
Willy Tarreaubaaee002006-06-26 02:48:02 +02002299 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002300 struct peers *pr;
2301 struct proxy *px;
2302
Willy Tarreaubebd2122020-04-15 16:06:11 +02002303 if (warned & WARN_ANY)
2304 qfprintf(stdout, "Warnings were found.\n");
2305
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002306 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002307 if (pr->peers_fe)
2308 break;
2309
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002310 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002311 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002312 break;
2313
Emeric Brunbc5c8212021-08-13 09:32:50 +02002314 if (!px) {
2315 /* We may only have log-forward section */
2316 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002317 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002318 break;
2319 }
2320
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002321 if (pr || px) {
2322 /* At least one peer or one listener has been found */
2323 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002324 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002325 }
2326 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2327 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002329
Erwan Le Goasb0c05012022-09-14 17:51:55 +02002330 if (global.mode & MODE_DUMP_CFG)
2331 deinit_and_exit(0);
2332
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002333 if (global.mode & MODE_DIAG) {
2334 cfg_run_diagnostics();
2335 }
2336
Remi Tricot-Le Breton51944462022-05-16 16:24:31 +02002337#ifdef USE_OPENSSL
William Lallemand3b8bafd2022-07-19 18:13:29 +02002338
Remi Tricot-Le Breton51944462022-05-16 16:24:31 +02002339 /* Initialize SSL random generator. Must be called before chroot for
2340 * access to /dev/urandom, and before ha_random_boot() which may use
2341 * RAND_bytes().
2342 */
2343 if (!ssl_initialize_random()) {
2344 ha_alert("OpenSSL random data generator initialization failed.\n");
2345 exit(EXIT_FAILURE);
2346 }
2347#endif
2348 ha_random_boot(argv); // the argv pointer brings some kernel-fed entropy
2349
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002350 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002351 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002352
Willy Tarreaue6945732016-12-21 19:57:00 +01002353 list_for_each_entry(pcf, &post_check_list, list) {
2354 err_code |= pcf->fct();
2355 if (err_code & (ERR_ABORT|ERR_FATAL))
2356 exit(1);
2357 }
2358
William Lallemand0a012aa2022-06-21 11:11:50 +02002359 /* set the default maxconn in the master, but let it be rewritable with -n */
2360 if (global.mode & MODE_MWORKER_WAIT)
2361 global.maxconn = DEFAULT_MAXCONN;
2362
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363 if (cfg_maxconn > 0)
2364 global.maxconn = cfg_maxconn;
2365
Willy Tarreau4975d142021-03-13 11:00:33 +01002366 if (global.cli_fe)
2367 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002368
2369 if (cfg_peers) {
2370 /* peers also need to bypass global maxconn */
2371 struct peers *p = cfg_peers;
2372
2373 for (p = cfg_peers; p; p = p->next)
2374 if (p->peers_fe)
2375 global.maxsock += p->peers_fe->maxconn;
2376 }
2377
Willy Tarreaud0256482015-01-15 21:45:22 +01002378 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002379 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2380 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2381 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2382 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002383 *
2384 * If memmax is set, then it depends on which values are set. If
2385 * maxsslconn is set, we use memmax to determine how many cleartext
2386 * connections may be added, and set maxconn to the sum of the two.
2387 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2388 * the remaining amount of memory between memmax and the cleartext
2389 * connections. If neither are set, then it is considered that all
2390 * connections are SSL-capable, and maxconn is computed based on this,
2391 * then maxsslconn accordingly. We need to know if SSL is used on the
2392 * frontends, backends, or both, because when it's used on both sides,
2393 * we need twice the value for maxsslconn, but we only count the
2394 * handshake once since it is not performed on the two sides at the
2395 * same time (frontend-side is terminated before backend-side begins).
2396 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002397 * ssl_handshake_cost during its initialization. In any case, if
2398 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2399 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002400 */
Willy Tarreauac350932019-03-01 15:43:14 +01002401 ideal_maxconn = compute_ideal_maxconn();
2402
Willy Tarreaud0256482015-01-15 21:45:22 +01002403 if (!global.rlimit_memmax) {
2404 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002405 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002406 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2407 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2408 }
2409 }
2410#ifdef USE_OPENSSL
2411 else if (!global.maxconn && !global.maxsslconn &&
2412 (global.ssl_used_frontend || global.ssl_used_backend)) {
2413 /* memmax is set, compute everything automatically. Here we want
2414 * to ensure that all SSL connections will be served. We take
2415 * care of the number of sides where SSL is used, and consider
2416 * the worst case : SSL used on both sides and doing a handshake
2417 * simultaneously. Note that we can't have more than maxconn
2418 * handshakes at a time by definition, so for the worst case of
2419 * two SSL conns per connection, we count a single handshake.
2420 */
2421 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2422 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002423 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002424
Willy Tarreau2cb3be72022-05-24 07:43:57 +02002425 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002426 mem -= global.maxzlibmem;
2427 mem = mem * MEM_USABLE_RATIO;
2428
Willy Tarreau304e17e2020-03-10 17:54:54 +01002429 /* Principle: we test once to set maxconn according to the free
2430 * memory. If it results in values the system rejects, we try a
2431 * second time by respecting rlim_fd_max. If it fails again, we
2432 * go back to the initial value and will let the final code
2433 * dealing with rlimit report the error. That's up to 3 attempts.
2434 */
2435 do {
2436 global.maxconn = mem /
2437 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2438 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2439 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002440
Willy Tarreau304e17e2020-03-10 17:54:54 +01002441 if (retried == 1)
2442 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2443 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002444#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002445 if (global.maxconn > SYSTEM_MAXCONN)
2446 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002447#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002448 global.maxsslconn = sides * global.maxconn;
2449
2450 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2451 break;
2452 } while (retried++ < 2);
2453
Willy Tarreaud0256482015-01-15 21:45:22 +01002454 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2455 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2456 global.maxconn, global.maxsslconn);
2457 }
2458 else if (!global.maxsslconn &&
2459 (global.ssl_used_frontend || global.ssl_used_backend)) {
2460 /* memmax and maxconn are known, compute maxsslconn automatically.
2461 * maxsslconn being forced, we don't know how many of it will be
2462 * on each side if both sides are being used. The worst case is
2463 * when all connections use only one SSL instance because
2464 * handshakes may be on two sides at the same time.
2465 */
2466 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2467 int64_t mem = global.rlimit_memmax * 1048576ULL;
2468 int64_t sslmem;
2469
Willy Tarreau8e5b9582022-05-26 08:55:05 +02002470 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002471 mem -= global.maxzlibmem;
2472 mem = mem * MEM_USABLE_RATIO;
2473
Willy Tarreau87b09662015-04-03 00:22:06 +02002474 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002475 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2476 global.maxsslconn = round_2dig(global.maxsslconn);
2477
2478 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002479 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2480 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2481 "without SSL is %d, but %d was found and SSL is in use.\n",
2482 global.rlimit_memmax,
2483 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2484 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002485 exit(1);
2486 }
2487
2488 if (global.maxsslconn > sides * global.maxconn)
2489 global.maxsslconn = sides * global.maxconn;
2490
2491 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2492 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2493 }
2494#endif
2495 else if (!global.maxconn) {
2496 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2497 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2498 int64_t mem = global.rlimit_memmax * 1048576ULL;
2499 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002500 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002501
2502 if (global.ssl_used_frontend || global.ssl_used_backend)
Willy Tarreau8e5b9582022-05-26 08:55:05 +02002503 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002504
2505 mem -= global.maxzlibmem;
2506 mem = mem * MEM_USABLE_RATIO;
2507
2508 clearmem = mem;
2509 if (sides)
2510 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2511
Willy Tarreau304e17e2020-03-10 17:54:54 +01002512 /* Principle: we test once to set maxconn according to the free
2513 * memory. If it results in values the system rejects, we try a
2514 * second time by respecting rlim_fd_max. If it fails again, we
2515 * go back to the initial value and will let the final code
2516 * dealing with rlimit report the error. That's up to 3 attempts.
2517 */
2518 do {
2519 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2520 if (retried == 1)
2521 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2522 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002523#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002524 if (global.maxconn > SYSTEM_MAXCONN)
2525 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002526#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002527
Willy Tarreau304e17e2020-03-10 17:54:54 +01002528 if (clearmem <= 0 || !global.maxconn) {
2529 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2530 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2531 "is %d, but %d was found.\n",
2532 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002533 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002534 global.maxsslconn);
2535 exit(1);
2536 }
2537
2538 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2539 break;
2540 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002541
2542 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2543 if (sides && global.maxsslconn > sides * global.maxconn) {
2544 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2545 "to be limited to %d. Better reduce global.maxsslconn to get more "
2546 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2547 }
2548 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2549 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002550 }
2551
Willy Tarreaua409f302020-03-10 17:08:53 +01002552 global.maxsock = compute_ideal_maxsock(global.maxconn);
2553 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002554 if (!global.maxpipes)
2555 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556
Olivier Houchard88698d92019-04-16 19:07:22 +02002557 /* update connection pool thresholds */
2558 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2559 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2560
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002561 proxy_adjust_all_maxconn();
2562
Willy Tarreau1db37712007-06-03 17:16:49 +02002563 if (global.tune.maxpollevents <= 0)
2564 global.tune.maxpollevents = MAX_POLL_EVENTS;
2565
Willy Tarreau060a7612021-03-10 11:06:26 +01002566 if (global.tune.runqueue_depth <= 0) {
2567 /* tests on various thread counts from 1 to 64 have shown an
2568 * optimal queue depth following roughly 1/sqrt(threads).
2569 */
2570 int s = my_flsl(global.nbthread);
2571 s += (global.nbthread / s); // roughly twice the sqrt.
2572 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2573 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002574
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002575 if (global.tune.recv_enough == 0)
2576 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2577
Willy Tarreau27a674e2009-08-17 07:23:33 +02002578 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2579 global.tune.maxrewrite = global.tune.bufsize / 2;
2580
Amaury Denoyelle11124302021-06-04 18:22:08 +02002581 usermsgs_clr(NULL);
2582
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2584 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002585 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002586 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2587 }
2588
William Lallemand095ba4c2017-06-01 17:38:50 +02002589 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002590 /* command line daemon mode inhibits foreground and debug modes mode */
2591 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002592 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002594
2595 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596
William Lallemand095ba4c2017-06-01 17:38:50 +02002597 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002598 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002599 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002600 }
2601
Christopher Faulet3ef26392017-08-29 16:46:57 +02002602 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002603 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002604 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002605 exit(1);
2606 }
2607
Christopher Faulet96d44832017-11-14 22:02:30 +01002608 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002609 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002610 exit(1);
2611 }
2612
Amaury Denoyelle28ea31c2022-11-14 16:18:46 +01002613 if (!global.cluster_secret)
2614 generate_random_cluster_secret();
2615
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002616 /*
2617 * Note: we could register external pollers here.
2618 * Built-in pollers have been registered before main().
2619 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002620
Willy Tarreau43b78992009-01-25 15:42:27 +01002621 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002622 disable_poller("kqueue");
2623
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002624 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2625 disable_poller("evports");
2626
Willy Tarreau43b78992009-01-25 15:42:27 +01002627 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002628 disable_poller("epoll");
2629
Willy Tarreau43b78992009-01-25 15:42:27 +01002630 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002631 disable_poller("poll");
2632
Willy Tarreau43b78992009-01-25 15:42:27 +01002633 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002634 disable_poller("select");
2635
2636 /* Note: we could disable any poller by name here */
2637
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002638 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002639 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002640 fprintf(stderr, "\n");
2641 list_filters(stderr);
2642 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002643
Willy Tarreau4f60f162007-04-08 16:39:58 +02002644 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002645 ha_alert("No polling mechanism available.\n"
Willy Tarreaue5715bf2022-07-09 23:38:46 +02002646 " This may happen when using thread-groups with old pollers (poll/select), or\n"
2647 " it is possible that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
Christopher Faulet767a84b2017-11-24 16:50:31 +01002648 " is too low on this platform to support maxconn and the number of listeners\n"
2649 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2650 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2651 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2652 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2653 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2654 " check build settings using 'haproxy -vv'.\n\n",
2655 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002656 exit(1);
2657 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002658 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2659 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002660 }
2661
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002662 if (!global.node)
2663 global.node = strdup(hostname);
2664
Willy Tarreau02b092f2020-10-07 18:36:54 +02002665 /* stop disabled proxies */
2666 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002667 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002668 stop_proxy(px);
2669 }
2670
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002671 if (!hlua_post_init())
2672 exit(1);
Willy Tarreau284cfc62022-12-19 08:15:57 +01002673
2674 /* Set the per-thread pool cache size to the default value if not set.
2675 * This is the right place to decide to automatically adjust it (e.g.
2676 * check L2 cache size, thread counts or take into account certain
2677 * expensive pools).
2678 */
2679 if (!global.tune.pool_cache_size)
2680 global.tune.pool_cache_size = CONFIG_HAP_POOL_CACHE_SIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681}
2682
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002683void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002685 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002686 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002687 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002688 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002689 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002690 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002691 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002692 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002693 struct per_thread_init_fct *tif, *tifb;
2694 struct per_thread_deinit_fct *tdf, *tdfb;
2695 struct per_thread_alloc_fct *taf, *tafb;
2696 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002697 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002698 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002699 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreau65009eb2022-04-27 18:02:54 +02002700 struct pre_check_fct *prcf, *prcfb;
Willy Tarreau226866e2022-04-27 18:07:24 +02002701 struct cfg_postparser *pprs, *pprsb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002702 int cur_fd;
2703
Willy Tarreaue98d3852022-11-15 09:34:07 +01002704 /* the user may want to skip this phase */
2705 if (global.tune.options & GTUNE_QUICK_EXIT)
2706 return;
2707
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002708 /* At this point the listeners state is weird:
2709 * - most listeners are still bound and referenced in their protocol
2710 * - some might be zombies that are not in their proto anymore, but
2711 * still appear in their proxy's listeners with a valid FD.
2712 * - some might be stopped and still appear in their proxy as FD #-1
2713 * - among all of them, some might be inherited hence shared and we're
2714 * not allowed to pause them or whatever, we must just close them.
2715 * - finally some are not listeners (pipes, logs, stdout, etc) and
2716 * must be left intact.
2717 *
2718 * The safe way to proceed is to unbind (and close) whatever is not yet
2719 * unbound so that no more receiver/listener remains alive. Then close
2720 * remaining listener FDs, which correspond to zombie listeners (those
2721 * belonging to disabled proxies that were in another process).
2722 * objt_listener() would be cleaner here but not converted yet.
2723 */
2724 protocol_unbind_all();
2725
2726 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002727 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002728 continue;
2729
Willy Tarreaua74cb382020-10-15 21:29:49 +02002730 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002731 struct listener *l = fdtab[cur_fd].owner;
2732
2733 BUG_ON(l->state != LI_INIT);
2734 unbind_listener(l);
2735 }
2736 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002737
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002738 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002739 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002740 /* build a list of unique uri_auths */
2741 if (!ua)
2742 ua = p->uri_auth;
2743 else {
2744 /* check if p->uri_auth is unique */
2745 for (uap = ua; uap; uap=uap->next)
2746 if (uap == p->uri_auth)
2747 break;
2748
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002749 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002750 /* add it, if it is */
2751 p->uri_auth->next = ua;
2752 ua = p->uri_auth;
2753 }
William Lallemand0f99e342011-10-12 17:50:54 +02002754 }
2755
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002756 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002758 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002760
Christopher Faulet27c8d202021-10-13 09:50:53 +02002761 /* destroy all referenced defaults proxies */
2762 proxy_destroy_all_unref_defaults();
2763
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002764 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002765 struct stat_scope *scope, *scopep;
2766
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002767 uap = ua;
2768 ua = ua->next;
2769
Willy Tarreaua534fea2008-08-03 12:19:50 +02002770 free(uap->uri_prefix);
2771 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002772 free(uap->node);
2773 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002774
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002775 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002776 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002777
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002778 scope = uap->scope;
2779 while (scope) {
2780 scopep = scope;
2781 scope = scope->next;
2782
2783 free(scopep->px_id);
2784 free(scopep);
2785 }
2786
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002787 free(uap);
2788 }
2789
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002790 userlist_free(userlist);
2791
David Carlier834cb2e2015-09-25 12:02:25 +01002792 cfg_unregister_sections();
2793
Christopher Faulet0132d062017-07-26 15:33:35 +02002794 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002795
Willy Tarreau05554e62016-12-21 20:46:26 +01002796 list_for_each_entry(pdf, &post_deinit_list, list)
2797 pdf->fct();
2798
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002799 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002800 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002801 ha_free(&global.chroot);
Frédéric Lécaille372508c2022-05-06 08:53:16 +02002802 ha_free(&global.cluster_secret);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002803 ha_free(&global.pidfile);
2804 ha_free(&global.node);
2805 ha_free(&global.desc);
2806 ha_free(&oldpids);
2807 ha_free(&old_argv);
2808 ha_free(&localpeer);
2809 ha_free(&global.server_state_base);
2810 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002811 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002812 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002813
William Lallemand0f99e342011-10-12 17:50:54 +02002814 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002815 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002816 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002817 free(log);
2818 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002819 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002820 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002821 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002822 free(wl);
2823 }
2824
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002825 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2826 if (bol->must_free)
2827 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002828 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002829 free(bol);
2830 }
2831
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002832 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002833 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002834 free(pxdf);
2835 }
2836
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002837 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002838 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002839 free(pdf);
2840 }
2841
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002842 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002843 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002844 free(srvdf);
2845 }
2846
Tim Duesterhusfc854942020-09-10 19:46:42 +02002847 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002848 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002849 free(pcf);
2850 }
2851
Tim Duesterhus34bef072020-07-04 11:49:50 +02002852 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002853 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002854 free(pscf);
2855 }
2856
Tim Duesterhus53508d62020-09-10 19:46:40 +02002857 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002858 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002859 free(ppcf);
2860 }
2861
Willy Tarreau65009eb2022-04-27 18:02:54 +02002862 list_for_each_entry_safe(prcf, prcfb, &pre_check_list, list) {
2863 LIST_DELETE(&prcf->list);
2864 free(prcf);
2865 }
2866
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002867 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002868 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002869 free(tif);
2870 }
2871
2872 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002873 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002874 free(tdf);
2875 }
2876
2877 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002878 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002879 free(taf);
2880 }
2881
2882 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002883 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002884 free(tff);
2885 }
2886
Willy Tarreau226866e2022-04-27 18:07:24 +02002887 list_for_each_entry_safe(pprs, pprsb, &postparsers, list) {
2888 LIST_DELETE(&pprs->list);
2889 free(pprs);
2890 }
2891
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002892 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002893 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002894 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002895} /* end deinit() */
2896
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002897__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002898{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002899 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002900 deinit();
2901 exit(status);
2902}
William Lallemand72160322018-11-06 17:37:16 +01002903
Willy Tarreau918ff602011-07-25 16:33:49 +02002904/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002905void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002906{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002907 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002908
Willy Tarreau55542642021-10-08 09:33:24 +02002909 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002910 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002911 wake_expired_tasks();
2912
William Lallemand1aab50b2018-06-07 09:46:01 +02002913 /* check if we caught some signals and process them in the
2914 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002915 if (signal_queue_len && tid == 0) {
2916 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002917 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002918 }
2919
2920 /* Process a few tasks */
2921 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002922
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002923 /* also stop if we failed to cleanly stop all tasks */
2924 if (killed > 1)
2925 break;
2926
Matthias Wirtheea152e2022-09-09 10:21:00 +02002927 /* expire immediately if events or signals are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002928 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002929 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002930 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002931 else {
Willy Tarreaue7475c82022-06-20 09:23:24 +02002932 _HA_ATOMIC_OR(&th_ctx->flags, TH_FL_SLEEPING);
Willy Tarreaudce4ad72022-06-22 15:38:38 +02002933 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_NOTIFIED);
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002934 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002935 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002936 activity[tid].wake_tasks++;
Willy Tarreaue7475c82022-06-20 09:23:24 +02002937 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_SLEEPING);
Matthias Wirtheea152e2022-09-09 10:21:00 +02002938 } else if (signal_queue_len) {
2939 /* this check is required after setting TH_FL_SLEEPING to avoid
2940 * a race with wakeup on signals using wake_threads() */
2941 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_SLEEPING);
Olivier Houchard79321b92018-07-26 17:55:11 +02002942 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002943 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002944 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002945
Willy Tarreau4f46a352020-03-23 09:27:28 +01002946 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002947 int i;
2948
2949 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002950 /* stop muxes before acknowledging stopping */
Willy Tarreau24cfc9f2022-07-04 14:07:29 +02002951 if (!(tg_ctx->stopping_threads & ti->ltid_bit)) {
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002952 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2953 wake = 1;
2954 }
2955
Willy Tarreauef422ce2022-06-28 19:29:29 +02002956 if (_HA_ATOMIC_OR_FETCH(&tg_ctx->stopping_threads, ti->ltid_bit) == ti->ltid_bit &&
2957 _HA_ATOMIC_OR_FETCH(&stopping_tgroup_mask, tg->tgid_bit) == tg->tgid_bit) {
2958 /* first one to detect it, notify all threads that stopping was just set */
2959 for (i = 0; i < global.nbthread; i++) {
2960 if (ha_thread_info[i].tg->threads_enabled &
2961 ha_thread_info[i].ltid_bit &
2962 ~_HA_ATOMIC_LOAD(&ha_thread_info[i].tg_ctx->stopping_threads))
Willy Tarreaud6455742020-05-13 14:30:25 +02002963 wake_thread(i);
Willy Tarreauef422ce2022-06-28 19:29:29 +02002964 }
Willy Tarreaud6455742020-05-13 14:30:25 +02002965 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002966 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002967
2968 /* stop when there's nothing left to do */
2969 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreauef422ce2022-06-28 19:29:29 +02002970 (_HA_ATOMIC_LOAD(&stopping_tgroup_mask) & all_tgroups_mask) == all_tgroups_mask) {
2971 /* check that all threads are aware of the stopping status */
2972 for (i = 0; i < global.nbtgroups; i++)
Willy Tarreauf34a3fa2022-07-06 10:13:05 +02002973 if ((_HA_ATOMIC_LOAD(&ha_tgroup_ctx[i].stopping_threads) & ha_tgroup_info[i].threads_enabled) !=
2974 ha_tgroup_info[i].threads_enabled)
Willy Tarreauef422ce2022-06-28 19:29:29 +02002975 break;
2976#ifdef USE_THREAD
2977 if (i == global.nbtgroups) {
2978 /* all are OK, let's wake them all and stop */
2979 for (i = 0; i < global.nbthread; i++)
2980 if (i != tid && ha_thread_info[i].tg->threads_enabled & ha_thread_info[i].ltid_bit)
2981 wake_thread(i);
2982 break;
2983 }
2984#endif
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002985 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002986 }
2987
Willy Tarreauc49ba522019-12-11 08:12:23 +01002988 /* If we have to sleep, measure how long */
2989 next = wake ? TICK_ETERNITY : next_timer_expiry();
2990
Willy Tarreau58b458d2008-06-29 22:40:23 +02002991 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002992 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002993
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002994 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002995 }
2996}
2997
Christopher Faulet1d17c102017-08-29 15:38:48 +02002998static void *run_thread_poll_loop(void *data)
2999{
Willy Tarreau082b6282019-05-22 14:42:12 +02003000 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02003001 struct per_thread_init_fct *ptif;
3002 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02003003 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02003004 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02003005 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
3006 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02003007
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003008 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02003009 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02003010 clock_set_local_source();
Willy Tarreau91e6df02019-05-03 17:21:18 +02003011
Willy Tarreau6ec902a2019-06-07 14:41:11 +02003012 /* Now, initialize one thread init at a time. This is better since
3013 * some init code is a bit tricky and may release global resources
3014 * after reallocating them locally. This will also ensure there is
3015 * no race on file descriptors allocation.
3016 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02003017#ifdef USE_THREAD
3018 pthread_mutex_lock(&init_mutex);
3019#endif
3020 /* The first thread must set the number of threads left */
3021 if (!init_left)
3022 init_left = global.nbthread;
3023 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02003024
Willy Tarreau55542642021-10-08 09:33:24 +02003025 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003026
Willy Tarreau082b6282019-05-22 14:42:12 +02003027 /* per-thread alloc calls performed here are not allowed to snoop on
3028 * other threads, so they are free to initialize at their own rhythm
3029 * as long as they act as if they were alone. None of them may rely
3030 * on resources initialized by the other ones.
3031 */
3032 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
3033 if (!ptaf->fct()) {
3034 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02003035#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08003036 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02003037#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02003038 exit(1);
3039 }
3040 }
3041
Willy Tarreau3078e9f2019-05-20 10:50:43 +02003042 /* per-thread init calls performed here are not allowed to snoop on
3043 * other threads, so they are free to initialize at their own rhythm
3044 * as long as they act as if they were alone.
3045 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02003046 list_for_each_entry(ptif, &per_thread_init_list, list) {
3047 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003048 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02003049#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08003050 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02003051#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003052 exit(1);
3053 }
3054 }
3055
Willy Tarreau71092822019-06-10 09:51:04 +02003056 /* enabling protocols will result in fd_insert() calls to be performed,
3057 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02003058 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02003059 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02003060 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02003061 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02003062
Willy Tarreau34a150c2019-06-11 09:16:41 +02003063#ifdef USE_THREAD
3064 pthread_cond_broadcast(&init_cond);
3065 pthread_mutex_unlock(&init_mutex);
3066
3067 /* now wait for other threads to finish starting */
3068 pthread_mutex_lock(&init_mutex);
3069 while (init_left)
3070 pthread_cond_wait(&init_cond, &init_mutex);
3071 pthread_mutex_unlock(&init_mutex);
3072#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02003073
Willy Tarreaua45a8b52019-12-06 16:31:45 +01003074#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
3075 /* Let's refrain from using setuid executables. This way the impact of
3076 * an eventual vulnerability in a library remains limited. It may
3077 * impact external checks but who cares about them anyway ? In the
3078 * worst case it's possible to disable the option. Obviously we do this
3079 * in workers only. We can't hard-fail on this one as it really is
3080 * implementation dependent though we're interested in feedback, hence
3081 * the warning.
3082 */
3083 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
3084 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02003085 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaua45a8b52019-12-06 16:31:45 +01003086 ha_warning("Failed to disable setuid, please report to developers with detailed "
3087 "information about your operating system. You can silence this warning "
3088 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
3089 }
3090 }
3091#endif
3092
Willy Tarreaud96f1122019-12-03 07:07:36 +01003093#if defined(RLIMIT_NPROC)
3094 /* all threads have started, it's now time to prevent any new thread
3095 * or process from starting. Obviously we do this in workers only. We
3096 * can't hard-fail on this one as it really is implementation dependent
3097 * though we're interested in feedback, hence the warning.
3098 */
3099 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
3100 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
3101 static int warn_fail;
3102
Willy Tarreau18515722021-04-06 11:57:41 +02003103 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01003104 ha_warning("Failed to disable forks, please report to developers with detailed "
3105 "information about your operating system. You can silence this warning "
3106 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
3107 }
3108 }
3109#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003110 run_poll_loop();
3111
3112 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
3113 ptdf->fct();
3114
Willy Tarreau082b6282019-05-22 14:42:12 +02003115 list_for_each_entry(ptff, &per_thread_free_list, list)
3116 ptff->fct();
3117
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003118#ifdef USE_THREAD
Willy Tarreau291f6ff2022-07-04 13:36:16 +02003119 if (!_HA_ATOMIC_AND_FETCH(&ha_tgroup_info[ti->tgid-1].threads_enabled, ~ti->ltid_bit))
Willy Tarreaucce203a2022-06-24 15:55:11 +02003120 _HA_ATOMIC_AND(&all_tgroups_mask, ~tg->tgid_bit);
Willy Tarreauad92fdf2022-07-06 10:17:21 +02003121 if (!_HA_ATOMIC_AND_FETCH(&tg_ctx->stopping_threads, ~ti->ltid_bit))
3122 _HA_ATOMIC_AND(&stopping_tgroup_mask, ~tg->tgid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003123 if (tid > 0)
3124 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02003125#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003126 return NULL;
3127}
Christopher Faulet1d17c102017-08-29 15:38:48 +02003128
William Dauchyf9af9d72019-11-17 15:47:16 +01003129/* set uid/gid depending on global settings */
3130static void set_identity(const char *program_name)
3131{
3132 if (global.gid) {
3133 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
3134 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
3135 " without 'uid'/'user' is generally useless.\n", program_name);
3136
3137 if (setgid(global.gid) == -1) {
3138 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
3139 protocol_unbind_all();
3140 exit(1);
3141 }
3142 }
3143
3144 if (global.uid && setuid(global.uid) == -1) {
3145 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
3146 protocol_unbind_all();
3147 exit(1);
3148 }
3149}
3150
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151int main(int argc, char **argv)
3152{
3153 int err, retry;
3154 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02003155 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02003156 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
3157
Willy Tarreau41afd902022-07-21 09:55:22 +02003158 /* Catch broken toolchains */
3159 if (sizeof(long) != sizeof(void *) || (intovf + 0x7FFFFFFF >= intovf)) {
3160 const char *msg;
3161
3162 if (sizeof(long) != sizeof(void *))
3163 /* Apparently MingW64 was not made for us and can also break openssl */
3164 msg = "The compiler this program was built with uses unsupported integral type sizes.\n"
3165 "Most likely it follows the unsupported LLP64 model. Never try to link HAProxy\n"
3166 "against libraries built with that compiler either! Please only use a compiler\n"
3167 "producing ILP32 or LP64 programs for both programs and libraries.\n";
3168 else if (intovf + 0x7FFFFFFF >= intovf)
3169 /* Catch forced CFLAGS that miss 2-complement integer overflow */
3170 msg = "The source code was miscompiled by the compiler, which usually indicates that\n"
3171 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
3172 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
3173 "and INSTALL files to decide on the best way to pass your local build options.\n";
3174 else
3175 msg = "Bug in the compiler bug detection code, please report it to developers!\n";
3176
Willy Tarreau1335da32021-07-14 17:54:01 +02003177 fprintf(stderr,
3178 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
Willy Tarreau41afd902022-07-21 09:55:22 +02003179 "%s"
3180 "\nBuild options :"
Willy Tarreau1335da32021-07-14 17:54:01 +02003181#ifdef BUILD_TARGET
Willy Tarreau41afd902022-07-21 09:55:22 +02003182 "\n TARGET = " BUILD_TARGET
Willy Tarreau1335da32021-07-14 17:54:01 +02003183#endif
3184#ifdef BUILD_CPU
Willy Tarreau41afd902022-07-21 09:55:22 +02003185 "\n CPU = " BUILD_CPU
Willy Tarreau1335da32021-07-14 17:54:01 +02003186#endif
3187#ifdef BUILD_CC
Willy Tarreau41afd902022-07-21 09:55:22 +02003188 "\n CC = " BUILD_CC
Willy Tarreau1335da32021-07-14 17:54:01 +02003189#endif
3190#ifdef BUILD_CFLAGS
Willy Tarreau41afd902022-07-21 09:55:22 +02003191 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau1335da32021-07-14 17:54:01 +02003192#endif
3193#ifdef BUILD_OPTIONS
Willy Tarreau41afd902022-07-21 09:55:22 +02003194 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau1335da32021-07-14 17:54:01 +02003195#endif
3196#ifdef BUILD_DEBUG
Willy Tarreau41afd902022-07-21 09:55:22 +02003197 "\n DEBUG = " BUILD_DEBUG
Willy Tarreau1335da32021-07-14 17:54:01 +02003198#endif
Willy Tarreau41afd902022-07-21 09:55:22 +02003199 "\n\n", msg);
3200
Willy Tarreau1335da32021-07-14 17:54:01 +02003201 return 1;
3202 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203
Olivier Houchard5fa300d2018-02-03 15:15:21 +01003204 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003205
Willy Tarreaubf696402019-03-01 10:09:28 +01003206 /* take a copy of initial limits before we possibly change them */
3207 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02003208
3209 if (limit.rlim_max == RLIM_INFINITY)
3210 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01003211 rlim_fd_cur_at_boot = limit.rlim_cur;
3212 rlim_fd_max_at_boot = limit.rlim_max;
3213
Willy Tarreau5794fb02018-11-25 18:43:29 +01003214 /* process all initcalls in order of potential dependency */
3215 RUN_INITCALLS(STG_PREPARE);
3216 RUN_INITCALLS(STG_LOCK);
Willy Tarreau3ebe4d92022-02-18 14:51:49 +01003217 RUN_INITCALLS(STG_REGISTER);
Willy Tarreau34527d52022-02-17 17:45:58 +01003218
3219 /* now's time to initialize early boot variables */
3220 init_early(argc, argv);
3221
Willy Tarreau18f96d02022-02-23 17:25:00 +01003222 /* handles argument parsing */
3223 init_args(argc, argv);
3224
Willy Tarreau5794fb02018-11-25 18:43:29 +01003225 RUN_INITCALLS(STG_ALLOC);
3226 RUN_INITCALLS(STG_POOL);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003227 RUN_INITCALLS(STG_INIT);
3228
Willy Tarreau34527d52022-02-17 17:45:58 +01003229 /* this is the late init where the config is parsed */
Emeric Bruncf20bf12010-10-22 16:06:11 +02003230 init(argc, argv);
Willy Tarreau34527d52022-02-17 17:45:58 +01003231
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003232 signal_register_fct(SIGQUIT, dump, SIGQUIT);
3233 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
3234 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02003235 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003236
Willy Tarreaue437c442010-03-17 18:02:46 +01003237 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
3238 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
3239 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003240 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003241 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003242
Willy Tarreaudc23a922011-02-16 11:10:36 +01003243 /* ulimits */
3244 if (!global.rlimit_nofile)
3245 global.rlimit_nofile = global.maxsock;
3246
3247 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01003248 limit.rlim_cur = global.rlimit_nofile;
3249 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
3250
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003251 if ((global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit) ||
Willy Tarreauc06557c2022-09-22 16:12:08 +02003252 raise_rlim_nofile(NULL, &limit) != 0) {
Willy Tarreauef635472016-06-21 11:48:18 +02003253 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003254 if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
3255 limit.rlim_cur = global.fd_hard_limit;
3256
William Dauchy0fec3ab2019-10-27 20:08:11 +01003257 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3258 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
3259 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003260 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003261 }
3262 else {
3263 /* try to set it to the max possible at least */
3264 limit.rlim_cur = limit.rlim_max;
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003265 if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
3266 limit.rlim_cur = global.fd_hard_limit;
3267
Willy Tarreauc06557c2022-09-22 16:12:08 +02003268 if (raise_rlim_nofile(&limit, &limit) == 0)
William Dauchy0fec3ab2019-10-27 20:08:11 +01003269 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02003270
William Dauchya5194602020-03-28 19:29:58 +01003271 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003272 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
3273 global.rlimit_nofile = limit.rlim_cur;
3274 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01003275 }
3276 }
3277
3278 if (global.rlimit_memmax) {
3279 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01003280 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01003281#ifdef RLIMIT_AS
3282 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003283 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3284 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3285 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003286 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003287 }
3288 else
William Dauchya5194602020-03-28 19:29:58 +01003289 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003290 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003291 }
3292#else
3293 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003294 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3295 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3296 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003297 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003298 }
3299 else
William Dauchya5194602020-03-28 19:29:58 +01003300 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003301 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003302 }
3303#endif
3304 }
3305
William Lallemandf82afbb2022-01-07 18:19:42 +01003306 /* Try to get the listeners FD from the previous process using
3307 * _getsocks on the stat socket, it must never been done in wait mode
3308 * and check mode
3309 */
3310 if (old_unixsocket &&
3311 !(global.mode & (MODE_MWORKER_WAIT|MODE_CHECK|MODE_CHECK_CONDITION))) {
William Lallemand85b0bd92017-06-01 17:38:53 +02003312 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02003313 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003314 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02003315 if (!(global.mode & MODE_MWORKER))
3316 exit(1);
3317 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02003318 }
3319 }
William Lallemand85b0bd92017-06-01 17:38:53 +02003320
Willy Tarreaubaaee002006-06-26 02:48:02 +02003321 /* We will loop at most 100 times with 10 ms delay each time.
3322 * That's at most 1 second. We only send a signal to old pids
3323 * if we cannot grab at least one port.
3324 */
3325 retry = MAX_START_RETRIES;
3326 err = ERR_NONE;
3327 while (retry >= 0) {
3328 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003329 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003330 /* exit the loop on no error or fatal error */
3331 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003332 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003333 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003334 break;
3335
3336 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3337 * listening sockets. So on those platforms, it would be wiser to
3338 * simply send SIGUSR1, which will not be undoable.
3339 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003340 if (tell_old_pids(SIGTTOU) == 0) {
3341 /* no need to wait if we can't contact old pids */
3342 retry = 0;
3343 continue;
3344 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003345 /* give some time to old processes to stop listening */
3346 w.tv_sec = 0;
3347 w.tv_usec = 10*1000;
3348 select(0, NULL, NULL, NULL, &w);
3349 retry--;
3350 }
3351
Willy Tarreaue91bff22020-09-02 11:11:43 +02003352 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003353 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003354 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003355 if (retry != MAX_START_RETRIES && nb_oldpids) {
3356 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003357 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003358 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 exit(1);
3360 }
3361
William Lallemand944e6192018-11-21 15:48:31 +01003362 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003363 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003364 /* Note: we don't have to send anything to the old pids because we
3365 * never stopped them. */
3366 exit(1);
3367 }
3368
Willy Tarreaue91bff22020-09-02 11:11:43 +02003369 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003370 * the previous process gave us, we don't need them anymore
3371 */
Willy Tarreaub5101162022-01-28 18:28:18 +01003372 sock_drop_unused_old_sockets();
Willy Tarreaudd815982007-10-16 12:25:14 +02003373
Willy Tarreaubaaee002006-06-26 02:48:02 +02003374 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003375 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3376 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003377
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 /* MODE_QUIET can inhibit alerts and warnings below this line */
3379
PiBa-NL149a81a2017-12-25 21:03:31 +01003380 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3381 /* either stdin/out/err are already closed or should stay as they are. */
3382 if ((global.mode & MODE_DAEMON)) {
3383 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3384 global.mode &= ~MODE_VERBOSE;
3385 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3386 }
3387 } else {
3388 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3389 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003390 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 }
3393
3394 /* open log & pid files before the chroot */
William Lallemand7b820a62022-02-14 09:02:14 +01003395 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) &&
3396 !(global.mode & MODE_MWORKER_WAIT) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003397 unlink(global.pidfile);
3398 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3399 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003400 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 if (nb_oldpids)
3402 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003403 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404 exit(1);
3405 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003406 }
3407
Willy Tarreaub38651a2007-03-24 17:24:39 +01003408 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003409 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3410 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003411 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003412 exit(1);
3413 }
3414
Jackie Tapia749f74c2020-07-22 18:59:40 -05003415 /* If the user is not root, we'll still let them try the configuration
3416 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003417 */
3418 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003419 ha_warning("[%s.main()] Some options which require full privileges"
3420 " might not work well.\n"
3421 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003422
William Lallemand095ba4c2017-06-01 17:38:50 +02003423 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3424
3425 /* chroot if needed */
3426 if (global.chroot != NULL) {
3427 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003428 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003429 if (nb_oldpids)
3430 tell_old_pids(SIGTTIN);
3431 protocol_unbind_all();
3432 exit(1);
3433 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003434 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003435 }
3436
William Lallemand944e6192018-11-21 15:48:31 +01003437 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003438 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003439
William Lallemand27edc4b2019-05-07 17:49:33 +02003440 /* send a SIGTERM to workers who have a too high reloads number */
3441 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3442 mworker_kill_max_reloads(SIGTERM);
3443
Willy Tarreaubaaee002006-06-26 02:48:02 +02003444 /* Note that any error at this stage will be fatal because we will not
3445 * be able to restart the old pids.
3446 */
3447
William Dauchyf9af9d72019-11-17 15:47:16 +01003448 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3449 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003450
Willy Tarreaubaaee002006-06-26 02:48:02 +02003451 /* check ulimits */
3452 limit.rlim_cur = limit.rlim_max = 0;
3453 getrlimit(RLIMIT_NOFILE, &limit);
3454 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003455 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3456 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3457 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3458 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3459 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003460 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003461 }
3462 else
3463 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003464 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003465 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3466 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003467 }
3468
William Lallemand944e6192018-11-21 15:48:31 +01003469 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003470 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003471 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003472 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003473
William Lallemand095ba4c2017-06-01 17:38:50 +02003474 /*
3475 * if daemon + mworker: must fork here to let a master
3476 * process live in background before forking children
3477 */
William Lallemand73b85e72017-06-01 17:38:51 +02003478
3479 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3480 && (global.mode & MODE_MWORKER)
3481 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003482 ret = fork();
3483 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003484 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003485 protocol_unbind_all();
3486 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003487 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003488 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003489 } else /* change the process group ID in the child (master process) */
3490 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003491 }
William Lallemande20b6a62017-06-01 17:38:55 +02003492
William Lallemande20b6a62017-06-01 17:38:55 +02003493
William Lallemanddeed7802017-11-06 11:00:04 +01003494 /* if in master-worker mode, write the PID of the father */
3495 if (global.mode & MODE_MWORKER) {
3496 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003497 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003498 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003499 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003500 }
3501
Willy Tarreaubaaee002006-06-26 02:48:02 +02003502 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003503 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemandeba6a542022-09-26 12:54:39 +02003504 struct ring *tmp_startup_logs = NULL;
3505
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003506 if (global.mode & MODE_MWORKER)
3507 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003508
William Lallemandeba6a542022-09-26 12:54:39 +02003509 /* at this point the worker must have his own startup_logs buffer */
3510 tmp_startup_logs = startup_logs_dup(startup_logs);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003511 ret = fork();
3512 if (ret < 0) {
3513 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3514 protocol_unbind_all();
3515 exit(1); /* there has been an error */
3516 }
3517 else if (ret == 0) { /* child breaks here */
William Lallemandeba6a542022-09-26 12:54:39 +02003518 startup_logs_free(startup_logs);
3519 startup_logs = tmp_startup_logs;
Willy Tarreau3c032f22021-07-21 10:17:02 +02003520 /* This one must not be exported, it's internal! */
3521 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003522 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003523 }
3524 else { /* parent here */
3525 in_parent = 1;
3526
William Lallemand944e6192018-11-21 15:48:31 +01003527 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3528 char pidstr[100];
3529 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003530 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003531 }
3532 if (global.mode & MODE_MWORKER) {
3533 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003534
William Lallemand5d71a6b2021-11-09 15:25:31 +01003535 ha_notice("New worker (%d) forked\n", ret);
William Lallemand944e6192018-11-21 15:48:31 +01003536 /* find the right mworker_proc */
3537 list_for_each_entry(child, &proc_list, list) {
William Lallemandd4835a92022-07-21 00:52:43 +02003538 if (child->reloads == 0 &&
3539 child->options & PROC_O_TYPE_WORKER &&
3540 child->pid == -1) {
William Lallemand944e6192018-11-21 15:48:31 +01003541 child->timestamp = now.tv_sec;
3542 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003543 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003544 break;
3545 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003546 }
3547 }
William Lallemand944e6192018-11-21 15:48:31 +01003548 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003549
William Lallemand944e6192018-11-21 15:48:31 +01003550 } else {
3551 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003552 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003553 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003554
3555#ifdef USE_CPU_AFFINITY
Willy Tarreau5b093412022-07-08 09:38:30 +02003556 if (!in_parent && ha_cpuset_count(&cpu_map[0].proc)) { /* only do this if the process has a CPU map */
Olivier Houchard97148f62017-08-16 17:29:11 +02003557
David CARLIERdf91cbd2022-01-06 18:53:50 +00003558#if defined(CPUSET_USE_CPUSET) || defined(__DragonFly__)
Willy Tarreau5b093412022-07-08 09:38:30 +02003559 struct hap_cpuset *set = &cpu_map[0].proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003560 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
David CARLIERdf91cbd2022-01-06 18:53:50 +00003561#elif defined(__FreeBSD__)
Willy Tarreau5b093412022-07-08 09:38:30 +02003562 struct hap_cpuset *set = &cpu_map[0].proc;
David CARLIERdf91cbd2022-01-06 18:53:50 +00003563 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003564#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003565 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003566#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003567 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003568 if (pidfd >= 0) {
3569 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3570 close(pidfd);
3571 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003572
3573 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003574 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575
Willy Tarreaud67ff342021-06-15 07:58:09 +02003576 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003577 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
William Lallemandfab0fdc2021-11-09 18:01:22 +01003578 master = 1;
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003579
3580 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3581 (global.mode & MODE_DAEMON)) {
3582 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003583 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3584 stdio_quiet(-1);
3585
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003586 global.mode &= ~MODE_VERBOSE;
3587 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003588 }
3589
William Lallemandfab0fdc2021-11-09 18:01:22 +01003590 if (global.mode & MODE_MWORKER_WAIT) {
3591 /* only the wait mode handles the master CLI */
3592 mworker_loop();
3593 } else {
3594
William Lallemanda46a99e2022-07-07 14:00:36 +02003595#if defined(USE_SYSTEMD)
3596 if (global.tune.options & GTUNE_USE_SYSTEMD)
3597 sd_notifyf(0, "READY=1\nMAINPID=%lu\nSTATUS=Ready.\n", (unsigned long)getpid());
3598#endif
William Lallemandfab0fdc2021-11-09 18:01:22 +01003599 /* if not in wait mode, reload in wait mode to free the memory */
William Lallemand68192b22022-09-24 15:44:42 +02003600 setenv("HAPROXY_LOAD_SUCCESS", "1", 1);
William Lallemand836bda22021-11-09 18:16:47 +01003601 ha_notice("Loading success.\n");
William Lallemand68836742021-11-10 10:49:06 +01003602 proc_self->failedreloads = 0; /* reset the number of failure */
William Lallemandfab0fdc2021-11-09 18:01:22 +01003603 mworker_reexec_waitmode();
3604 }
William Lallemand1499b9b2017-06-07 15:04:47 +02003605 /* should never get there */
3606 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003607 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003608#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003609 ssl_free_dh();
3610#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003611 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003612 }
3613
William Lallemandcb11fd22017-06-01 17:38:52 +02003614 /* child must never use the atexit function */
3615 atexit_flag = 0;
3616
William Lallemandbc193052018-09-11 10:06:26 +02003617 /* close useless master sockets */
3618 if (global.mode & MODE_MWORKER) {
3619 struct mworker_proc *child, *it;
3620 master = 0;
3621
William Lallemand309dc9a2018-10-26 14:47:45 +02003622 mworker_cli_proxy_stop();
3623
William Lallemandbc193052018-09-11 10:06:26 +02003624 /* free proc struct of other processes */
3625 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003626 /* close the FD of the master side for all
3627 * workers, we don't need to close the worker
3628 * side of other workers since it's done with
3629 * the bind_proc */
William Lallemand7e018782022-01-28 21:56:24 +01003630 if (child->ipc_fd[0] >= 0) {
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003631 close(child->ipc_fd[0]);
William Lallemand7e018782022-01-28 21:56:24 +01003632 child->ipc_fd[0] = -1;
3633 }
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003634 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandd4835a92022-07-21 00:52:43 +02003635 child->reloads == 0 &&
3636 child->pid == -1) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003637 /* keep this struct if this is our pid */
3638 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003639 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003640 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003641 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003642 mworker_free_child(child);
3643 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003644 }
3645 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003646
William Lallemande1340412017-12-28 16:09:36 +01003647 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3648 devnullfd = open("/dev/null", O_RDWR, 0);
3649 if (devnullfd < 0) {
3650 ha_alert("Cannot open /dev/null\n");
3651 exit(EXIT_FAILURE);
3652 }
3653 }
3654
William Lallemand095ba4c2017-06-01 17:38:50 +02003655 /* Must chroot and setgid/setuid in the children */
3656 /* chroot if needed */
3657 if (global.chroot != NULL) {
3658 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003659 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003660 if (nb_oldpids)
3661 tell_old_pids(SIGTTIN);
3662 protocol_unbind_all();
3663 exit(1);
3664 }
3665 }
3666
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003667 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003668 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003669
William Lallemand7f80eb22017-05-26 18:19:55 +02003670 /* pass through every cli socket, and check if it's bound to
3671 * the current process and if it exposes listeners sockets.
3672 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3673 * */
3674
Willy Tarreau4975d142021-03-13 11:00:33 +01003675 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003676 struct bind_conf *bind_conf;
3677
Willy Tarreau4975d142021-03-13 11:00:33 +01003678 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003679 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003680 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3681 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003682 }
3683 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003684 }
3685
William Lallemand2e8fad92018-11-13 16:18:23 +01003686 /*
3687 * This is only done in daemon mode because we might want the
3688 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3689 * we should now close the 3 first FDs to ensure that we can
3690 * detach from the TTY. We MUST NOT do it in other cases since
3691 * it would have already be done, and 0-2 would have been
3692 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003693 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003694 if ((global.mode & MODE_DAEMON) &&
3695 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003696 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003697 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003698 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003699 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3700 }
3701 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003702 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3703 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003704 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003705 }
3706
William Dauchye039f262019-11-17 15:47:15 +01003707 /* try our best to re-enable core dumps depending on system capabilities.
3708 * What is addressed here :
3709 * - remove file size limits
3710 * - remove core size limits
3711 * - mark the process dumpable again if it lost it due to user/group
3712 */
3713 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3714 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3715
3716#if defined(RLIMIT_FSIZE)
3717 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3718 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3719 ha_alert("[%s.main()] Failed to set the raise the maximum "
3720 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003721 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003722 }
3723 else
3724 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003725 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003726 }
3727#endif
3728
3729#if defined(RLIMIT_CORE)
3730 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3731 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3732 ha_alert("[%s.main()] Failed to set the raise the core "
3733 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003734 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003735 }
3736 else
3737 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003738 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003739 }
3740#endif
3741
3742#if defined(USE_PRCTL)
3743 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3744 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3745 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003746#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003747 {
3748 int traceable = PROC_TRACE_CTL_ENABLE;
3749 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3750 ha_warning("[%s.main()] Failed to set the traceable flag, "
3751 "no core will be dumped.\n", argv[0]);
3752 }
William Dauchye039f262019-11-17 15:47:15 +01003753#endif
3754 }
3755
Christopher Faulete3a5e352017-10-24 13:53:54 +02003756 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003757 reset_usermsgs_ctx();
3758
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003759 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003760 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003761
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003762 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003763 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003764
3765 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003766 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003767
3768 /* wait for all threads to terminate */
3769 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003770
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003771 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003772}
3773
Willy Tarreaubaaee002006-06-26 02:48:02 +02003774/*
3775 * Local variables:
3776 * c-indent-level: 8
3777 * c-basic-offset: 8
3778 * End:
3779 */