blob: e03b2388e9ff24ed3bef51217470e5d017590eef [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 Tarreau40c88f92023-01-07 09:45:17 +01003 * Copyright 2000-2023 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
Willy Tarreau6c011712023-01-06 16:09:58 +0100207 .nb_stk_ctr = MAX_SESS_STKCTR,
Amaury Denoyelle97e84c62022-04-19 18:26:55 +0200208#ifdef USE_QUIC
Frédéric Lécailleaee67572022-05-23 18:29:39 +0200209 .quic_backend_max_idle_timeout = QUIC_TP_DFLT_BACK_MAX_IDLE_TIMEOUT,
210 .quic_frontend_max_idle_timeout = QUIC_TP_DFLT_FRONT_MAX_IDLE_TIMEOUT,
211 .quic_frontend_max_streams_bidi = QUIC_TP_DFLT_FRONT_MAX_STREAMS_BIDI,
Frédéric Lécaille92862102022-05-20 16:29:10 +0200212 .quic_retry_threshold = QUIC_DFLT_RETRY_THRESHOLD,
Amaury Denoyelle24d5b722023-01-31 11:44:50 +0100213 .quic_max_frame_loss = QUIC_DFLT_MAX_FRAME_LOSS,
Amaury Denoyelle97e84c62022-04-19 18:26:55 +0200214 .quic_streams_buf = 30,
215#endif /* USE_QUIC */
Willy Tarreau27a674e2009-08-17 07:23:33 +0200216 },
Emeric Brun76d88952012-10-05 15:47:31 +0200217#ifdef USE_OPENSSL
218#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200219 .maxsslconn = DEFAULT_MAXSSLCONN,
220#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200221#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 /* others NULL OK */
223};
224
225/*********************************************************************/
226
227int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100228int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200229int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100230int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100231int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100232int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreau392524d2022-02-17 18:10:36 +0100233int arg_mode = 0; /* MODE_DEBUG etc as passed on command line ... */
234char *change_dir = NULL; /* set when -C is passed */
235char *check_condition = NULL; /* check condition passed to -cc */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500237/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 * or kill. We will send them a signal every 10 ms until we can bind to all
239 * our ports. With 200 retries, that's about 2 seconds.
240 */
241#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242static int *oldpids = NULL;
243static int oldpids_sig; /* use USR1 or TERM */
244
Olivier Houchardf73629d2017-04-05 22:33:04 +0200245/* Path to the unix socket we use to retrieve listener sockets from the old process */
246static const char *old_unixsocket;
247
William Lallemandcb11fd22017-06-01 17:38:52 +0200248int atexit_flag = 0;
249
Willy Tarreaubb545b42010-08-25 12:58:59 +0200250int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251const int zero = 0;
252const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200253const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100255char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200256char *localpeer = NULL;
Willy Tarreau76871a42022-03-08 16:01:40 +0100257static char *kwd_dump = NULL; // list of keyword dumps to produce
Willy Tarreaubaaee002006-06-26 02:48:02 +0200258
William Lallemand00417412020-06-05 14:08:41 +0200259static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200260
William Lallemandbc193052018-09-11 10:06:26 +0200261struct list proc_list = LIST_HEAD_INIT(proc_list);
262
263int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100264unsigned int rlim_fd_cur_at_boot = 0;
265unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200266
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100267/* per-boot randomness */
268unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
269
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200270/* takes the thread config in argument or NULL for any thread */
William Lallemandb3f2be32018-09-11 10:06:18 +0200271static void *run_thread_poll_loop(void *data);
272
Willy Tarreauff055502014-04-28 22:27:06 +0200273/* bitfield of a few warnings to emit just once (WARN_*) */
274unsigned int warned = 0;
275
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200276/* set if experimental features have been used for the current process */
Willy Tarreauedd42682022-02-25 10:10:00 +0100277unsigned int tainted = 0;
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200278
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200279unsigned int experimental_directives_allowed = 0;
280
281int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
282 char **errmsg)
283{
284 if (kw->flags & KWF_EXPERIMENTAL) {
285 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200286 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 +0200287 file, linenum, kw->kw);
288 return 1;
289 }
290 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
291 }
292
293 return 0;
294}
295
William Lallemande7361152018-10-26 14:47:36 +0200296/* master CLI configuration (-S flag) */
297struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100298
299/* These are strings to be reported in the output of "haproxy -vv". They may
300 * either be constants (in which case must_free must be zero) or dynamically
301 * allocated strings to pass to free() on exit, and in this case must_free
302 * must be non-zero.
303 */
304struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
305struct build_opts_str {
306 struct list list;
307 const char *str;
308 int must_free;
309};
310
Willy Tarreaubaaee002006-06-26 02:48:02 +0200311/*********************************************************************/
312/* general purpose functions ***************************************/
313/*********************************************************************/
314
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100315/* used to register some build option strings at boot. Set must_free to
316 * non-zero if the string must be freed upon exit.
317 */
318void hap_register_build_opts(const char *str, int must_free)
319{
320 struct build_opts_str *b;
321
322 b = calloc(1, sizeof(*b));
323 if (!b) {
324 fprintf(stderr, "out of memory\n");
325 exit(1);
326 }
327 b->str = str;
328 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200329 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100330}
331
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200332#define VERSION_MAX_ELTS 7
333
334/* This function splits an haproxy version string into an array of integers.
335 * The syntax of the supported version string is the following:
336 *
337 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
338 *
339 * This validates for example:
340 * 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
341 * 2.4-dev18-f6818d-20
342 *
343 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
344 * one fixed place in the array. The tags take a numeric value called <e> which
345 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
346 * considered as zero (henxe 1.5 and 1.5.0 are the same).
347 *
348 * The resulting values are:
349 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
350 * 1.2.1 1, 2, 1, 0, 3, 0, 0
351 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
352 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
353 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
354 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
355 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
356 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
357 *
358 * The function returns non-zero if the conversion succeeded, or zero if it
359 * failed.
360 */
361int split_version(const char *version, unsigned int *value)
362{
363 const char *p, *s;
364 char *error;
365 int nelts;
366
367 /* Initialize array with zeroes */
368 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
369 value[nelts] = 0;
370 value[4] = 3;
371
372 p = version;
373
374 /* If the version number is empty, return false */
375 if (*p == '\0')
376 return 0;
377
378 /* Convert first number <a> */
379 value[0] = strtol(p, &error, 10);
380 p = error + 1;
381 if (*error == '\0')
382 return 1;
383 if (*error == '-')
384 goto split_version_tag;
385 if (*error != '.')
386 return 0;
387
388 /* Convert first number <b> */
389 value[1] = strtol(p, &error, 10);
390 p = error + 1;
391 if (*error == '\0')
392 return 1;
393 if (*error == '-')
394 goto split_version_tag;
395 if (*error != '.')
396 return 0;
397
398 /* Convert first number <c> */
399 value[2] = strtol(p, &error, 10);
400 p = error + 1;
401 if (*error == '\0')
402 return 1;
403 if (*error == '-')
404 goto split_version_tag;
405 if (*error != '.')
406 return 0;
407
408 /* Convert first number <d> */
409 value[3] = strtol(p, &error, 10);
410 p = error + 1;
411 if (*error == '\0')
412 return 1;
413 if (*error != '-')
414 return 0;
415
416 split_version_tag:
417 /* Check for commit number */
418 if (*p >= '0' && *p <= '9')
419 goto split_version_commit;
420
421 /* Read tag */
422 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
423 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
424 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
425 else
426 goto split_version_commit;
427
428 /* Convert tag number */
429 value[5] = strtol(p, &error, 10);
430 p = error + 1;
431 if (*error == '\0')
432 return 1;
433 if (*error != '-')
434 return 0;
435
436 split_version_commit:
437 /* Search the last "-" */
438 s = strrchr(p, '-');
439 if (s) {
440 s++;
441 if (*s == '\0')
442 return 0;
443 value[6] = strtol(s, &error, 10);
444 if (*error != '\0')
445 value[6] = 0;
446 return 1;
447 }
448
449 /* convert the version */
450 value[6] = strtol(p, &error, 10);
451 if (*error != '\0')
452 value[6] = 0;
453
454 return 1;
455}
456
457/* This function compares the current haproxy version with an arbitrary version
458 * string. It returns:
459 * -1 : the version in argument is older than the current haproxy version
460 * 0 : the version in argument is the same as the current haproxy version
461 * 1 : the version in argument is newer than the current haproxy version
462 *
463 * Or some errors:
464 * -2 : the current haproxy version is not parsable
465 * -3 : the version in argument is not parsable
466 */
467int compare_current_version(const char *version)
468{
469 unsigned int loc[VERSION_MAX_ELTS];
470 unsigned int mod[VERSION_MAX_ELTS];
471 int i;
472
473 /* split versions */
474 if (!split_version(haproxy_version, loc))
475 return -2;
476 if (!split_version(version, mod))
477 return -3;
478
479 /* compare versions */
480 for (i = 0; i < VERSION_MAX_ELTS; i++) {
481 if (mod[i] < loc[i])
482 return -1;
483 else if (mod[i] > loc[i])
484 return 1;
485 }
486 return 0;
487}
488
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100489static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200490{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200491 struct utsname utsname;
492
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200493 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100494 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100495
496 if (strlen(PRODUCT_URL_BUGS) > 0) {
497 char base_version[20];
498 int dots = 0;
499 char *del;
500
501 /* only retrieve the base version without distro-specific extensions */
502 for (del = haproxy_version; *del; del++) {
503 if (*del == '.')
504 dots++;
505 else if (*del < '0' || *del > '9')
506 break;
507 }
508
509 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
510 if (dots < 2)
511 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
512 else
513 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
514 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200515
516 if (uname(&utsname) == 0) {
517 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
518 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200519}
520
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100521static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100522{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100523 struct build_opts_str *item;
524
Willy Tarreau7b066db2007-12-02 11:28:59 +0100525 printf("Build options :"
526#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100527 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100528#endif
529#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100530 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100531#endif
532#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100533 "\n CC = " BUILD_CC
534#endif
535#ifdef BUILD_CFLAGS
536 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100537#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100538#ifdef BUILD_OPTIONS
539 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100540#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100541#ifdef BUILD_DEBUG
542 "\n DEBUG = " BUILD_DEBUG
543#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100544#ifdef BUILD_FEATURES
545 "\n\nFeature list : " BUILD_FEATURES
546#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200547 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100548 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200549 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100550 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200551
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100552 list_for_each_entry(item, &build_opts_list, list) {
553 puts(item->str);
554 }
555
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100556 putchar('\n');
557
Willy Tarreaube5b6852009-10-03 18:57:08 +0200558 list_pollers(stdout);
559 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200560 list_mux_proto(stdout);
561 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100562 list_services(stdout);
563 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100564 list_filters(stdout);
565 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100566}
567
Willy Tarreaubaaee002006-06-26 02:48:02 +0200568/*
569 * This function prints the command line usage and exits
570 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100571static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200572{
573 display_version();
574 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200575 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200576 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200577 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100578 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreauf4b79c42022-02-23 15:20:53 +0100580 " -dM[<byte>,help,...] debug memory (default: poison with <byte>/0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200582 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200583 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100584#if defined(USE_SYSTEMD)
585 " -Ws master-worker mode with systemd notify support.\n"
586#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200588 " -c check mode : only check config files and exit\n"
Maximilian Maderfc0cceb2021-06-06 00:50:22 +0200589 " -cc check condition : evaluate a condition and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100590 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200591 " -m limits the usable amount of memory (in MB)\n"
592 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200593 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200594 " -p writes pids of all children to this file\n"
Erwan Le Goasf30c5d72022-09-29 10:34:04 +0200595 " -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 +0200596#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200597 " -de disables epoll() usage even when available\n"
598#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200599#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200600 " -dk disables kqueue() usage even when available\n"
601#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200602#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000603 " -dv disables event ports usage even when available\n"
604#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200605#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200606 " -dp disables poll() usage even when available\n"
607#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200608#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100609 " -dS disables splice usage (broken on old kernels)\n"
610#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200611#if defined(USE_GETADDRINFO)
612 " -dG disables getaddrinfo() usage\n"
613#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000614#if defined(SO_REUSEPORT)
615 " -dR disables SO_REUSEPORT usage\n"
616#endif
Willy Tarreau654726d2021-12-28 15:43:11 +0100617#if defined(HA_HAVE_DUMP_LIBS)
618 " -dL dumps loaded object files after config checks\n"
619#endif
Willy Tarreau76871a42022-03-08 16:01:40 +0100620 " -dK{class[,...]} dump registered keywords (use 'help' for list)\n"
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100621 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100622 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200623 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200624 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200625 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200626 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200627 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100629 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 exit(1);
631}
632
633
634
635/*********************************************************************/
636/* more specific functions ***************************************/
637/*********************************************************************/
638
William Lallemand73b85e72017-06-01 17:38:51 +0200639/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
640 * pids the signal was correctly delivered to.
641 */
William Lallemande25473c2019-04-01 11:29:56 +0200642int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200643{
644 int p;
645 int ret = 0;
646 for (p = 0; p < nb_oldpids; p++)
647 if (kill(oldpids[p], sig) == 0)
648 ret++;
649 return ret;
650}
651
William Lallemand75ea0a02017-11-15 19:02:58 +0100652/*
William Lallemand73b85e72017-06-01 17:38:51 +0200653 * remove a pid forom the olpid array and decrease nb_oldpids
654 * return 1 pid was found otherwise return 0
655 */
656
657int delete_oldpid(int pid)
658{
659 int i;
660
661 for (i = 0; i < nb_oldpids; i++) {
662 if (oldpids[i] == pid) {
663 oldpids[i] = oldpids[nb_oldpids - 1];
664 oldpids[nb_oldpids - 1] = 0;
665 nb_oldpids--;
666 return 1;
667 }
668 }
669 return 0;
670}
671
William Lallemand85b0bd92017-06-01 17:38:53 +0200672
William Lallemand73b85e72017-06-01 17:38:51 +0200673/*
674 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800675 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200676 */
William Lallemandfab0fdc2021-11-09 18:01:22 +0100677static void mworker_reexec()
William Lallemand73b85e72017-06-01 17:38:51 +0200678{
William Lallemand00417412020-06-05 14:08:41 +0200679 char **next_argv = NULL;
680 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200681 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200682 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200683 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100684 struct rlimit limit;
William Lallemand2be557f2021-11-24 18:45:37 +0100685 struct mworker_proc *current_child = NULL;
William Lallemand73b85e72017-06-01 17:38:51 +0200686
687 mworker_block_signals();
William Lallemand73b85e72017-06-01 17:38:51 +0200688 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
689
William Lallemand55a921c2022-01-28 21:17:30 +0100690 mworker_cleanup_proc();
William Lallemandbc193052018-09-11 10:06:26 +0200691 mworker_proc_list_to_env(); /* put the children description in the env */
692
William Lallemandc4810b82021-11-18 10:51:30 +0100693 /* ensure that we close correctly every listeners before reexecuting */
694 mworker_cleanlisteners();
695
William Lallemand7c756a82018-11-26 11:53:40 +0100696 /* during the reload we must ensure that every FDs that can't be
697 * reuse (ie those that are not referenced in the proc_list)
698 * are closed or they will leak. */
699
700 /* close the listeners FD */
701 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200702
William Lallemand67e371e2021-11-25 10:03:44 +0100703 if (fdtab)
704 deinit_pollers();
William Lallemandefd95472021-11-26 14:43:57 +0100705
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500706#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200707 /* close random device FDs */
708 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100709#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100710
Willy Tarreau8dca1952019-03-01 10:21:55 +0100711 /* restore the initial FD limits */
712 limit.rlim_cur = rlim_fd_cur_at_boot;
713 limit.rlim_max = rlim_fd_max_at_boot;
Willy Tarreauc06557c2022-09-22 16:12:08 +0200714 if (raise_rlim_nofile(&limit, &limit) != 0) {
Willy Tarreau8dca1952019-03-01 10:21:55 +0100715 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
716 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
717 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
718 }
719
William Lallemand73b85e72017-06-01 17:38:51 +0200720 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200721 while (old_argv[old_argc])
722 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200723
William Lallemand85b0bd92017-06-01 17:38:53 +0200724 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200725 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200726 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200727 if (next_argv == NULL)
728 goto alloc_error;
729
William Lallemand00417412020-06-05 14:08:41 +0200730 /* copy the program name */
731 next_argv[next_argc++] = old_argv[0];
732
733 /* insert the new options just after argv[0] in case we have a -- */
734
William Lallemandbefab9e2021-11-25 00:49:19 +0100735 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
736 /* add -sf <PID>* to argv */
737 if (mworker_child_nb() > 0) {
738 struct mworker_proc *child;
William Lallemand3f128872019-04-01 11:29:59 +0200739
William Lallemandbefab9e2021-11-25 00:49:19 +0100740 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200741
William Lallemandbefab9e2021-11-25 00:49:19 +0100742 list_for_each_entry(child, &proc_list, list) {
743 if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
744 current_child = child;
William Lallemand2be557f2021-11-24 18:45:37 +0100745
William Lallemandbefab9e2021-11-25 00:49:19 +0100746 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
747 continue;
748 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
749 goto alloc_error;
750 msg = NULL;
751 }
William Lallemand73b85e72017-06-01 17:38:51 +0200752 }
William Lallemand2be557f2021-11-24 18:45:37 +0100753
754 if (current_child) {
755 /* add the -x option with the socketpair of the current worker */
756 next_argv[next_argc++] = "-x";
757 if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
758 goto alloc_error;
759 msg = NULL;
760 }
William Lallemand85b0bd92017-06-01 17:38:53 +0200761 }
762
William Lallemand00417412020-06-05 14:08:41 +0200763 /* copy the previous options */
764 for (i = 1; i < old_argc; i++)
765 next_argv[next_argc++] = old_argv[i];
766
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200767 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100768 execvp(next_argv[0], next_argv);
Christopher Faulet767a84b2017-11-24 16:50:31 +0100769 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100770 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100771 return;
772
William Lallemand73b85e72017-06-01 17:38:51 +0200773alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100774 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800775 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200776 return;
777}
778
William Lallemandfab0fdc2021-11-09 18:01:22 +0100779/* reexec haproxy in waitmode */
780static void mworker_reexec_waitmode()
781{
782 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
783 mworker_reexec();
784}
785
786/* reload haproxy and emit a warning */
787void mworker_reload()
788{
William Lallemandad221f42021-11-09 18:43:59 +0100789 struct mworker_proc *child;
William Lallemandefd95472021-11-26 14:43:57 +0100790 struct per_thread_deinit_fct *ptdf;
William Lallemandad221f42021-11-09 18:43:59 +0100791
William Lallemand836bda22021-11-09 18:16:47 +0100792 ha_notice("Reloading HAProxy\n");
William Lallemandad221f42021-11-09 18:43:59 +0100793
William Lallemandefd95472021-11-26 14:43:57 +0100794 /* close the poller FD and the thread waker pipe FD */
795 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
796 ptdf->fct();
797
William Lallemandad221f42021-11-09 18:43:59 +0100798 /* increment the number of reloads */
799 list_for_each_entry(child, &proc_list, list) {
800 child->reloads++;
801 }
802
William Lallemanda46a99e2022-07-07 14:00:36 +0200803#if defined(USE_SYSTEMD)
804 if (global.tune.options & GTUNE_USE_SYSTEMD)
805 sd_notify(0, "RELOADING=1\nSTATUS=Reloading Configuration.\n");
806#endif
William Lallemandfab0fdc2021-11-09 18:01:22 +0100807 mworker_reexec();
808}
809
William Lallemandb3f2be32018-09-11 10:06:18 +0200810static void mworker_loop()
811{
812
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200813 /* Busy polling makes no sense in the master :-) */
814 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200815
William Lallemandbc193052018-09-11 10:06:26 +0200816
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100817 signal_unregister(SIGTTIN);
818 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100819 signal_unregister(SIGUSR1);
820 signal_unregister(SIGHUP);
821 signal_unregister(SIGQUIT);
822
William Lallemandb3f2be32018-09-11 10:06:18 +0200823 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
824 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100825 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
826 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200827 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
828 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
829 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
830 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
831
832 mworker_unblock_signals();
William Lallemand27f3fa52018-12-06 14:05:20 +0100833 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200834
William Lallemandbc193052018-09-11 10:06:26 +0200835 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
836 some SIGCHLD were lost */
837
William Lallemandb3f2be32018-09-11 10:06:18 +0200838 jobs++; /* this is the "master" job, we want to take care of the
839 signals even if there is no listener so the poll loop don't
840 leave */
841
842 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200843 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200844}
William Lallemandcb11fd22017-06-01 17:38:52 +0200845
846/*
847 * Reexec the process in failure mode, instead of exiting
848 */
849void reexec_on_failure()
850{
William Lallemand68836742021-11-10 10:49:06 +0100851 struct mworker_proc *child;
852
William Lallemandcb11fd22017-06-01 17:38:52 +0200853 if (!atexit_flag)
854 return;
William Lallemand68836742021-11-10 10:49:06 +0100855
856 /* get the info of the children in the env */
857 if (mworker_env_to_proc_list() < 0) {
858 exit(EXIT_FAILURE);
859 }
860
861 /* increment the number of failed reloads */
862 list_for_each_entry(child, &proc_list, list) {
863 child->failedreloads++;
864 }
865
Willy Tarreaue08acae2022-01-28 18:40:06 +0100866 /* do not keep unused FDs retrieved from the previous process */
867 sock_drop_unused_old_sockets();
868
William Lallemandfab0fdc2021-11-09 18:01:22 +0100869 usermsgs_clr(NULL);
William Lallemand68192b22022-09-24 15:44:42 +0200870 setenv("HAPROXY_LOAD_SUCCESS", "0", 1);
William Lallemand836bda22021-11-09 18:16:47 +0100871 ha_warning("Loading failure!\n");
William Lallemanda46a99e2022-07-07 14:00:36 +0200872#if defined(USE_SYSTEMD)
873 /* the sd_notify API is not able to send a reload failure signal. So
874 * the READY=1 signal still need to be sent */
875 if (global.tune.options & GTUNE_USE_SYSTEMD)
876 sd_notify(0, "READY=1\nSTATUS=Reload failed!\n");
877#endif
878
William Lallemandfab0fdc2021-11-09 18:01:22 +0100879 mworker_reexec_waitmode();
William Lallemandcb11fd22017-06-01 17:38:52 +0200880}
William Lallemand73b85e72017-06-01 17:38:51 +0200881
William Lallemand40db4ae2022-12-07 15:03:55 +0100882/*
883 * Exit with an error message upon a wait-mode failure.
884 */
885void exit_on_waitmode_failure()
886{
887 if (!atexit_flag)
888 return;
889
890 ha_alert("Non-recoverable mworker wait-mode error, exiting.\n");
891}
892
William Lallemand73b85e72017-06-01 17:38:51 +0200893
894/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200895 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
896 * a signal zero to all subscribers. This means that it's as easy as
897 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100899static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900{
901 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200902 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100903 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904}
905
906/*
907 * upon SIGTTOU, we pause everything
908 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100909static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910{
Willy Tarreau775e0012020-09-24 16:36:26 +0200911 if (protocol_pause_all() & ERR_FATAL) {
912 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200913 ha_warning("%s", msg);
914 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200915 soft_stop();
916 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100917 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918}
919
920/*
921 * upon SIGTTIN, let's have a soft stop.
922 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100923static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924{
Willy Tarreau775e0012020-09-24 16:36:26 +0200925 if (protocol_resume_all() & ERR_FATAL) {
926 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 +0200927 ha_warning("%s", msg);
928 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200929 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930}
931
932/*
933 * this function dumps every server's state when the process receives SIGHUP.
934 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100935static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100937 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938
Christopher Faulet767a84b2017-11-24 16:50:31 +0100939 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940 while (p) {
941 struct server *s = p->srv;
942
943 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
944 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100945 chunk_printf(&trash,
946 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
947 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200948 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200949 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200950 ha_warning("%s\n", trash.area);
951 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952 s = s->next;
953 }
954
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200955 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
956 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100957 chunk_printf(&trash,
958 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
959 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200960 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 +0200961 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100962 chunk_printf(&trash,
963 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
964 p->id,
965 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200966 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 +0200967 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100968 chunk_printf(&trash,
969 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
970 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
971 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200972 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 +0200973 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200974 ha_warning("%s\n", trash.area);
975 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200976
977 p = p->next;
978 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200979}
980
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100981static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200983 /* dump memory usage then free everything possible */
984 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100985 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986}
987
William Lallemande1340412017-12-28 16:09:36 +0100988/*
989 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
990 * If <fd> < 0, it opens /dev/null and use it to dup
991 *
992 * In the case of chrooting, you have to open /dev/null before the chroot, and
993 * pass the <fd> to this function
994 */
995static void stdio_quiet(int fd)
996{
997 if (fd < 0)
998 fd = open("/dev/null", O_RDWR, 0);
999
1000 if (fd > -1) {
1001 fclose(stdin);
1002 fclose(stdout);
1003 fclose(stderr);
1004
1005 dup2(fd, 0);
1006 dup2(fd, 1);
1007 dup2(fd, 2);
1008 if (fd > 2)
1009 close(fd);
1010 return;
1011 }
1012
1013 ha_alert("Cannot open /dev/null\n");
1014 exit(EXIT_FAILURE);
1015}
1016
1017
Joseph Herlant03420902018-11-15 10:41:50 -08001018/* This function checks if cfg_cfgfiles contains directories.
1019 * If it finds one, it adds all the files (and only files) it contains
1020 * in cfg_cfgfiles in place of the directory (and removes the directory).
1021 * It adds the files in lexical order.
1022 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001023 * It doesn't add files with name starting with '.'
1024 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001025static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001026{
1027 struct wordlist *wl, *wlb;
1028 char *err = NULL;
1029
1030 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1031 struct stat file_stat;
1032 struct dirent **dir_entries = NULL;
1033 int dir_entries_nb;
1034 int dir_entries_it;
1035
1036 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001037 ha_alert("Cannot open configuration file/directory %s : %s\n",
1038 wl->s,
1039 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001040 exit(1);
1041 }
1042
1043 if (!S_ISDIR(file_stat.st_mode))
1044 continue;
1045
1046 /* from this point wl->s is a directory */
1047
1048 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1049 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001050 ha_alert("Cannot open configuration directory %s : %s\n",
1051 wl->s,
1052 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001053 exit(1);
1054 }
1055
1056 /* for each element in the directory wl->s */
1057 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1058 struct dirent *dir_entry = dir_entries[dir_entries_it];
1059 char *filename = NULL;
1060 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1061
1062 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001063 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001064 */
1065 if (dir_entry->d_name[0] == '.' ||
1066 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1067 goto next_dir_entry;
1068
1069 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001070 ha_alert("Cannot load configuration files %s : out of memory.\n",
1071 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001072 exit(1);
1073 }
1074
1075 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001076 ha_alert("Cannot open configuration file %s : %s\n",
1077 wl->s,
1078 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001079 exit(1);
1080 }
1081
1082 /* don't add anything else than regular file in cfg_cfgfiles
1083 * this way we avoid loops
1084 */
1085 if (!S_ISREG(file_stat.st_mode))
1086 goto next_dir_entry;
1087
1088 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001089 ha_alert("Cannot load configuration files %s : %s\n",
1090 filename,
1091 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001092 exit(1);
1093 }
1094
1095next_dir_entry:
1096 free(filename);
1097 free(dir_entry);
1098 }
1099
1100 free(dir_entries);
1101
1102 /* remove the current directory (wl) from cfg_cfgfiles */
1103 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001104 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001105 free(wl);
1106 }
1107
1108 free(err);
1109}
1110
Willy Tarreaubaaee002006-06-26 02:48:02 +02001111/*
William Lallemand73b85e72017-06-01 17:38:51 +02001112 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001113 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001114 * Return an allocated copy of argv
1115 */
1116
1117static char **copy_argv(int argc, char **argv)
1118{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001119 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001120
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001121 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001122 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001123 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001124 return NULL;
1125 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001126 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001127
William Lallemanddf6c5a82020-06-04 17:40:23 +02001128 /* first copy argv[0] */
1129 *newargv++ = *argv++;
1130 argc--;
1131
1132 while (argc > 0) {
1133 if (**argv != '-') {
1134 /* non options are copied but will fail in the argument parser */
1135 *newargv++ = *argv++;
1136 argc--;
1137
1138 } else {
1139 char *flag;
1140
1141 flag = *argv + 1;
1142
1143 if (flag[0] == '-' && flag[1] == 0) {
1144 /* "--\0" copy every arguments till the end of argv */
1145 *newargv++ = *argv++;
1146 argc--;
1147
1148 while (argc > 0) {
1149 *newargv++ = *argv++;
1150 argc--;
1151 }
1152 } else {
1153 switch (*flag) {
1154 case 's':
1155 /* -sf / -st and their parameters are ignored */
1156 if (flag[1] == 'f' || flag[1] == 't') {
1157 argc--;
1158 argv++;
1159 /* The list can't contain a negative value since the only
1160 way to know the end of this list is by looking for the
1161 next option or the end of the options */
1162 while (argc > 0 && argv[0][0] != '-') {
1163 argc--;
1164 argv++;
1165 }
William Lallemand398da622020-09-02 16:12:23 +02001166 } else {
1167 argc--;
1168 argv++;
1169
William Lallemanddf6c5a82020-06-04 17:40:23 +02001170 }
1171 break;
1172
1173 case 'x':
1174 /* this option and its parameter are ignored */
1175 argc--;
1176 argv++;
1177 if (argc > 0) {
1178 argc--;
1179 argv++;
1180 }
1181 break;
1182
1183 case 'C':
1184 case 'n':
1185 case 'm':
1186 case 'N':
1187 case 'L':
1188 case 'f':
1189 case 'p':
1190 case 'S':
1191 /* these options have only 1 parameter which must be copied and can start with a '-' */
1192 *newargv++ = *argv++;
1193 argc--;
1194 if (argc == 0)
1195 goto error;
1196 *newargv++ = *argv++;
1197 argc--;
1198 break;
1199 default:
1200 /* for other options just copy them without parameters, this is also done
1201 * for options like "--foo", but this will fail in the argument parser.
1202 * */
1203 *newargv++ = *argv++;
1204 argc--;
1205 break;
1206 }
William Lallemand73b85e72017-06-01 17:38:51 +02001207 }
1208 }
William Lallemand73b85e72017-06-01 17:38:51 +02001209 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001210
William Lallemanddf6c5a82020-06-04 17:40:23 +02001211 return retargv;
1212
1213error:
1214 free(retargv);
1215 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001216}
1217
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001218
1219/* Performs basic random seed initialization. The main issue with this is that
1220 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1221 * which means that there will only be 4 billion possible random sequences once
1222 * srandom() is called, regardless of the internal state. Not calling it is
1223 * even worse as we'll always produce the same randoms sequences. What we do
1224 * here is to create an initial sequence from various entropy sources, hash it
1225 * using SHA1 and keep the resulting 160 bits available globally.
1226 *
1227 * We initialize the current process with the first 32 bits before starting the
1228 * polling loop, where all this will be changed to have process specific and
1229 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001230 *
1231 * Before starting threads, it's still possible to call random() as srandom()
1232 * is initialized from this, but after threads and/or processes are started,
1233 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001234 */
1235static void ha_random_boot(char *const *argv)
1236{
1237 unsigned char message[256];
1238 unsigned char *m = message;
1239 struct timeval tv;
1240 blk_SHA_CTX ctx;
1241 unsigned long l;
1242 int fd;
1243 int i;
1244
1245 /* start with current time as pseudo-random seed */
1246 gettimeofday(&tv, NULL);
1247 write_u32(m, tv.tv_sec); m += 4;
1248 write_u32(m, tv.tv_usec); m += 4;
1249
1250 /* PID and PPID add some OS-based randomness */
1251 write_u16(m, getpid()); m += 2;
1252 write_u16(m, getppid()); m += 2;
1253
1254 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1255 fd = open("/dev/urandom", O_RDONLY);
1256 if (fd >= 0) {
1257 i = read(fd, m, 20);
1258 if (i > 0)
1259 m += i;
1260 close(fd);
1261 }
1262
1263 /* take up to 160 bits bytes from openssl (non-blocking) */
1264#ifdef USE_OPENSSL
1265 if (RAND_bytes(m, 20) == 1)
1266 m += 20;
1267#endif
1268
1269 /* take 160 bits from existing random in case it was already initialized */
1270 for (i = 0; i < 5; i++) {
1271 write_u32(m, random());
1272 m += 4;
1273 }
1274
1275 /* stack address (benefit form operating system's ASLR) */
1276 l = (unsigned long)&m;
1277 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1278
1279 /* argv address (benefit form operating system's ASLR) */
1280 l = (unsigned long)&argv;
1281 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1282
1283 /* use tv_usec again after all the operations above */
1284 gettimeofday(&tv, NULL);
1285 write_u32(m, tv.tv_usec); m += 4;
1286
1287 /*
1288 * At this point, ~84-92 bytes have been used
1289 */
1290
1291 /* finish with the hostname */
1292 strncpy((char *)m, hostname, message + sizeof(message) - m);
1293 m += strlen(hostname);
1294
1295 /* total message length */
1296 l = m - message;
1297
1298 memset(&ctx, 0, sizeof(ctx));
1299 blk_SHA1_Init(&ctx);
1300 blk_SHA1_Update(&ctx, message, l);
1301 blk_SHA1_Final(boot_seed, &ctx);
1302
1303 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001304 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001305}
1306
Willy Tarreau5a023f02019-03-01 14:19:31 +01001307/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1308 * setting, and returns it. It may return -1 meaning "unlimited" if some
1309 * unlimited proxies have been found and the global.maxconn value is not yet
1310 * set. It may also return a value greater than maxconn if it's not yet set.
1311 * Note that a value of zero means there is no need for pipes. -1 is never
1312 * returned if global.maxconn is valid.
1313 */
1314static int compute_ideal_maxpipes()
1315{
1316 struct proxy *cur;
1317 int nbfe = 0, nbbe = 0;
1318 int unlimited = 0;
1319 int pipes;
1320 int max;
1321
1322 for (cur = proxies_list; cur; cur = cur->next) {
1323 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1324 if (cur->cap & PR_CAP_FE) {
1325 max = cur->maxconn;
1326 nbfe += max;
1327 if (!max) {
1328 unlimited = 1;
1329 break;
1330 }
1331 }
1332 if (cur->cap & PR_CAP_BE) {
1333 max = cur->fullconn ? cur->fullconn : global.maxconn;
1334 nbbe += max;
1335 if (!max) {
1336 unlimited = 1;
1337 break;
1338 }
1339 }
1340 }
1341 }
1342
1343 pipes = MAX(nbfe, nbbe);
1344 if (global.maxconn) {
1345 if (pipes > global.maxconn || unlimited)
1346 pipes = global.maxconn;
1347 } else if (unlimited) {
1348 pipes = -1;
1349 }
1350
1351 return pipes >= 4 ? pipes / 4 : pipes;
1352}
1353
Willy Tarreauac350932019-03-01 15:43:14 +01001354/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1355 * rlimits and computes an ideal maxconn. It's meant to be called only when
1356 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001357 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1358 * default 100) is returned as it is expected that it will even run on tight
1359 * environments, and will maintain compatibility with previous packages that
1360 * used to rely on this value as the default one. The system will emit a
1361 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001362 */
1363static int compute_ideal_maxconn()
1364{
1365 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1366 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1367 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001368 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001369 int maxconn;
1370
1371 /* we have to take into account these elements :
1372 * - number of engine_fds, which inflates the number of FD needed per
1373 * connection by this number.
1374 * - number of pipes per connection on average : for the unlimited
1375 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1376 * fixed value of 2*pipes.
1377 * - two FDs per connection
1378 */
1379
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02001380 if (global.fd_hard_limit && remain > global.fd_hard_limit)
1381 remain = global.fd_hard_limit;
1382
Willy Tarreauac350932019-03-01 15:43:14 +01001383 /* subtract listeners and checks */
1384 remain -= global.maxsock;
1385
Willy Tarreau3f200852019-03-14 19:13:17 +01001386 /* one epoll_fd/kqueue_fd per thread */
1387 remain -= global.nbthread;
1388
1389 /* one wake-up pipe (2 fd) per thread */
1390 remain -= 2 * global.nbthread;
1391
Willy Tarreauac350932019-03-01 15:43:14 +01001392 /* Fixed pipes values : we only subtract them if they're not larger
1393 * than the remaining FDs because pipes are optional.
1394 */
1395 if (pipes >= 0 && pipes * 2 < remain)
1396 remain -= pipes * 2;
1397
1398 if (pipes < 0) {
1399 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1400 * = maxconn * (2 + 0.5 + engine_fds)
1401 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1402 */
1403 maxconn = 2 * remain / (5 + 2 * engine_fds);
1404 } else {
1405 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1406 * = maxconn * (2 + engine_fds)
1407 */
1408 maxconn = remain / (2 + engine_fds);
1409 }
1410
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001411 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001412}
1413
Willy Tarreaua409f302020-03-10 17:08:53 +01001414/* computes the estimated maxsock value for the given maxconn based on the
1415 * possibly set global.maxpipes and existing partial global.maxsock. It may
1416 * temporarily change global.maxconn for the time needed to propagate the
1417 * computations, and will reset it.
1418 */
1419static int compute_ideal_maxsock(int maxconn)
1420{
1421 int maxpipes = global.maxpipes;
1422 int maxsock = global.maxsock;
1423
1424
1425 if (!maxpipes) {
1426 int old_maxconn = global.maxconn;
1427
1428 global.maxconn = maxconn;
1429 maxpipes = compute_ideal_maxpipes();
1430 global.maxconn = old_maxconn;
1431 }
1432
1433 maxsock += maxconn * 2; /* each connection needs two sockets */
1434 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1435 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1436 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1437
1438 /* compute fd used by async engines */
1439 if (global.ssl_used_async_engines) {
1440 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1441
1442 maxsock += maxconn * sides * global.ssl_used_async_engines;
1443 }
1444 return maxsock;
1445}
1446
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001447/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001448 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1449 * value is accepted, non-zero otherwise. This is used to determine if an
1450 * automatic limit may be applied or not. When it is not, the caller knows that
1451 * the highest we can do is the rlim_max at boot. In case of error, we return
1452 * that the setting is possible, so that we defer the error processing to the
1453 * final stage in charge of enforcing this.
1454 */
1455static int check_if_maxsock_permitted(int maxsock)
1456{
1457 struct rlimit orig_limit, test_limit;
1458 int ret;
1459
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02001460 if (global.fd_hard_limit && maxsock > global.fd_hard_limit)
1461 return 0;
1462
Willy Tarreau304e17e2020-03-10 17:54:54 +01001463 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1464 return 1;
1465
1466 /* don't go further if we can't even set to what we have */
Willy Tarreauc06557c2022-09-22 16:12:08 +02001467 if (raise_rlim_nofile(NULL, &orig_limit) != 0)
Willy Tarreau304e17e2020-03-10 17:54:54 +01001468 return 1;
1469
1470 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1471 test_limit.rlim_cur = test_limit.rlim_max;
Willy Tarreauc06557c2022-09-22 16:12:08 +02001472 ret = raise_rlim_nofile(NULL, &test_limit);
Willy Tarreau304e17e2020-03-10 17:54:54 +01001473
Willy Tarreauc06557c2022-09-22 16:12:08 +02001474 if (raise_rlim_nofile(NULL, &orig_limit) != 0)
Willy Tarreau304e17e2020-03-10 17:54:54 +01001475 return 1;
1476
1477 return ret == 0;
1478}
1479
Willy Tarreau34527d52022-02-17 17:45:58 +01001480/* This performs th every basic early initialization at the end of the PREPARE
1481 * init stage. It may only assume that list heads are initialized, but not that
1482 * anything else is correct. It will initialize a number of variables that
1483 * depend on command line and will pre-parse the command line. If it fails, it
1484 * directly exits.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001485 */
Willy Tarreau34527d52022-02-17 17:45:58 +01001486static void init_early(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001487{
Kevinm48936af2010-12-22 16:08:21 +00001488 char *progname;
Willy Tarreau34527d52022-02-17 17:45:58 +01001489 char *tmp;
1490 int len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001491
Willy Tarreau34527d52022-02-17 17:45:58 +01001492 /* First, let's initialize most global variables */
1493 totalconn = actconn = listeners = stopping = 0;
1494 killed = pid = 0;
1495
1496 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
1497 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Christopher Faulete3a5e352017-10-24 13:53:54 +02001498 global.mode = MODE_STARTING;
William Lallemand73b85e72017-06-01 17:38:51 +02001499
Willy Tarreau34527d52022-02-17 17:45:58 +01001500 /* if we were in mworker mode, we should restart in mworker mode */
1501 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1502 global.mode |= MODE_MWORKER;
David du Colombier7af46052012-05-16 14:16:48 +02001503
Willy Tarreau34527d52022-02-17 17:45:58 +01001504 /* initialize date, time, and pid */
1505 tzset();
1506 clock_init_process_date();
1507 start_date = now;
1508 pid = getpid();
1509
1510 /* Set local host name and adjust some environment variables.
1511 * NB: POSIX does not make it mandatory for gethostname() to
1512 * NULL-terminate the string in case of truncation, and at least
1513 * FreeBSD appears not to do it.
Emeric Brun2b920a12010-09-23 18:30:22 +02001514 */
1515 memset(hostname, 0, sizeof(hostname));
1516 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001517
Willy Tarreau34527d52022-02-17 17:45:58 +01001518 /* preset some environment variables */
1519 localpeer = strdup(hostname);
1520 if (!localpeer || setenv("HAPROXY_LOCALPEER", localpeer, 1) < 0) {
Dragan Dosen4f014152020-06-18 16:56:47 +02001521 ha_alert("Cannot allocate memory for local peer.\n");
1522 exit(EXIT_FAILURE);
1523 }
Emeric Brun2b920a12010-09-23 18:30:22 +02001524
Willy Tarreau34527d52022-02-17 17:45:58 +01001525 /* Some CPU affinity stuff may have to be initialized */
1526#ifdef USE_CPU_AFFINITY
1527 {
Willy Tarreau5b093412022-07-08 09:38:30 +02001528 int g, i;
1529
1530 for (g = 0; g < MAX_TGROUPS; g++) {
1531 ha_cpuset_zero(&cpu_map[g].proc);
1532 ha_cpuset_zero(&cpu_map[g].proc_t1);
1533 for (i = 0; i < MAX_THREADS_PER_GROUP; ++i) {
1534 ha_cpuset_zero(&cpu_map[g].thread[i]);
1535 }
Willy Tarreau34527d52022-02-17 17:45:58 +01001536 }
1537 }
1538#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001539
Willy Tarreau34527d52022-02-17 17:45:58 +01001540 /* extract the program name from argv[0], it will be used for the logs
1541 * and error messages.
1542 */
1543 progname = *argv;
1544 while ((tmp = strchr(progname, '/')) != NULL)
1545 progname = tmp + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001546
Willy Tarreau34527d52022-02-17 17:45:58 +01001547 len = strlen(progname);
1548 progname = strdup(progname);
1549 if (!progname) {
1550 ha_alert("Cannot allocate memory for log_tag.\n");
1551 exit(EXIT_FAILURE);
1552 }
Willy Tarreau84310e22014-02-14 11:59:04 +01001553
Willy Tarreau34527d52022-02-17 17:45:58 +01001554 chunk_initlen(&global.log_tag, progname, len, len);
1555}
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001556
Willy Tarreau392524d2022-02-17 18:10:36 +01001557/* handles program arguments. Very minimal parsing is performed, variables are
1558 * fed with some values, and lists are completed with other ones. In case of
1559 * error, it will exit.
Willy Tarreau34527d52022-02-17 17:45:58 +01001560 */
Willy Tarreau392524d2022-02-17 18:10:36 +01001561static void init_args(int argc, char **argv)
Willy Tarreau34527d52022-02-17 17:45:58 +01001562{
Willy Tarreau34527d52022-02-17 17:45:58 +01001563 char *progname = global.log_tag.area;
Willy Tarreau392524d2022-02-17 18:10:36 +01001564 char *err_msg = NULL;
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001565
Willy Tarreau34527d52022-02-17 17:45:58 +01001566 /* pre-fill in the global tuning options before we let the cmdline
1567 * change them.
1568 */
Willy Tarreau43b78992009-01-25 15:42:27 +01001569 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001570#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001571 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001572#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001573#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001574 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001575#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001576#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001577 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001578#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001579#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001580 global.tune.options |= GTUNE_USE_EVPORTS;
1581#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001582#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001583 global.tune.options |= GTUNE_USE_SPLICE;
1584#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001585#if defined(USE_GETADDRINFO)
1586 global.tune.options |= GTUNE_USE_GAI;
1587#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001588#if defined(SO_REUSEPORT)
1589 global.tune.options |= GTUNE_USE_REUSEPORT;
1590#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001591#ifdef USE_THREAD
1592 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1593#endif
Amaury Denoyellee30f3782022-11-21 11:54:13 +01001594#ifdef USE_QUIC
1595 global.tune.options |= GTUNE_QUIC_SOCK_PER_CONN;
1596#endif
William Dauchya5194602020-03-28 19:29:58 +01001597 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598
Willy Tarreau392524d2022-02-17 18:10:36 +01001599 /* keep a copy of original arguments for the master process */
1600 old_argv = copy_argv(argc, argv);
1601 if (!old_argv) {
1602 ha_alert("failed to copy argv.\n");
1603 exit(EXIT_FAILURE);
1604 }
1605
1606 /* skip program name and start */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607 argc--; argv++;
1608 while (argc > 0) {
1609 char *flag;
1610
1611 if (**argv == '-') {
1612 flag = *argv+1;
1613
1614 /* 1 arg */
1615 if (*flag == 'v') {
1616 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001617 if (flag[1] == 'v') /* -vv */
1618 display_build_opts();
Tim Duesterhus77b3db02022-04-27 00:08:11 +02001619 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001621#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001623 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001624#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001625#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001626 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001627 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001628#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001629#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001630 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001631 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001632#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001633#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001634 else if (*flag == 'd' && flag[1] == 'v')
1635 global.tune.options &= ~GTUNE_USE_EVPORTS;
1636#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001637#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001638 else if (*flag == 'd' && flag[1] == 'S')
1639 global.tune.options &= ~GTUNE_USE_SPLICE;
1640#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001641#if defined(USE_GETADDRINFO)
1642 else if (*flag == 'd' && flag[1] == 'G')
1643 global.tune.options &= ~GTUNE_USE_GAI;
1644#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001645#if defined(SO_REUSEPORT)
1646 else if (*flag == 'd' && flag[1] == 'R')
1647 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1648#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001649 else if (*flag == 'd' && flag[1] == 'V')
1650 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001651 else if (*flag == 'V')
1652 arg_mode |= MODE_VERBOSE;
Erwan Le Goasb0c05012022-09-14 17:51:55 +02001653 else if (*flag == 'd' && flag[1] == 'C') {
Erwan Le Goasf30c5d72022-09-29 10:34:04 +02001654 char *end;
1655 char *key;
1656
1657 key = flag + 2;
1658 for (;key && *key; key = end) {
1659 end = strchr(key, ',');
1660 if (end)
1661 *(end++) = 0;
1662
1663 if (strcmp(key, "line") == 0)
1664 arg_mode |= MODE_DUMP_NB_L;
1665
1666 }
Erwan Le Goasb0c05012022-09-14 17:51:55 +02001667 arg_mode |= MODE_DUMP_CFG;
1668 HA_ATOMIC_STORE(&global.anon_key, atoll(flag + 2));
1669 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001670 else if (*flag == 'd' && flag[1] == 'b')
1671 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001672 else if (*flag == 'd' && flag[1] == 'D')
1673 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001674 else if (*flag == 'd' && flag[1] == 'W')
1675 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreauef301b72022-02-23 14:15:18 +01001676 else if (*flag == 'd' && flag[1] == 'M') {
Willy Tarreau1408b1f2022-02-18 18:54:40 +01001677 int ret = pool_parse_debugging(flag + 2, &err_msg);
1678
1679 if (ret <= -1) {
1680 if (ret < -1)
1681 ha_alert("-dM: %s\n", err_msg);
1682 else
1683 printf("%s\n", err_msg);
1684 ha_free(&err_msg);
1685 exit(ret < -1 ? EXIT_FAILURE : 0);
1686 } else if (ret == 0) {
1687 ha_warning("-dM: %s\n", err_msg);
1688 ha_free(&err_msg);
1689 }
Willy Tarreauef301b72022-02-23 14:15:18 +01001690 }
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001691 else if (*flag == 'd' && flag[1] == 'r')
1692 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreau654726d2021-12-28 15:43:11 +01001693#if defined(HA_HAVE_DUMP_LIBS)
1694 else if (*flag == 'd' && flag[1] == 'L')
1695 arg_mode |= MODE_DUMP_LIBS;
1696#endif
Willy Tarreau76871a42022-03-08 16:01:40 +01001697 else if (*flag == 'd' && flag[1] == 'K') {
1698 arg_mode |= MODE_DUMP_KWD;
1699 kwd_dump = flag + 2;
1700 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001701 else if (*flag == 'd')
1702 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001703 else if (*flag == 'c' && flag[1] == 'c') {
1704 arg_mode |= MODE_CHECK_CONDITION;
1705 argv++;
1706 argc--;
1707 check_condition = *argv;
1708 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001709 else if (*flag == 'c')
1710 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001711 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001712 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001713 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001714 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001715#if defined(USE_SYSTEMD)
1716 global.tune.options |= GTUNE_USE_SYSTEMD;
1717#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001718 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 +01001719 usage(progname);
1720#endif
1721 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001722 else if (*flag == 'W')
1723 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001724 else if (*flag == 'q')
1725 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001726 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001727 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001728 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001729 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001730 }
William Lallemand4fc09692017-06-19 16:37:19 +02001731 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001732 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001733 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001734
Olivier Houchardf73629d2017-04-05 22:33:04 +02001735 argv++;
1736 argc--;
1737 }
William Lallemande7361152018-10-26 14:47:36 +02001738 else if (*flag == 'S') {
1739 struct wordlist *c;
1740
William Lallemanda6b32492020-06-04 23:49:20 +02001741 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001742 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1743 usage(progname);
1744 }
1745 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1746 ha_alert("Cannot allocate memory\n");
1747 exit(EXIT_FAILURE);
1748 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001749 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001750
1751 argv++;
1752 argc--;
1753 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1755 /* list of pids to finish ('f') or terminate ('t') */
1756
1757 if (flag[1] == 'f')
1758 oldpids_sig = SIGUSR1; /* finish then exit */
1759 else
1760 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001761 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001762 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001763 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1764 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001765 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001766 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001767 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001768 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001769 errno = 0;
1770 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1771 if (errno) {
1772 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1773 flag,
1774 *argv, strerror(errno));
1775 exit(1);
1776 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001777 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001778 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001779 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1780 flag, endptr);
1781 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001782 }
Chris Lane236062f2018-02-05 23:15:44 +00001783 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001784 if (oldpids[nb_oldpids] <= 0)
1785 usage(progname);
1786 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001787 }
1788 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001789 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1790 /* now that's a cfgfile list */
1791 argv++; argc--;
1792 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001793 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001794 ha_alert("Cannot load configuration file/directory %s : %s\n",
1795 *argv,
1796 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001797 exit(1);
1798 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001799 argv++; argc--;
1800 }
1801 break;
1802 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001803 else { /* >=2 args */
1804 argv++; argc--;
1805 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001806 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001807
1808 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001809 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001810 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001811 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001812 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001813 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001814 free(localpeer);
1815 if ((localpeer = strdup(*argv)) == NULL) {
1816 ha_alert("Cannot allocate memory for local peer.\n");
1817 exit(EXIT_FAILURE);
1818 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001819 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001820 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001821 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001822 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001823 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001824 ha_alert("Cannot load configuration file/directory %s : %s\n",
1825 *argv,
1826 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001827 exit(1);
1828 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001829 break;
Willy Tarreau392524d2022-02-17 18:10:36 +01001830 case 'p' :
1831 free(global.pidfile);
1832 if ((global.pidfile = strdup(*argv)) == NULL) {
1833 ha_alert("Cannot allocate memory for pidfile.\n");
1834 exit(EXIT_FAILURE);
1835 }
1836 break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001837 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001838 }
1839 }
1840 }
1841 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001842 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001843 argv++; argc--;
1844 }
Willy Tarreau392524d2022-02-17 18:10:36 +01001845 free(err_msg);
1846}
1847
Willy Tarreau76871a42022-03-08 16:01:40 +01001848/* call the various keyword dump functions based on the comma-delimited list of
1849 * classes in kwd_dump.
1850 */
1851static void dump_registered_keywords(void)
1852{
1853 char *end;
1854 int all __maybe_unused = 0;
1855
1856 for (; kwd_dump && *kwd_dump; kwd_dump = end) {
1857 end = strchr(kwd_dump, ',');
1858 if (end)
1859 *(end++) = 0;
1860
1861 if (strcmp(kwd_dump, "help") == 0) {
1862 printf("# List of supported keyword classes:\n");
1863 printf("all: list all keywords\n");
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001864 printf("acl: ACL keywords\n");
Willy Tarreauca1acd62022-03-29 15:02:44 +02001865 printf("cfg: configuration keywords\n");
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001866 printf("cli: CLI keywords\n");
Willy Tarreau29d799d2022-03-29 16:59:49 +02001867 printf("cnv: sample converter keywords\n");
Willy Tarreau3b65e142022-03-29 15:03:09 +02001868 printf("flt: filter names\n");
Willy Tarreauf78813f2022-03-29 16:51:29 +02001869 printf("smp: sample fetch functions\n");
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001870 printf("svc: service names\n");
Willy Tarreau76871a42022-03-08 16:01:40 +01001871 continue;
1872 }
1873 else if (strcmp(kwd_dump, "all") == 0) {
1874 all = 1;
1875 }
Willy Tarreauca1acd62022-03-29 15:02:44 +02001876
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001877 if (all || strcmp(kwd_dump, "acl") == 0) {
1878 printf("# List of registered ACL keywords:\n");
1879 acl_dump_kwd();
1880 }
1881
Willy Tarreauca1acd62022-03-29 15:02:44 +02001882 if (all || strcmp(kwd_dump, "cfg") == 0) {
1883 printf("# List of registered configuration keywords:\n");
1884 cfg_dump_registered_keywords();
1885 }
Willy Tarreau3b65e142022-03-29 15:03:09 +02001886
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001887 if (all || strcmp(kwd_dump, "cli") == 0) {
1888 printf("# List of registered CLI keywords:\n");
1889 cli_list_keywords();
1890 }
1891
Willy Tarreau29d799d2022-03-29 16:59:49 +02001892 if (all || strcmp(kwd_dump, "cnv") == 0) {
1893 printf("# List of registered sample converter functions:\n");
1894 smp_dump_conv_kw();
1895 }
1896
Willy Tarreau3b65e142022-03-29 15:03:09 +02001897 if (all || strcmp(kwd_dump, "flt") == 0) {
1898 printf("# List of registered filter names:\n");
1899 flt_dump_kws(NULL);
1900 }
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001901
Willy Tarreauf78813f2022-03-29 16:51:29 +02001902 if (all || strcmp(kwd_dump, "smp") == 0) {
1903 printf("# List of registered sample fetch functions:\n");
1904 smp_dump_fetch_kw();
1905 }
1906
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001907 if (all || strcmp(kwd_dump, "svc") == 0) {
1908 printf("# List of registered service names:\n");
1909 list_services(NULL);
1910 }
Willy Tarreau76871a42022-03-08 16:01:40 +01001911 }
1912}
1913
Amaury Denoyelle28ea31c2022-11-14 16:18:46 +01001914/* Generate a random cluster-secret in case the setting is not provided in the
1915 * configuration. This allows to use features which rely on it albeit with some
1916 * limitations.
1917 */
1918static void generate_random_cluster_secret()
1919{
1920 /* used as a default random cluster-secret if none defined. */
1921 uint64_t rand = ha_random64();
1922
1923 /* The caller must not overwrite an already defined secret. */
1924 BUG_ON(global.cluster_secret);
1925
1926 global.cluster_secret = malloc(8);
1927 if (!global.cluster_secret)
1928 return;
1929
1930 memcpy(global.cluster_secret, &rand, sizeof(rand));
1931 global.cluster_secret[7] = '\0';
1932}
1933
Willy Tarreau392524d2022-02-17 18:10:36 +01001934/*
1935 * This function initializes all the necessary variables. It only returns
1936 * if everything is OK. If something fails, it exits.
1937 */
1938static void init(int argc, char **argv)
1939{
1940 char *progname = global.log_tag.area;
1941 int err_code = 0;
1942 struct wordlist *wl;
1943 struct proxy *px;
1944 struct post_check_fct *pcf;
William Lallemandb53eb872022-04-21 18:02:53 +02001945 struct pre_check_fct *prcf;
Willy Tarreau392524d2022-02-17 18:10:36 +01001946 int ideal_maxconn;
1947
William Lallemand151dbbe2022-12-02 17:17:43 +01001948#ifdef USE_OPENSSL
1949#ifdef USE_OPENSSL_WOLFSSL
1950 wolfSSL_Init();
1951 wolfSSL_Debugging_ON();
1952#endif
1953#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
William Lallemand44c80ce2022-12-02 17:06:59 +01001954 /* Initialize the error strings of OpenSSL
1955 * It only needs to be done explicitly with older versions of the SSL
1956 * library. On newer versions, errors strings are loaded during start
1957 * up. */
1958 SSL_load_error_strings();
1959#endif
William Lallemand151dbbe2022-12-02 17:17:43 +01001960#endif
William Lallemand44c80ce2022-12-02 17:06:59 +01001961
William Lallemandeba6a542022-09-26 12:54:39 +02001962 startup_logs_init();
1963
Willy Tarreau392524d2022-02-17 18:10:36 +01001964 if (!init_trash_buffers(1)) {
1965 ha_alert("failed to initialize trash buffers.\n");
1966 exit(1);
1967 }
1968
1969 if (init_acl() != 0)
1970 exit(1);
1971
1972 /* Initialise lua. */
1973 hlua_init();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001974
Christopher Faulete3a5e352017-10-24 13:53:54 +02001975 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001976 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Erwan Le Goasf30c5d72022-09-29 10:34:04 +02001977 | MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS | MODE_DUMP_KWD
1978 | MODE_DUMP_CFG | MODE_DUMP_NB_L));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001979
William Lallemand944e6192018-11-21 15:48:31 +01001980 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001981 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001982 global.mode |= MODE_MWORKER_WAIT;
1983 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001984 }
1985
William Lallemand40db4ae2022-12-07 15:03:55 +01001986 /* set the atexit functions when not doing configuration check */
1987 if (!(global.mode & (MODE_CHECK | MODE_CHECK_CONDITION))
1988 && (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
1989
1990 if (global.mode & MODE_MWORKER) {
1991 atexit_flag = 1;
1992 atexit(reexec_on_failure);
1993 } else if (global.mode & MODE_MWORKER_WAIT) {
1994 atexit_flag = 1;
1995 atexit(exit_on_waitmode_failure);
1996 }
William Lallemandcb11fd22017-06-01 17:38:52 +02001997 }
1998
Willy Tarreau576132e2011-09-10 19:26:56 +02001999 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002000 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02002001 exit(1);
2002 }
2003
Amaury Denoyelle11124302021-06-04 18:22:08 +02002004 usermsgs_clr("config");
2005
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002006 if (global.mode & MODE_CHECK_CONDITION) {
2007 int result;
2008
2009 uint32_t err;
2010 const char *errptr;
2011 char *errmsg = NULL;
2012
2013 char *args[MAX_LINE_ARGS+1];
2014 int arg = sizeof(args) / sizeof(*args);
William Lallemand89e236f2022-05-06 17:22:36 +02002015 size_t outlen;
Willy Tarreauc8194c32021-07-16 16:38:58 +02002016 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002017
William Lallemand89e236f2022-05-06 17:22:36 +02002018 if (!check_condition)
2019 usage(progname);
2020
2021 outlen = strlen(check_condition) + 1;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002022 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02002023 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002024 &errptr);
2025
2026 if (err & PARSE_ERR_QUOTE) {
2027 ha_alert("Syntax Error in condition: Unmatched quote.\n");
2028 exit(2);
2029 }
2030
2031 if (err & PARSE_ERR_HEX) {
2032 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
2033 exit(2);
2034 }
2035
2036 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
2037 ha_alert("Error in condition: Line too long.\n");
2038 exit(2);
2039 }
2040
Willy Tarreauc8194c32021-07-16 16:38:58 +02002041 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002042 ha_alert("Error in condition: Too many words.\n");
2043 exit(2);
2044 }
2045
2046 if (err) {
2047 ha_alert("Unhandled error in condition, please report this to the developers.\n");
2048 exit(2);
2049 }
2050
Willy Tarreauc8194c32021-07-16 16:38:58 +02002051 /* remerge all words into a single expression */
2052 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
2053 ;
2054
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002055 result = cfg_eval_condition(args, &errmsg, &errptr);
2056
2057 if (result < 0) {
2058 if (errmsg)
2059 ha_alert("Failed to evaluate condition: %s\n", errmsg);
2060
2061 exit(2);
2062 }
2063
2064 exit(result ? 0 : 1);
2065 }
2066
William Lallemand944e6192018-11-21 15:48:31 +01002067 /* in wait mode, we don't try to read the configuration files */
2068 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01002069 char *env_cfgfiles = NULL;
2070 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01002071
William Lallemand944e6192018-11-21 15:48:31 +01002072 /* handle cfgfiles that are actually directories */
2073 cfgfiles_expand_directories();
2074
2075 if (LIST_ISEMPTY(&cfg_cfgfiles))
2076 usage(progname);
2077
Sébastien Gross537b9e72022-11-30 22:36:50 +01002078 /* temporary create environment variables with default
2079 * values to ease user configuration. Do not forget to
2080 * unset them after the list_for_each_entry loop.
2081 */
2082 setenv("HAPROXY_HTTP_LOG_FMT", default_http_log_format, 1);
2083 setenv("HAPROXY_HTTPS_LOG_FMT", default_https_log_format, 1);
2084 setenv("HAPROXY_TCP_LOG_FMT", default_tcp_log_format, 1);
William Lallemand944e6192018-11-21 15:48:31 +01002085 list_for_each_entry(wl, &cfg_cfgfiles, list) {
2086 int ret;
2087
Christopher Faulet4e366822021-01-12 18:57:38 +01002088 if (env_err == 0) {
2089 if (!memprintf(&env_cfgfiles, "%s%s%s",
2090 (env_cfgfiles ? env_cfgfiles : ""),
2091 (env_cfgfiles ? ";" : ""), wl->s))
2092 env_err = 1;
2093 }
William Lallemand7b302d82019-05-20 11:15:37 +02002094
William Lallemand944e6192018-11-21 15:48:31 +01002095 ret = readcfgfile(wl->s);
2096 if (ret == -1) {
2097 ha_alert("Could not open configuration file %s : %s\n",
2098 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01002099 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002100 exit(1);
2101 }
2102 if (ret & (ERR_ABORT|ERR_FATAL))
2103 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
2104 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01002105 if (err_code & ERR_ABORT) {
2106 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002107 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01002108 }
Willy Tarreauc4382422009-12-06 13:10:44 +01002109 }
Sébastien Gross537b9e72022-11-30 22:36:50 +01002110 /* remove temporary environment variables. */
2111 unsetenv("HAPROXY_HTTP_LOG_FMT");
2112 unsetenv("HAPROXY_HTTPS_LOG_FMT");
2113 unsetenv("HAPROXY_TCP_LOG_FMT");
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02002114
William Lallemand944e6192018-11-21 15:48:31 +01002115 /* do not try to resolve arguments nor to spot inconsistencies when
2116 * the configuration contains fatal errors caused by files not found
2117 * or failed memory allocations.
2118 */
2119 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2120 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01002121 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002122 exit(1);
2123 }
Christopher Faulet4e366822021-01-12 18:57:38 +01002124 if (env_err) {
2125 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
2126 exit(1);
2127 }
2128 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
2129 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02002130
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02002131 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002132 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01002133 struct mworker_proc *tmproc;
2134
William Lallemand482f9a92019-04-12 16:15:00 +02002135 setenv("HAPROXY_MWORKER", "1", 1);
2136
William Lallemand16dd1b32018-11-19 18:46:18 +01002137 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
2138
William Lallemand56be0e02022-01-28 21:11:41 +01002139 tmproc = mworker_proc_new();
William Lallemand16dd1b32018-11-19 18:46:18 +01002140 if (!tmproc) {
2141 ha_alert("Cannot allocate process structures.\n");
2142 exit(EXIT_FAILURE);
2143 }
William Lallemand8f7069a2019-04-12 16:09:23 +02002144 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01002145 tmproc->pid = pid;
2146 tmproc->timestamp = start_date.tv_sec;
William Lallemand16dd1b32018-11-19 18:46:18 +01002147 proc_self = tmproc;
2148
Willy Tarreau2b718102021-04-21 07:32:39 +02002149 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01002150 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002151
William Lallemand56be0e02022-01-28 21:11:41 +01002152 tmproc = mworker_proc_new();
Willy Tarreau6185a032021-06-15 08:02:06 +02002153 if (!tmproc) {
2154 ha_alert("Cannot allocate process structures.\n");
2155 exit(EXIT_FAILURE);
2156 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002157 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
William Lallemandce83b4a2018-10-26 14:47:30 +02002158
Willy Tarreau6185a032021-06-15 08:02:06 +02002159 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
2160 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02002161 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002162
2163 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01002164 }
Willy Tarreau53bfac82022-07-22 17:35:49 +02002165
2166 if (global.mode & MODE_MWORKER_WAIT) {
2167 /* in exec mode, there's always exactly one thread. Failure to
2168 * set these ones now will result in nbthread being detected
2169 * automatically.
2170 */
2171 global.nbtgroups = 1;
2172 global.nbthread = 1;
2173 }
2174
William Lallemand944e6192018-11-21 15:48:31 +01002175 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
2176 struct wordlist *it, *c;
2177
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02002178 /* get the info of the children in the env */
2179 if (mworker_env_to_proc_list() < 0) {
2180 exit(EXIT_FAILURE);
2181 }
William Lallemande7361152018-10-26 14:47:36 +02002182
William Lallemand550db6d2018-11-06 17:37:12 +01002183 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemandec059c22022-09-22 17:26:23 +02002184 char *path = NULL;
William Lallemande7361152018-10-26 14:47:36 +02002185
William Lallemand550db6d2018-11-06 17:37:12 +01002186 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02002187 ha_alert("Can't create the master's CLI.\n");
2188 exit(EXIT_FAILURE);
2189 }
William Lallemande7361152018-10-26 14:47:36 +02002190
William Lallemand550db6d2018-11-06 17:37:12 +01002191 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
2192
William Lallemand21623b52022-09-24 15:51:27 +02002193 if (mworker_cli_proxy_new_listener(c->s) == NULL) {
William Lallemand550db6d2018-11-06 17:37:12 +01002194 ha_alert("Can't create the master's CLI.\n");
2195 exit(EXIT_FAILURE);
2196 }
Willy Tarreau2b718102021-04-21 07:32:39 +02002197 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01002198 free(c->s);
2199 free(c);
2200 }
William Lallemande57b7022022-12-07 14:25:41 +01002201 /* Creates the mcli_reload listener, which is the listener used
2202 * to retrieve the master CLI session which asked for the reload.
2203 *
2204 * ipc_fd[1] will be used as a listener, and ipc_fd[0]
2205 * will be used to send the FD of the session.
2206 *
2207 * Both FDs will be kept in the master. The sockets are
2208 * created only if they weren't inherited.
2209 */
2210 if ((proc_self->ipc_fd[1] == -1) &&
2211 socketpair(AF_UNIX, SOCK_STREAM, 0, proc_self->ipc_fd) < 0) {
2212 ha_alert("cannot create the mcli_reload socketpair.\n");
2213 exit(EXIT_FAILURE);
2214 }
2215
William Lallemandec059c22022-09-22 17:26:23 +02002216 /* Create the mcli_reload listener from the proc_self struct */
2217 memprintf(&path, "sockpair@%d", proc_self->ipc_fd[1]);
William Lallemand56f73b22022-09-24 15:56:25 +02002218 mcli_reload_bind_conf = mworker_cli_proxy_new_listener(path);
2219 if (mcli_reload_bind_conf == NULL) {
William Lallemandec059c22022-09-22 17:26:23 +02002220 ha_alert("Cannot create the mcli_reload listener.\n");
2221 exit(EXIT_FAILURE);
2222 }
2223 ha_free(&path);
William Lallemand550db6d2018-11-06 17:37:12 +01002224 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002225 }
2226
Eric Salama5ba83352021-03-16 15:11:17 +01002227 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
2228 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
2229 }
2230
Christopher Faulet27c8d202021-10-13 09:50:53 +02002231 /* destroy unreferenced defaults proxies */
2232 proxy_destroy_all_unref_defaults();
2233
William Lallemandb53eb872022-04-21 18:02:53 +02002234 list_for_each_entry(prcf, &pre_check_list, list)
2235 err_code |= prcf->fct();
Willy Tarreaue90904d2021-02-12 14:08:31 +01002236
William Lallemand8b9a2df2022-05-04 14:29:46 +02002237 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2238 ha_alert("Fatal errors found in configuration.\n");
2239 exit(1);
2240 }
2241
Willy Tarreau57c3e752022-12-08 08:13:20 +01002242 /* Note: global.nbthread will be initialized as part of this call */
Willy Tarreaubb925012009-07-23 13:36:36 +02002243 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02002244 for (px = proxies_list; px; px = px->next) {
2245 struct server *srv;
2246 struct post_proxy_check_fct *ppcf;
2247 struct post_server_check_fct *pscf;
2248
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002249 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002250 continue;
2251
Christopher Fauletc1692962019-08-12 09:51:07 +02002252 list_for_each_entry(pscf, &post_server_check_list, list) {
2253 for (srv = px->srv; srv; srv = srv->next)
2254 err_code |= pscf->fct(srv);
2255 }
2256 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2257 err_code |= ppcf->fct(px);
2258 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002259 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002260 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002261 exit(1);
2262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002263
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002264 err_code |= pattern_finalize_config();
2265 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2266 ha_alert("Failed to finalize pattern config.\n");
2267 exit(1);
2268 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002269
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002270 if (global.rlimit_memmax_all)
2271 global.rlimit_memmax = global.rlimit_memmax_all;
2272
Willy Tarreaue5733232019-05-22 19:24:06 +02002273#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002274 err_code |= netns_init();
2275 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002276 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002277 exit(1);
2278 }
2279#endif
2280
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002281 /* Apply server states */
2282 apply_server_state();
2283
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002284 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002285 srv_compute_all_admin_states(px);
2286
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002287 /* Apply servers' configured address */
2288 err_code |= srv_init_addr();
2289 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002290 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002291 exit(1);
2292 }
2293
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002294 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2295 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2296 exit(1);
2297 }
2298
Willy Tarreau654726d2021-12-28 15:43:11 +01002299#if defined(HA_HAVE_DUMP_LIBS)
2300 if (global.mode & MODE_DUMP_LIBS) {
2301 qfprintf(stdout, "List of loaded object files:\n");
2302 chunk_reset(&trash);
2303 if (dump_libs(&trash, 0))
2304 printf("%s", trash.area);
2305 }
2306#endif
2307
Willy Tarreau76871a42022-03-08 16:01:40 +01002308 if (global.mode & MODE_DUMP_KWD)
2309 dump_registered_keywords();
2310
Willy Tarreaubaaee002006-06-26 02:48:02 +02002311 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002312 struct peers *pr;
2313 struct proxy *px;
2314
Willy Tarreaubebd2122020-04-15 16:06:11 +02002315 if (warned & WARN_ANY)
2316 qfprintf(stdout, "Warnings were found.\n");
2317
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002318 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002319 if (pr->peers_fe)
2320 break;
2321
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002322 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002323 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002324 break;
2325
Emeric Brunbc5c8212021-08-13 09:32:50 +02002326 if (!px) {
2327 /* We may only have log-forward section */
2328 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002329 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002330 break;
2331 }
2332
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002333 if (pr || px) {
2334 /* At least one peer or one listener has been found */
2335 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002336 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002337 }
2338 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2339 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002341
Erwan Le Goasb0c05012022-09-14 17:51:55 +02002342 if (global.mode & MODE_DUMP_CFG)
2343 deinit_and_exit(0);
2344
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002345 if (global.mode & MODE_DIAG) {
2346 cfg_run_diagnostics();
2347 }
2348
Remi Tricot-Le Breton51944462022-05-16 16:24:31 +02002349#ifdef USE_OPENSSL
William Lallemand3b8bafd2022-07-19 18:13:29 +02002350
Remi Tricot-Le Breton51944462022-05-16 16:24:31 +02002351 /* Initialize SSL random generator. Must be called before chroot for
2352 * access to /dev/urandom, and before ha_random_boot() which may use
2353 * RAND_bytes().
2354 */
2355 if (!ssl_initialize_random()) {
2356 ha_alert("OpenSSL random data generator initialization failed.\n");
2357 exit(EXIT_FAILURE);
2358 }
2359#endif
2360 ha_random_boot(argv); // the argv pointer brings some kernel-fed entropy
2361
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002362 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002363 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002364
Willy Tarreaue6945732016-12-21 19:57:00 +01002365 list_for_each_entry(pcf, &post_check_list, list) {
2366 err_code |= pcf->fct();
2367 if (err_code & (ERR_ABORT|ERR_FATAL))
2368 exit(1);
2369 }
2370
William Lallemand0a012aa2022-06-21 11:11:50 +02002371 /* set the default maxconn in the master, but let it be rewritable with -n */
2372 if (global.mode & MODE_MWORKER_WAIT)
2373 global.maxconn = DEFAULT_MAXCONN;
2374
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 if (cfg_maxconn > 0)
2376 global.maxconn = cfg_maxconn;
2377
Willy Tarreau4975d142021-03-13 11:00:33 +01002378 if (global.cli_fe)
2379 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002380
2381 if (cfg_peers) {
2382 /* peers also need to bypass global maxconn */
2383 struct peers *p = cfg_peers;
2384
2385 for (p = cfg_peers; p; p = p->next)
2386 if (p->peers_fe)
2387 global.maxsock += p->peers_fe->maxconn;
2388 }
2389
Willy Tarreaud0256482015-01-15 21:45:22 +01002390 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002391 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2392 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2393 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2394 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002395 *
2396 * If memmax is set, then it depends on which values are set. If
2397 * maxsslconn is set, we use memmax to determine how many cleartext
2398 * connections may be added, and set maxconn to the sum of the two.
2399 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2400 * the remaining amount of memory between memmax and the cleartext
2401 * connections. If neither are set, then it is considered that all
2402 * connections are SSL-capable, and maxconn is computed based on this,
2403 * then maxsslconn accordingly. We need to know if SSL is used on the
2404 * frontends, backends, or both, because when it's used on both sides,
2405 * we need twice the value for maxsslconn, but we only count the
2406 * handshake once since it is not performed on the two sides at the
2407 * same time (frontend-side is terminated before backend-side begins).
2408 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002409 * ssl_handshake_cost during its initialization. In any case, if
2410 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2411 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002412 */
Willy Tarreauac350932019-03-01 15:43:14 +01002413 ideal_maxconn = compute_ideal_maxconn();
2414
Willy Tarreaud0256482015-01-15 21:45:22 +01002415 if (!global.rlimit_memmax) {
2416 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002417 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002418 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2419 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2420 }
2421 }
2422#ifdef USE_OPENSSL
2423 else if (!global.maxconn && !global.maxsslconn &&
2424 (global.ssl_used_frontend || global.ssl_used_backend)) {
2425 /* memmax is set, compute everything automatically. Here we want
2426 * to ensure that all SSL connections will be served. We take
2427 * care of the number of sides where SSL is used, and consider
2428 * the worst case : SSL used on both sides and doing a handshake
2429 * simultaneously. Note that we can't have more than maxconn
2430 * handshakes at a time by definition, so for the worst case of
2431 * two SSL conns per connection, we count a single handshake.
2432 */
2433 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2434 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002435 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002436
Willy Tarreau2cb3be72022-05-24 07:43:57 +02002437 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002438 mem -= global.maxzlibmem;
2439 mem = mem * MEM_USABLE_RATIO;
2440
Willy Tarreau304e17e2020-03-10 17:54:54 +01002441 /* Principle: we test once to set maxconn according to the free
2442 * memory. If it results in values the system rejects, we try a
2443 * second time by respecting rlim_fd_max. If it fails again, we
2444 * go back to the initial value and will let the final code
2445 * dealing with rlimit report the error. That's up to 3 attempts.
2446 */
2447 do {
2448 global.maxconn = mem /
2449 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2450 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2451 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002452
Willy Tarreau304e17e2020-03-10 17:54:54 +01002453 if (retried == 1)
2454 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2455 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002456#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002457 if (global.maxconn > SYSTEM_MAXCONN)
2458 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002459#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002460 global.maxsslconn = sides * global.maxconn;
2461
2462 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2463 break;
2464 } while (retried++ < 2);
2465
Willy Tarreaud0256482015-01-15 21:45:22 +01002466 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2467 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2468 global.maxconn, global.maxsslconn);
2469 }
2470 else if (!global.maxsslconn &&
2471 (global.ssl_used_frontend || global.ssl_used_backend)) {
2472 /* memmax and maxconn are known, compute maxsslconn automatically.
2473 * maxsslconn being forced, we don't know how many of it will be
2474 * on each side if both sides are being used. The worst case is
2475 * when all connections use only one SSL instance because
2476 * handshakes may be on two sides at the same time.
2477 */
2478 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2479 int64_t mem = global.rlimit_memmax * 1048576ULL;
2480 int64_t sslmem;
2481
Willy Tarreau8e5b9582022-05-26 08:55:05 +02002482 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002483 mem -= global.maxzlibmem;
2484 mem = mem * MEM_USABLE_RATIO;
2485
Willy Tarreau87b09662015-04-03 00:22:06 +02002486 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002487 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2488 global.maxsslconn = round_2dig(global.maxsslconn);
2489
2490 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002491 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2492 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2493 "without SSL is %d, but %d was found and SSL is in use.\n",
2494 global.rlimit_memmax,
2495 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2496 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002497 exit(1);
2498 }
2499
2500 if (global.maxsslconn > sides * global.maxconn)
2501 global.maxsslconn = sides * global.maxconn;
2502
2503 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2504 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2505 }
2506#endif
2507 else if (!global.maxconn) {
2508 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2509 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2510 int64_t mem = global.rlimit_memmax * 1048576ULL;
2511 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002512 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002513
2514 if (global.ssl_used_frontend || global.ssl_used_backend)
Willy Tarreau8e5b9582022-05-26 08:55:05 +02002515 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002516
2517 mem -= global.maxzlibmem;
2518 mem = mem * MEM_USABLE_RATIO;
2519
2520 clearmem = mem;
2521 if (sides)
2522 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2523
Willy Tarreau304e17e2020-03-10 17:54:54 +01002524 /* Principle: we test once to set maxconn according to the free
2525 * memory. If it results in values the system rejects, we try a
2526 * second time by respecting rlim_fd_max. If it fails again, we
2527 * go back to the initial value and will let the final code
2528 * dealing with rlimit report the error. That's up to 3 attempts.
2529 */
2530 do {
2531 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2532 if (retried == 1)
2533 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2534 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002535#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002536 if (global.maxconn > SYSTEM_MAXCONN)
2537 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002538#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002539
Willy Tarreau304e17e2020-03-10 17:54:54 +01002540 if (clearmem <= 0 || !global.maxconn) {
2541 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2542 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2543 "is %d, but %d was found.\n",
2544 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002545 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002546 global.maxsslconn);
2547 exit(1);
2548 }
2549
2550 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2551 break;
2552 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002553
2554 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2555 if (sides && global.maxsslconn > sides * global.maxconn) {
2556 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2557 "to be limited to %d. Better reduce global.maxsslconn to get more "
2558 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2559 }
2560 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2561 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002562 }
2563
Willy Tarreaua409f302020-03-10 17:08:53 +01002564 global.maxsock = compute_ideal_maxsock(global.maxconn);
2565 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002566 if (!global.maxpipes)
2567 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002568
Olivier Houchard88698d92019-04-16 19:07:22 +02002569 /* update connection pool thresholds */
2570 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2571 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2572
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002573 proxy_adjust_all_maxconn();
2574
Willy Tarreau1db37712007-06-03 17:16:49 +02002575 if (global.tune.maxpollevents <= 0)
2576 global.tune.maxpollevents = MAX_POLL_EVENTS;
2577
Willy Tarreau060a7612021-03-10 11:06:26 +01002578 if (global.tune.runqueue_depth <= 0) {
2579 /* tests on various thread counts from 1 to 64 have shown an
2580 * optimal queue depth following roughly 1/sqrt(threads).
2581 */
2582 int s = my_flsl(global.nbthread);
2583 s += (global.nbthread / s); // roughly twice the sqrt.
2584 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2585 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002586
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002587 if (global.tune.recv_enough == 0)
2588 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2589
Willy Tarreau27a674e2009-08-17 07:23:33 +02002590 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2591 global.tune.maxrewrite = global.tune.bufsize / 2;
2592
Amaury Denoyelle11124302021-06-04 18:22:08 +02002593 usermsgs_clr(NULL);
2594
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2596 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002597 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002598 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2599 }
2600
William Lallemand095ba4c2017-06-01 17:38:50 +02002601 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002602 /* command line daemon mode inhibits foreground and debug modes mode */
2603 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002604 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002606
2607 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002608
William Lallemand095ba4c2017-06-01 17:38:50 +02002609 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002610 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002611 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002612 }
2613
Christopher Faulet3ef26392017-08-29 16:46:57 +02002614 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002615 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002616 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002617 exit(1);
2618 }
2619
Christopher Faulet96d44832017-11-14 22:02:30 +01002620 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002621 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002622 exit(1);
2623 }
2624
Amaury Denoyelle28ea31c2022-11-14 16:18:46 +01002625 if (!global.cluster_secret)
2626 generate_random_cluster_secret();
2627
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002628 /*
2629 * Note: we could register external pollers here.
2630 * Built-in pollers have been registered before main().
2631 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002632
Willy Tarreau43b78992009-01-25 15:42:27 +01002633 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002634 disable_poller("kqueue");
2635
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002636 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2637 disable_poller("evports");
2638
Willy Tarreau43b78992009-01-25 15:42:27 +01002639 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002640 disable_poller("epoll");
2641
Willy Tarreau43b78992009-01-25 15:42:27 +01002642 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002643 disable_poller("poll");
2644
Willy Tarreau43b78992009-01-25 15:42:27 +01002645 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002646 disable_poller("select");
2647
2648 /* Note: we could disable any poller by name here */
2649
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002650 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002651 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002652 fprintf(stderr, "\n");
2653 list_filters(stderr);
2654 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002655
Willy Tarreau4f60f162007-04-08 16:39:58 +02002656 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002657 ha_alert("No polling mechanism available.\n"
Willy Tarreaue5715bf2022-07-09 23:38:46 +02002658 " This may happen when using thread-groups with old pollers (poll/select), or\n"
2659 " it is possible that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
Christopher Faulet767a84b2017-11-24 16:50:31 +01002660 " is too low on this platform to support maxconn and the number of listeners\n"
2661 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2662 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2663 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2664 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2665 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2666 " check build settings using 'haproxy -vv'.\n\n",
2667 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002668 exit(1);
2669 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002670 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2671 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002672 }
2673
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002674 if (!global.node)
2675 global.node = strdup(hostname);
2676
Willy Tarreau02b092f2020-10-07 18:36:54 +02002677 /* stop disabled proxies */
2678 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002679 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002680 stop_proxy(px);
2681 }
2682
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002683 if (!hlua_post_init())
2684 exit(1);
Willy Tarreau284cfc62022-12-19 08:15:57 +01002685
2686 /* Set the per-thread pool cache size to the default value if not set.
2687 * This is the right place to decide to automatically adjust it (e.g.
2688 * check L2 cache size, thread counts or take into account certain
2689 * expensive pools).
2690 */
2691 if (!global.tune.pool_cache_size)
2692 global.tune.pool_cache_size = CONFIG_HAP_POOL_CACHE_SIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002693}
2694
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002695void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002697 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002698 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002699 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002700 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002701 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002702 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002703 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002704 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002705 struct per_thread_init_fct *tif, *tifb;
2706 struct per_thread_deinit_fct *tdf, *tdfb;
2707 struct per_thread_alloc_fct *taf, *tafb;
2708 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002709 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002710 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002711 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreau65009eb2022-04-27 18:02:54 +02002712 struct pre_check_fct *prcf, *prcfb;
Willy Tarreau226866e2022-04-27 18:07:24 +02002713 struct cfg_postparser *pprs, *pprsb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002714 int cur_fd;
2715
Willy Tarreaue98d3852022-11-15 09:34:07 +01002716 /* the user may want to skip this phase */
2717 if (global.tune.options & GTUNE_QUICK_EXIT)
2718 return;
2719
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002720 /* At this point the listeners state is weird:
2721 * - most listeners are still bound and referenced in their protocol
2722 * - some might be zombies that are not in their proto anymore, but
2723 * still appear in their proxy's listeners with a valid FD.
2724 * - some might be stopped and still appear in their proxy as FD #-1
2725 * - among all of them, some might be inherited hence shared and we're
2726 * not allowed to pause them or whatever, we must just close them.
2727 * - finally some are not listeners (pipes, logs, stdout, etc) and
2728 * must be left intact.
2729 *
2730 * The safe way to proceed is to unbind (and close) whatever is not yet
2731 * unbound so that no more receiver/listener remains alive. Then close
2732 * remaining listener FDs, which correspond to zombie listeners (those
2733 * belonging to disabled proxies that were in another process).
2734 * objt_listener() would be cleaner here but not converted yet.
2735 */
2736 protocol_unbind_all();
2737
2738 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002739 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002740 continue;
2741
Willy Tarreaua74cb382020-10-15 21:29:49 +02002742 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002743 struct listener *l = fdtab[cur_fd].owner;
2744
2745 BUG_ON(l->state != LI_INIT);
2746 unbind_listener(l);
2747 }
2748 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002749
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002750 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002751 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002752 /* build a list of unique uri_auths */
2753 if (!ua)
2754 ua = p->uri_auth;
2755 else {
2756 /* check if p->uri_auth is unique */
2757 for (uap = ua; uap; uap=uap->next)
2758 if (uap == p->uri_auth)
2759 break;
2760
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002761 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002762 /* add it, if it is */
2763 p->uri_auth->next = ua;
2764 ua = p->uri_auth;
2765 }
William Lallemand0f99e342011-10-12 17:50:54 +02002766 }
2767
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002768 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002769 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002770 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002771 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002772
Christopher Faulet27c8d202021-10-13 09:50:53 +02002773 /* destroy all referenced defaults proxies */
2774 proxy_destroy_all_unref_defaults();
2775
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002776 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002777 struct stat_scope *scope, *scopep;
2778
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002779 uap = ua;
2780 ua = ua->next;
2781
Willy Tarreaua534fea2008-08-03 12:19:50 +02002782 free(uap->uri_prefix);
2783 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002784 free(uap->node);
2785 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002786
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002787 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002788 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002789
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002790 scope = uap->scope;
2791 while (scope) {
2792 scopep = scope;
2793 scope = scope->next;
2794
2795 free(scopep->px_id);
2796 free(scopep);
2797 }
2798
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002799 free(uap);
2800 }
2801
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002802 userlist_free(userlist);
2803
David Carlier834cb2e2015-09-25 12:02:25 +01002804 cfg_unregister_sections();
2805
Christopher Faulet0132d062017-07-26 15:33:35 +02002806 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002807
Willy Tarreau05554e62016-12-21 20:46:26 +01002808 list_for_each_entry(pdf, &post_deinit_list, list)
2809 pdf->fct();
2810
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002811 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002812 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002813 ha_free(&global.chroot);
Frédéric Lécaille372508c2022-05-06 08:53:16 +02002814 ha_free(&global.cluster_secret);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002815 ha_free(&global.pidfile);
2816 ha_free(&global.node);
2817 ha_free(&global.desc);
2818 ha_free(&oldpids);
2819 ha_free(&old_argv);
2820 ha_free(&localpeer);
2821 ha_free(&global.server_state_base);
2822 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002823 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002824 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002825
William Lallemand0f99e342011-10-12 17:50:54 +02002826 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2c701db2023-01-26 15:32:12 +01002827 LIST_DEL_INIT(&log->list);
2828 free_logsrv(log);
2829 }
2830
Willy Tarreau477ecd82010-01-03 21:12:30 +01002831 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002832 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002833 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002834 free(wl);
2835 }
2836
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002837 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2838 if (bol->must_free)
2839 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002840 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002841 free(bol);
2842 }
2843
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002844 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002845 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002846 free(pxdf);
2847 }
2848
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002849 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002850 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002851 free(pdf);
2852 }
2853
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002854 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002855 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002856 free(srvdf);
2857 }
2858
Tim Duesterhusfc854942020-09-10 19:46:42 +02002859 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002860 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002861 free(pcf);
2862 }
2863
Tim Duesterhus34bef072020-07-04 11:49:50 +02002864 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002865 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002866 free(pscf);
2867 }
2868
Tim Duesterhus53508d62020-09-10 19:46:40 +02002869 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002870 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002871 free(ppcf);
2872 }
2873
Willy Tarreau65009eb2022-04-27 18:02:54 +02002874 list_for_each_entry_safe(prcf, prcfb, &pre_check_list, list) {
2875 LIST_DELETE(&prcf->list);
2876 free(prcf);
2877 }
2878
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002879 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002880 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002881 free(tif);
2882 }
2883
2884 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002885 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002886 free(tdf);
2887 }
2888
2889 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002890 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002891 free(taf);
2892 }
2893
2894 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002895 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002896 free(tff);
2897 }
2898
Willy Tarreau226866e2022-04-27 18:07:24 +02002899 list_for_each_entry_safe(pprs, pprsb, &postparsers, list) {
2900 LIST_DELETE(&pprs->list);
2901 free(pprs);
2902 }
2903
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002904 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002905 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002906 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002907} /* end deinit() */
2908
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002909__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002910{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002911 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002912 deinit();
2913 exit(status);
2914}
William Lallemand72160322018-11-06 17:37:16 +01002915
Willy Tarreau918ff602011-07-25 16:33:49 +02002916/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002917void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002918{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002919 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002920
Willy Tarreau55542642021-10-08 09:33:24 +02002921 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002922 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002923 wake_expired_tasks();
2924
William Lallemand1aab50b2018-06-07 09:46:01 +02002925 /* check if we caught some signals and process them in the
2926 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002927 if (signal_queue_len && tid == 0) {
2928 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002929 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002930 }
2931
2932 /* Process a few tasks */
2933 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002934
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002935 /* also stop if we failed to cleanly stop all tasks */
2936 if (killed > 1)
2937 break;
2938
Matthias Wirtheea152e2022-09-09 10:21:00 +02002939 /* expire immediately if events or signals are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002940 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002941 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002942 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002943 else {
Willy Tarreaue7475c82022-06-20 09:23:24 +02002944 _HA_ATOMIC_OR(&th_ctx->flags, TH_FL_SLEEPING);
Willy Tarreaudce4ad72022-06-22 15:38:38 +02002945 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_NOTIFIED);
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002946 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002947 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002948 activity[tid].wake_tasks++;
Willy Tarreaue7475c82022-06-20 09:23:24 +02002949 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_SLEEPING);
Matthias Wirtheea152e2022-09-09 10:21:00 +02002950 } else if (signal_queue_len) {
2951 /* this check is required after setting TH_FL_SLEEPING to avoid
2952 * a race with wakeup on signals using wake_threads() */
2953 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_SLEEPING);
Olivier Houchard79321b92018-07-26 17:55:11 +02002954 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002955 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002956 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002957
Willy Tarreau4f46a352020-03-23 09:27:28 +01002958 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002959 int i;
2960
2961 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002962 /* stop muxes before acknowledging stopping */
Willy Tarreau24cfc9f2022-07-04 14:07:29 +02002963 if (!(tg_ctx->stopping_threads & ti->ltid_bit)) {
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002964 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2965 wake = 1;
2966 }
2967
Willy Tarreauef422ce2022-06-28 19:29:29 +02002968 if (_HA_ATOMIC_OR_FETCH(&tg_ctx->stopping_threads, ti->ltid_bit) == ti->ltid_bit &&
2969 _HA_ATOMIC_OR_FETCH(&stopping_tgroup_mask, tg->tgid_bit) == tg->tgid_bit) {
2970 /* first one to detect it, notify all threads that stopping was just set */
2971 for (i = 0; i < global.nbthread; i++) {
Willy Tarreaub2f38c12023-01-19 19:14:18 +01002972 if (_HA_ATOMIC_LOAD(&ha_thread_info[i].tg->threads_enabled) &
Willy Tarreauef422ce2022-06-28 19:29:29 +02002973 ha_thread_info[i].ltid_bit &
2974 ~_HA_ATOMIC_LOAD(&ha_thread_info[i].tg_ctx->stopping_threads))
Willy Tarreaud6455742020-05-13 14:30:25 +02002975 wake_thread(i);
Willy Tarreauef422ce2022-06-28 19:29:29 +02002976 }
Willy Tarreaud6455742020-05-13 14:30:25 +02002977 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002978 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002979
2980 /* stop when there's nothing left to do */
2981 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreauef422ce2022-06-28 19:29:29 +02002982 (_HA_ATOMIC_LOAD(&stopping_tgroup_mask) & all_tgroups_mask) == all_tgroups_mask) {
2983 /* check that all threads are aware of the stopping status */
2984 for (i = 0; i < global.nbtgroups; i++)
Willy Tarreaub2f38c12023-01-19 19:14:18 +01002985 if ((_HA_ATOMIC_LOAD(&ha_tgroup_ctx[i].stopping_threads) &
2986 _HA_ATOMIC_LOAD(&ha_tgroup_info[i].threads_enabled)) !=
2987 _HA_ATOMIC_LOAD(&ha_tgroup_info[i].threads_enabled))
Willy Tarreauef422ce2022-06-28 19:29:29 +02002988 break;
2989#ifdef USE_THREAD
2990 if (i == global.nbtgroups) {
2991 /* all are OK, let's wake them all and stop */
2992 for (i = 0; i < global.nbthread; i++)
Willy Tarreaub2f38c12023-01-19 19:14:18 +01002993 if (i != tid && _HA_ATOMIC_LOAD(&ha_thread_info[i].tg->threads_enabled) & ha_thread_info[i].ltid_bit)
Willy Tarreauef422ce2022-06-28 19:29:29 +02002994 wake_thread(i);
2995 break;
2996 }
2997#endif
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002998 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002999 }
3000
Willy Tarreauc49ba522019-12-11 08:12:23 +01003001 /* If we have to sleep, measure how long */
3002 next = wake ? TICK_ETERNITY : next_timer_expiry();
3003
Willy Tarreau58b458d2008-06-29 22:40:23 +02003004 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02003005 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02003006
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01003007 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02003008 }
3009}
3010
Christopher Faulet1d17c102017-08-29 15:38:48 +02003011static void *run_thread_poll_loop(void *data)
3012{
Willy Tarreau082b6282019-05-22 14:42:12 +02003013 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02003014 struct per_thread_init_fct *ptif;
3015 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02003016 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02003017 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02003018 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
3019 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02003020
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003021 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02003022 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02003023 clock_set_local_source();
Aurelien DARRAGON739281b2023-01-27 15:13:28 +01003024 /* thread is started, from now on it is not idle nor harmless */
3025 thread_harmless_end();
3026 thread_idle_end();
Willy Tarreau91e6df02019-05-03 17:21:18 +02003027
Willy Tarreau6ec902a2019-06-07 14:41:11 +02003028 /* Now, initialize one thread init at a time. This is better since
3029 * some init code is a bit tricky and may release global resources
3030 * after reallocating them locally. This will also ensure there is
3031 * no race on file descriptors allocation.
3032 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02003033#ifdef USE_THREAD
3034 pthread_mutex_lock(&init_mutex);
3035#endif
3036 /* The first thread must set the number of threads left */
3037 if (!init_left)
3038 init_left = global.nbthread;
3039 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02003040
Willy Tarreau55542642021-10-08 09:33:24 +02003041 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003042
Willy Tarreau082b6282019-05-22 14:42:12 +02003043 /* per-thread alloc calls performed here are not allowed to snoop on
3044 * other threads, so they are free to initialize at their own rhythm
3045 * as long as they act as if they were alone. None of them may rely
3046 * on resources initialized by the other ones.
3047 */
3048 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
3049 if (!ptaf->fct()) {
3050 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02003051#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08003052 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02003053#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02003054 exit(1);
3055 }
3056 }
3057
Willy Tarreau3078e9f2019-05-20 10:50:43 +02003058 /* per-thread init calls performed here are not allowed to snoop on
3059 * other threads, so they are free to initialize at their own rhythm
3060 * as long as they act as if they were alone.
3061 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02003062 list_for_each_entry(ptif, &per_thread_init_list, list) {
3063 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003064 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02003065#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08003066 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02003067#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003068 exit(1);
3069 }
3070 }
3071
Willy Tarreau71092822019-06-10 09:51:04 +02003072 /* enabling protocols will result in fd_insert() calls to be performed,
3073 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02003074 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02003075 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02003076 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02003077 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02003078
Willy Tarreau34a150c2019-06-11 09:16:41 +02003079#ifdef USE_THREAD
3080 pthread_cond_broadcast(&init_cond);
3081 pthread_mutex_unlock(&init_mutex);
3082
3083 /* now wait for other threads to finish starting */
3084 pthread_mutex_lock(&init_mutex);
3085 while (init_left)
3086 pthread_cond_wait(&init_cond, &init_mutex);
3087 pthread_mutex_unlock(&init_mutex);
3088#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02003089
Willy Tarreaua45a8b52019-12-06 16:31:45 +01003090#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
3091 /* Let's refrain from using setuid executables. This way the impact of
3092 * an eventual vulnerability in a library remains limited. It may
3093 * impact external checks but who cares about them anyway ? In the
3094 * worst case it's possible to disable the option. Obviously we do this
3095 * in workers only. We can't hard-fail on this one as it really is
3096 * implementation dependent though we're interested in feedback, hence
3097 * the warning.
3098 */
3099 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
3100 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02003101 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 +01003102 ha_warning("Failed to disable setuid, please report to developers with detailed "
3103 "information about your operating system. You can silence this warning "
3104 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
3105 }
3106 }
3107#endif
3108
Willy Tarreaud96f1122019-12-03 07:07:36 +01003109#if defined(RLIMIT_NPROC)
3110 /* all threads have started, it's now time to prevent any new thread
3111 * or process from starting. Obviously we do this in workers only. We
3112 * can't hard-fail on this one as it really is implementation dependent
3113 * though we're interested in feedback, hence the warning.
3114 */
3115 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
3116 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
3117 static int warn_fail;
3118
Willy Tarreau18515722021-04-06 11:57:41 +02003119 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01003120 ha_warning("Failed to disable forks, please report to developers with detailed "
3121 "information about your operating system. You can silence this warning "
3122 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
3123 }
3124 }
3125#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003126 run_poll_loop();
3127
3128 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
3129 ptdf->fct();
3130
Willy Tarreau082b6282019-05-22 14:42:12 +02003131 list_for_each_entry(ptff, &per_thread_free_list, list)
3132 ptff->fct();
3133
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003134#ifdef USE_THREAD
Willy Tarreau291f6ff2022-07-04 13:36:16 +02003135 if (!_HA_ATOMIC_AND_FETCH(&ha_tgroup_info[ti->tgid-1].threads_enabled, ~ti->ltid_bit))
Willy Tarreaucce203a2022-06-24 15:55:11 +02003136 _HA_ATOMIC_AND(&all_tgroups_mask, ~tg->tgid_bit);
Willy Tarreauad92fdf2022-07-06 10:17:21 +02003137 if (!_HA_ATOMIC_AND_FETCH(&tg_ctx->stopping_threads, ~ti->ltid_bit))
3138 _HA_ATOMIC_AND(&stopping_tgroup_mask, ~tg->tgid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003139 if (tid > 0)
3140 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02003141#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003142 return NULL;
3143}
Christopher Faulet1d17c102017-08-29 15:38:48 +02003144
William Dauchyf9af9d72019-11-17 15:47:16 +01003145/* set uid/gid depending on global settings */
3146static void set_identity(const char *program_name)
3147{
3148 if (global.gid) {
3149 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
3150 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
3151 " without 'uid'/'user' is generally useless.\n", program_name);
3152
3153 if (setgid(global.gid) == -1) {
3154 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
3155 protocol_unbind_all();
3156 exit(1);
3157 }
3158 }
3159
3160 if (global.uid && setuid(global.uid) == -1) {
3161 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
3162 protocol_unbind_all();
3163 exit(1);
3164 }
3165}
3166
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167int main(int argc, char **argv)
3168{
3169 int err, retry;
3170 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02003171 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02003172 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
3173
Willy Tarreau41afd902022-07-21 09:55:22 +02003174 /* Catch broken toolchains */
3175 if (sizeof(long) != sizeof(void *) || (intovf + 0x7FFFFFFF >= intovf)) {
3176 const char *msg;
3177
3178 if (sizeof(long) != sizeof(void *))
3179 /* Apparently MingW64 was not made for us and can also break openssl */
3180 msg = "The compiler this program was built with uses unsupported integral type sizes.\n"
3181 "Most likely it follows the unsupported LLP64 model. Never try to link HAProxy\n"
3182 "against libraries built with that compiler either! Please only use a compiler\n"
3183 "producing ILP32 or LP64 programs for both programs and libraries.\n";
3184 else if (intovf + 0x7FFFFFFF >= intovf)
3185 /* Catch forced CFLAGS that miss 2-complement integer overflow */
3186 msg = "The source code was miscompiled by the compiler, which usually indicates that\n"
3187 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
3188 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
3189 "and INSTALL files to decide on the best way to pass your local build options.\n";
3190 else
3191 msg = "Bug in the compiler bug detection code, please report it to developers!\n";
3192
Willy Tarreau1335da32021-07-14 17:54:01 +02003193 fprintf(stderr,
3194 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
Willy Tarreau41afd902022-07-21 09:55:22 +02003195 "%s"
3196 "\nBuild options :"
Willy Tarreau1335da32021-07-14 17:54:01 +02003197#ifdef BUILD_TARGET
Willy Tarreau41afd902022-07-21 09:55:22 +02003198 "\n TARGET = " BUILD_TARGET
Willy Tarreau1335da32021-07-14 17:54:01 +02003199#endif
3200#ifdef BUILD_CPU
Willy Tarreau41afd902022-07-21 09:55:22 +02003201 "\n CPU = " BUILD_CPU
Willy Tarreau1335da32021-07-14 17:54:01 +02003202#endif
3203#ifdef BUILD_CC
Willy Tarreau41afd902022-07-21 09:55:22 +02003204 "\n CC = " BUILD_CC
Willy Tarreau1335da32021-07-14 17:54:01 +02003205#endif
3206#ifdef BUILD_CFLAGS
Willy Tarreau41afd902022-07-21 09:55:22 +02003207 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau1335da32021-07-14 17:54:01 +02003208#endif
3209#ifdef BUILD_OPTIONS
Willy Tarreau41afd902022-07-21 09:55:22 +02003210 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau1335da32021-07-14 17:54:01 +02003211#endif
3212#ifdef BUILD_DEBUG
Willy Tarreau41afd902022-07-21 09:55:22 +02003213 "\n DEBUG = " BUILD_DEBUG
Willy Tarreau1335da32021-07-14 17:54:01 +02003214#endif
Willy Tarreau41afd902022-07-21 09:55:22 +02003215 "\n\n", msg);
3216
Willy Tarreau1335da32021-07-14 17:54:01 +02003217 return 1;
3218 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003219
Olivier Houchard5fa300d2018-02-03 15:15:21 +01003220 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003221
Willy Tarreaubf696402019-03-01 10:09:28 +01003222 /* take a copy of initial limits before we possibly change them */
3223 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02003224
3225 if (limit.rlim_max == RLIM_INFINITY)
3226 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01003227 rlim_fd_cur_at_boot = limit.rlim_cur;
3228 rlim_fd_max_at_boot = limit.rlim_max;
3229
Willy Tarreau5794fb02018-11-25 18:43:29 +01003230 /* process all initcalls in order of potential dependency */
3231 RUN_INITCALLS(STG_PREPARE);
3232 RUN_INITCALLS(STG_LOCK);
Willy Tarreau3ebe4d92022-02-18 14:51:49 +01003233 RUN_INITCALLS(STG_REGISTER);
Willy Tarreau34527d52022-02-17 17:45:58 +01003234
3235 /* now's time to initialize early boot variables */
3236 init_early(argc, argv);
3237
Willy Tarreau18f96d02022-02-23 17:25:00 +01003238 /* handles argument parsing */
3239 init_args(argc, argv);
3240
Willy Tarreau5794fb02018-11-25 18:43:29 +01003241 RUN_INITCALLS(STG_ALLOC);
3242 RUN_INITCALLS(STG_POOL);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003243 RUN_INITCALLS(STG_INIT);
3244
Willy Tarreau34527d52022-02-17 17:45:58 +01003245 /* this is the late init where the config is parsed */
Emeric Bruncf20bf12010-10-22 16:06:11 +02003246 init(argc, argv);
Willy Tarreau34527d52022-02-17 17:45:58 +01003247
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003248 signal_register_fct(SIGQUIT, dump, SIGQUIT);
3249 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
3250 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02003251 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003252
Willy Tarreaue437c442010-03-17 18:02:46 +01003253 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
3254 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
3255 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003257 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003258
Willy Tarreaudc23a922011-02-16 11:10:36 +01003259 /* ulimits */
3260 if (!global.rlimit_nofile)
3261 global.rlimit_nofile = global.maxsock;
3262
3263 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01003264 limit.rlim_cur = global.rlimit_nofile;
3265 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
3266
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003267 if ((global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit) ||
Willy Tarreauc06557c2022-09-22 16:12:08 +02003268 raise_rlim_nofile(NULL, &limit) != 0) {
Willy Tarreauef635472016-06-21 11:48:18 +02003269 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003270 if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
3271 limit.rlim_cur = global.fd_hard_limit;
3272
William Dauchy0fec3ab2019-10-27 20:08:11 +01003273 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3274 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
3275 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003276 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003277 }
3278 else {
3279 /* try to set it to the max possible at least */
3280 limit.rlim_cur = limit.rlim_max;
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003281 if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
3282 limit.rlim_cur = global.fd_hard_limit;
3283
Willy Tarreauc06557c2022-09-22 16:12:08 +02003284 if (raise_rlim_nofile(&limit, &limit) == 0)
William Dauchy0fec3ab2019-10-27 20:08:11 +01003285 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02003286
William Dauchya5194602020-03-28 19:29:58 +01003287 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003288 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
3289 global.rlimit_nofile = limit.rlim_cur;
3290 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01003291 }
3292 }
3293
3294 if (global.rlimit_memmax) {
3295 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01003296 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01003297#ifdef RLIMIT_AS
3298 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003299 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3300 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3301 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003302 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003303 }
3304 else
William Dauchya5194602020-03-28 19:29:58 +01003305 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003306 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003307 }
3308#else
3309 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003310 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3311 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3312 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003313 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003314 }
3315 else
William Dauchya5194602020-03-28 19:29:58 +01003316 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003317 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003318 }
3319#endif
3320 }
3321
William Lallemandf82afbb2022-01-07 18:19:42 +01003322 /* Try to get the listeners FD from the previous process using
3323 * _getsocks on the stat socket, it must never been done in wait mode
3324 * and check mode
3325 */
3326 if (old_unixsocket &&
3327 !(global.mode & (MODE_MWORKER_WAIT|MODE_CHECK|MODE_CHECK_CONDITION))) {
William Lallemand85b0bd92017-06-01 17:38:53 +02003328 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02003329 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003330 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02003331 if (!(global.mode & MODE_MWORKER))
3332 exit(1);
3333 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02003334 }
3335 }
William Lallemand85b0bd92017-06-01 17:38:53 +02003336
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 /* We will loop at most 100 times with 10 ms delay each time.
3338 * That's at most 1 second. We only send a signal to old pids
3339 * if we cannot grab at least one port.
3340 */
3341 retry = MAX_START_RETRIES;
3342 err = ERR_NONE;
3343 while (retry >= 0) {
3344 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003345 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003346 /* exit the loop on no error or fatal error */
3347 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003348 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003349 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 break;
3351
3352 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3353 * listening sockets. So on those platforms, it would be wiser to
3354 * simply send SIGUSR1, which will not be undoable.
3355 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003356 if (tell_old_pids(SIGTTOU) == 0) {
3357 /* no need to wait if we can't contact old pids */
3358 retry = 0;
3359 continue;
3360 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003361 /* give some time to old processes to stop listening */
3362 w.tv_sec = 0;
3363 w.tv_usec = 10*1000;
3364 select(0, NULL, NULL, NULL, &w);
3365 retry--;
3366 }
3367
Willy Tarreaue91bff22020-09-02 11:11:43 +02003368 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003369 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003370 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003371 if (retry != MAX_START_RETRIES && nb_oldpids) {
3372 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003374 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 exit(1);
3376 }
3377
William Lallemand944e6192018-11-21 15:48:31 +01003378 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003379 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003380 /* Note: we don't have to send anything to the old pids because we
3381 * never stopped them. */
3382 exit(1);
3383 }
3384
Willy Tarreaue91bff22020-09-02 11:11:43 +02003385 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003386 * the previous process gave us, we don't need them anymore
3387 */
Willy Tarreaub5101162022-01-28 18:28:18 +01003388 sock_drop_unused_old_sockets();
Willy Tarreaudd815982007-10-16 12:25:14 +02003389
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003391 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3392 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 /* MODE_QUIET can inhibit alerts and warnings below this line */
3395
PiBa-NL149a81a2017-12-25 21:03:31 +01003396 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3397 /* either stdin/out/err are already closed or should stay as they are. */
3398 if ((global.mode & MODE_DAEMON)) {
3399 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3400 global.mode &= ~MODE_VERBOSE;
3401 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3402 }
3403 } else {
3404 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3405 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003406 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003407 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003408 }
3409
3410 /* open log & pid files before the chroot */
William Lallemand7b820a62022-02-14 09:02:14 +01003411 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) &&
3412 !(global.mode & MODE_MWORKER_WAIT) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 unlink(global.pidfile);
3414 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3415 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003416 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003417 if (nb_oldpids)
3418 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003419 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003420 exit(1);
3421 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003422 }
3423
Willy Tarreaub38651a2007-03-24 17:24:39 +01003424 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003425 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3426 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003427 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003428 exit(1);
3429 }
3430
Jackie Tapia749f74c2020-07-22 18:59:40 -05003431 /* If the user is not root, we'll still let them try the configuration
3432 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003433 */
3434 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003435 ha_warning("[%s.main()] Some options which require full privileges"
3436 " might not work well.\n"
3437 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003438
William Lallemand095ba4c2017-06-01 17:38:50 +02003439 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3440
3441 /* chroot if needed */
3442 if (global.chroot != NULL) {
3443 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003444 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003445 if (nb_oldpids)
3446 tell_old_pids(SIGTTIN);
3447 protocol_unbind_all();
3448 exit(1);
3449 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003450 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003451 }
3452
William Lallemand944e6192018-11-21 15:48:31 +01003453 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003454 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003455
William Lallemand27edc4b2019-05-07 17:49:33 +02003456 /* send a SIGTERM to workers who have a too high reloads number */
3457 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3458 mworker_kill_max_reloads(SIGTERM);
3459
Willy Tarreaubaaee002006-06-26 02:48:02 +02003460 /* Note that any error at this stage will be fatal because we will not
3461 * be able to restart the old pids.
3462 */
3463
William Dauchyf9af9d72019-11-17 15:47:16 +01003464 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3465 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003466
Willy Tarreaubaaee002006-06-26 02:48:02 +02003467 /* check ulimits */
3468 limit.rlim_cur = limit.rlim_max = 0;
3469 getrlimit(RLIMIT_NOFILE, &limit);
3470 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003471 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3472 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3473 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3474 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3475 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003476 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003477 }
3478 else
3479 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003480 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003481 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3482 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003483 }
3484
William Lallemand944e6192018-11-21 15:48:31 +01003485 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003487 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003488 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003489
William Lallemand095ba4c2017-06-01 17:38:50 +02003490 /*
3491 * if daemon + mworker: must fork here to let a master
3492 * process live in background before forking children
3493 */
William Lallemand73b85e72017-06-01 17:38:51 +02003494
3495 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3496 && (global.mode & MODE_MWORKER)
3497 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003498 ret = fork();
3499 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003500 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003501 protocol_unbind_all();
3502 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003503 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003504 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003505 } else /* change the process group ID in the child (master process) */
3506 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003507 }
William Lallemande20b6a62017-06-01 17:38:55 +02003508
William Lallemande20b6a62017-06-01 17:38:55 +02003509
William Lallemanddeed7802017-11-06 11:00:04 +01003510 /* if in master-worker mode, write the PID of the father */
3511 if (global.mode & MODE_MWORKER) {
3512 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003513 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003514 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003515 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003516 }
3517
Willy Tarreaubaaee002006-06-26 02:48:02 +02003518 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003519 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemandeba6a542022-09-26 12:54:39 +02003520 struct ring *tmp_startup_logs = NULL;
3521
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003522 if (global.mode & MODE_MWORKER)
3523 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003524
William Lallemandeba6a542022-09-26 12:54:39 +02003525 /* at this point the worker must have his own startup_logs buffer */
3526 tmp_startup_logs = startup_logs_dup(startup_logs);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003527 ret = fork();
3528 if (ret < 0) {
3529 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3530 protocol_unbind_all();
3531 exit(1); /* there has been an error */
3532 }
3533 else if (ret == 0) { /* child breaks here */
William Lallemandeba6a542022-09-26 12:54:39 +02003534 startup_logs_free(startup_logs);
3535 startup_logs = tmp_startup_logs;
Willy Tarreau3c032f22021-07-21 10:17:02 +02003536 /* This one must not be exported, it's internal! */
3537 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003538 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003539 }
3540 else { /* parent here */
3541 in_parent = 1;
3542
William Lallemand944e6192018-11-21 15:48:31 +01003543 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3544 char pidstr[100];
3545 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003546 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003547 }
3548 if (global.mode & MODE_MWORKER) {
3549 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003550
William Lallemand5d71a6b2021-11-09 15:25:31 +01003551 ha_notice("New worker (%d) forked\n", ret);
William Lallemand944e6192018-11-21 15:48:31 +01003552 /* find the right mworker_proc */
3553 list_for_each_entry(child, &proc_list, list) {
William Lallemandd4835a92022-07-21 00:52:43 +02003554 if (child->reloads == 0 &&
3555 child->options & PROC_O_TYPE_WORKER &&
3556 child->pid == -1) {
William Lallemand944e6192018-11-21 15:48:31 +01003557 child->timestamp = now.tv_sec;
3558 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003559 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003560 break;
3561 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003562 }
3563 }
William Lallemand944e6192018-11-21 15:48:31 +01003564 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003565
William Lallemand944e6192018-11-21 15:48:31 +01003566 } else {
3567 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003568 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003569 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003570
3571#ifdef USE_CPU_AFFINITY
Willy Tarreau5b093412022-07-08 09:38:30 +02003572 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 +02003573
David CARLIERdf91cbd2022-01-06 18:53:50 +00003574#if defined(CPUSET_USE_CPUSET) || defined(__DragonFly__)
Willy Tarreau5b093412022-07-08 09:38:30 +02003575 struct hap_cpuset *set = &cpu_map[0].proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003576 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
David CARLIERdf91cbd2022-01-06 18:53:50 +00003577#elif defined(__FreeBSD__)
Willy Tarreau5b093412022-07-08 09:38:30 +02003578 struct hap_cpuset *set = &cpu_map[0].proc;
David CARLIERdf91cbd2022-01-06 18:53:50 +00003579 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003580#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003581 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003582#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003583 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003584 if (pidfd >= 0) {
3585 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3586 close(pidfd);
3587 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003588
3589 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003590 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591
Willy Tarreaud67ff342021-06-15 07:58:09 +02003592 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003593 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
William Lallemandfab0fdc2021-11-09 18:01:22 +01003594 master = 1;
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003595
3596 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3597 (global.mode & MODE_DAEMON)) {
3598 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003599 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3600 stdio_quiet(-1);
3601
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003602 global.mode &= ~MODE_VERBOSE;
3603 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003604 }
3605
William Lallemandfab0fdc2021-11-09 18:01:22 +01003606 if (global.mode & MODE_MWORKER_WAIT) {
3607 /* only the wait mode handles the master CLI */
3608 mworker_loop();
3609 } else {
3610
William Lallemanda46a99e2022-07-07 14:00:36 +02003611#if defined(USE_SYSTEMD)
3612 if (global.tune.options & GTUNE_USE_SYSTEMD)
3613 sd_notifyf(0, "READY=1\nMAINPID=%lu\nSTATUS=Ready.\n", (unsigned long)getpid());
3614#endif
William Lallemandfab0fdc2021-11-09 18:01:22 +01003615 /* if not in wait mode, reload in wait mode to free the memory */
William Lallemand68192b22022-09-24 15:44:42 +02003616 setenv("HAPROXY_LOAD_SUCCESS", "1", 1);
William Lallemand836bda22021-11-09 18:16:47 +01003617 ha_notice("Loading success.\n");
William Lallemand68836742021-11-10 10:49:06 +01003618 proc_self->failedreloads = 0; /* reset the number of failure */
William Lallemandfab0fdc2021-11-09 18:01:22 +01003619 mworker_reexec_waitmode();
3620 }
William Lallemand1499b9b2017-06-07 15:04:47 +02003621 /* should never get there */
3622 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003623 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003624#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003625 ssl_free_dh();
3626#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003627 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003628 }
3629
William Lallemandcb11fd22017-06-01 17:38:52 +02003630 /* child must never use the atexit function */
3631 atexit_flag = 0;
3632
William Lallemandbc193052018-09-11 10:06:26 +02003633 /* close useless master sockets */
3634 if (global.mode & MODE_MWORKER) {
3635 struct mworker_proc *child, *it;
3636 master = 0;
3637
William Lallemand309dc9a2018-10-26 14:47:45 +02003638 mworker_cli_proxy_stop();
3639
William Lallemandbc193052018-09-11 10:06:26 +02003640 /* free proc struct of other processes */
3641 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003642 /* close the FD of the master side for all
3643 * workers, we don't need to close the worker
3644 * side of other workers since it's done with
3645 * the bind_proc */
William Lallemand7e018782022-01-28 21:56:24 +01003646 if (child->ipc_fd[0] >= 0) {
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003647 close(child->ipc_fd[0]);
William Lallemand7e018782022-01-28 21:56:24 +01003648 child->ipc_fd[0] = -1;
3649 }
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003650 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandd4835a92022-07-21 00:52:43 +02003651 child->reloads == 0 &&
3652 child->pid == -1) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003653 /* keep this struct if this is our pid */
3654 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003655 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003656 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003657 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003658 mworker_free_child(child);
3659 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003660 }
3661 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003662
William Lallemande1340412017-12-28 16:09:36 +01003663 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3664 devnullfd = open("/dev/null", O_RDWR, 0);
3665 if (devnullfd < 0) {
3666 ha_alert("Cannot open /dev/null\n");
3667 exit(EXIT_FAILURE);
3668 }
3669 }
3670
William Lallemand095ba4c2017-06-01 17:38:50 +02003671 /* Must chroot and setgid/setuid in the children */
3672 /* chroot if needed */
3673 if (global.chroot != NULL) {
3674 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003675 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003676 if (nb_oldpids)
3677 tell_old_pids(SIGTTIN);
3678 protocol_unbind_all();
3679 exit(1);
3680 }
3681 }
3682
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003683 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003684 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003685
William Lallemand7f80eb22017-05-26 18:19:55 +02003686 /* pass through every cli socket, and check if it's bound to
3687 * the current process and if it exposes listeners sockets.
3688 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3689 * */
3690
Willy Tarreau4975d142021-03-13 11:00:33 +01003691 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003692 struct bind_conf *bind_conf;
3693
Willy Tarreau4975d142021-03-13 11:00:33 +01003694 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003695 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003696 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3697 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003698 }
3699 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003700 }
3701
William Lallemand2e8fad92018-11-13 16:18:23 +01003702 /*
3703 * This is only done in daemon mode because we might want the
3704 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3705 * we should now close the 3 first FDs to ensure that we can
3706 * detach from the TTY. We MUST NOT do it in other cases since
3707 * it would have already be done, and 0-2 would have been
3708 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003709 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003710 if ((global.mode & MODE_DAEMON) &&
3711 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003712 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003713 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003714 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003715 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3716 }
3717 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003718 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3719 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003720 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 }
3722
William Dauchye039f262019-11-17 15:47:15 +01003723 /* try our best to re-enable core dumps depending on system capabilities.
3724 * What is addressed here :
3725 * - remove file size limits
3726 * - remove core size limits
3727 * - mark the process dumpable again if it lost it due to user/group
3728 */
3729 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3730 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3731
3732#if defined(RLIMIT_FSIZE)
3733 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3734 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3735 ha_alert("[%s.main()] Failed to set the raise the maximum "
3736 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003737 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003738 }
3739 else
3740 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003741 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003742 }
3743#endif
3744
3745#if defined(RLIMIT_CORE)
3746 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3747 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3748 ha_alert("[%s.main()] Failed to set the raise the core "
3749 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003750 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003751 }
3752 else
3753 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003754 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003755 }
3756#endif
3757
3758#if defined(USE_PRCTL)
3759 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3760 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3761 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003762#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003763 {
3764 int traceable = PROC_TRACE_CTL_ENABLE;
3765 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3766 ha_warning("[%s.main()] Failed to set the traceable flag, "
3767 "no core will be dumped.\n", argv[0]);
3768 }
William Dauchye039f262019-11-17 15:47:15 +01003769#endif
3770 }
3771
Christopher Faulete3a5e352017-10-24 13:53:54 +02003772 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003773 reset_usermsgs_ctx();
3774
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003775 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003776 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003777
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003778 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003779 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003780
3781 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003782 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003783
3784 /* wait for all threads to terminate */
3785 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003786
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003787 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003788}
3789
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790/*
3791 * Local variables:
3792 * c-indent-level: 8
3793 * c-basic-offset: 8
3794 * End:
3795 */