blob: 93b0780108639eb46f990e1d46cea41d646b7820 [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 Denoyelle5907fed2023-03-08 10:37:45 +0100118#include <haproxy/quic_conn.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 Tarreau84fe1f42023-04-20 15:40:38 +0200190 .options = GTUNE_LISTENER_MQ_OPT,
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,
Willy Tarreau0e875cf2023-04-23 00:51:59 +0200208 .default_shards = -2, /* by-group */
Amaury Denoyelle97e84c62022-04-19 18:26:55 +0200209#ifdef USE_QUIC
Frédéric Lécailleaee67572022-05-23 18:29:39 +0200210 .quic_backend_max_idle_timeout = QUIC_TP_DFLT_BACK_MAX_IDLE_TIMEOUT,
211 .quic_frontend_max_idle_timeout = QUIC_TP_DFLT_FRONT_MAX_IDLE_TIMEOUT,
212 .quic_frontend_max_streams_bidi = QUIC_TP_DFLT_FRONT_MAX_STREAMS_BIDI,
Frédéric Lécaille92862102022-05-20 16:29:10 +0200213 .quic_retry_threshold = QUIC_DFLT_RETRY_THRESHOLD,
Amaury Denoyelle24d5b722023-01-31 11:44:50 +0100214 .quic_max_frame_loss = QUIC_DFLT_MAX_FRAME_LOSS,
Amaury Denoyelle97e84c62022-04-19 18:26:55 +0200215 .quic_streams_buf = 30,
216#endif /* USE_QUIC */
Willy Tarreau27a674e2009-08-17 07:23:33 +0200217 },
Emeric Brun76d88952012-10-05 15:47:31 +0200218#ifdef USE_OPENSSL
219#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200220 .maxsslconn = DEFAULT_MAXSSLCONN,
221#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200222#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 /* others NULL OK */
224};
225
226/*********************************************************************/
227
228int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100229int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200230int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100231int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100232int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100233int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreau392524d2022-02-17 18:10:36 +0100234int arg_mode = 0; /* MODE_DEBUG etc as passed on command line ... */
235char *change_dir = NULL; /* set when -C is passed */
236char *check_condition = NULL; /* check condition passed to -cc */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500238/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239 * or kill. We will send them a signal every 10 ms until we can bind to all
240 * our ports. With 200 retries, that's about 2 seconds.
241 */
242#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243static int *oldpids = NULL;
244static int oldpids_sig; /* use USR1 or TERM */
245
Olivier Houchardf73629d2017-04-05 22:33:04 +0200246/* Path to the unix socket we use to retrieve listener sockets from the old process */
247static const char *old_unixsocket;
248
William Lallemandcb11fd22017-06-01 17:38:52 +0200249int atexit_flag = 0;
250
Willy Tarreaubb545b42010-08-25 12:58:59 +0200251int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252const int zero = 0;
253const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200254const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200255
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100256char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200257char *localpeer = NULL;
Willy Tarreau76871a42022-03-08 16:01:40 +0100258static char *kwd_dump = NULL; // list of keyword dumps to produce
Willy Tarreaubaaee002006-06-26 02:48:02 +0200259
William Lallemand00417412020-06-05 14:08:41 +0200260static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200261
William Lallemandbc193052018-09-11 10:06:26 +0200262struct list proc_list = LIST_HEAD_INIT(proc_list);
263
264int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100265unsigned int rlim_fd_cur_at_boot = 0;
266unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200267
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100268/* per-boot randomness */
269unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
270
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200271/* takes the thread config in argument or NULL for any thread */
William Lallemandb3f2be32018-09-11 10:06:18 +0200272static void *run_thread_poll_loop(void *data);
273
Willy Tarreauff055502014-04-28 22:27:06 +0200274/* bitfield of a few warnings to emit just once (WARN_*) */
275unsigned int warned = 0;
276
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200277/* set if experimental features have been used for the current process */
Willy Tarreauedd42682022-02-25 10:10:00 +0100278unsigned int tainted = 0;
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200279
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200280unsigned int experimental_directives_allowed = 0;
281
282int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
283 char **errmsg)
284{
285 if (kw->flags & KWF_EXPERIMENTAL) {
286 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200287 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 +0200288 file, linenum, kw->kw);
289 return 1;
290 }
291 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
292 }
293
294 return 0;
295}
296
William Lallemande7361152018-10-26 14:47:36 +0200297/* master CLI configuration (-S flag) */
298struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100299
300/* These are strings to be reported in the output of "haproxy -vv". They may
301 * either be constants (in which case must_free must be zero) or dynamically
302 * allocated strings to pass to free() on exit, and in this case must_free
303 * must be non-zero.
304 */
305struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
306struct build_opts_str {
307 struct list list;
308 const char *str;
309 int must_free;
310};
311
Willy Tarreaubaaee002006-06-26 02:48:02 +0200312/*********************************************************************/
313/* general purpose functions ***************************************/
314/*********************************************************************/
315
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100316/* used to register some build option strings at boot. Set must_free to
317 * non-zero if the string must be freed upon exit.
318 */
319void hap_register_build_opts(const char *str, int must_free)
320{
321 struct build_opts_str *b;
322
323 b = calloc(1, sizeof(*b));
324 if (!b) {
325 fprintf(stderr, "out of memory\n");
326 exit(1);
327 }
328 b->str = str;
329 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200330 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100331}
332
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200333#define VERSION_MAX_ELTS 7
334
335/* This function splits an haproxy version string into an array of integers.
336 * The syntax of the supported version string is the following:
337 *
338 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
339 *
340 * This validates for example:
341 * 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
342 * 2.4-dev18-f6818d-20
343 *
344 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
345 * one fixed place in the array. The tags take a numeric value called <e> which
346 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
347 * considered as zero (henxe 1.5 and 1.5.0 are the same).
348 *
349 * The resulting values are:
350 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
351 * 1.2.1 1, 2, 1, 0, 3, 0, 0
352 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
353 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
354 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
355 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
356 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
357 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
358 *
359 * The function returns non-zero if the conversion succeeded, or zero if it
360 * failed.
361 */
362int split_version(const char *version, unsigned int *value)
363{
364 const char *p, *s;
365 char *error;
366 int nelts;
367
368 /* Initialize array with zeroes */
369 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
370 value[nelts] = 0;
371 value[4] = 3;
372
373 p = version;
374
375 /* If the version number is empty, return false */
376 if (*p == '\0')
377 return 0;
378
379 /* Convert first number <a> */
380 value[0] = strtol(p, &error, 10);
381 p = error + 1;
382 if (*error == '\0')
383 return 1;
384 if (*error == '-')
385 goto split_version_tag;
386 if (*error != '.')
387 return 0;
388
389 /* Convert first number <b> */
390 value[1] = strtol(p, &error, 10);
391 p = error + 1;
392 if (*error == '\0')
393 return 1;
394 if (*error == '-')
395 goto split_version_tag;
396 if (*error != '.')
397 return 0;
398
399 /* Convert first number <c> */
400 value[2] = strtol(p, &error, 10);
401 p = error + 1;
402 if (*error == '\0')
403 return 1;
404 if (*error == '-')
405 goto split_version_tag;
406 if (*error != '.')
407 return 0;
408
409 /* Convert first number <d> */
410 value[3] = strtol(p, &error, 10);
411 p = error + 1;
412 if (*error == '\0')
413 return 1;
414 if (*error != '-')
415 return 0;
416
417 split_version_tag:
418 /* Check for commit number */
419 if (*p >= '0' && *p <= '9')
420 goto split_version_commit;
421
422 /* Read tag */
423 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
424 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
425 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
426 else
427 goto split_version_commit;
428
429 /* Convert tag number */
430 value[5] = strtol(p, &error, 10);
431 p = error + 1;
432 if (*error == '\0')
433 return 1;
434 if (*error != '-')
435 return 0;
436
437 split_version_commit:
438 /* Search the last "-" */
439 s = strrchr(p, '-');
440 if (s) {
441 s++;
442 if (*s == '\0')
443 return 0;
444 value[6] = strtol(s, &error, 10);
445 if (*error != '\0')
446 value[6] = 0;
447 return 1;
448 }
449
450 /* convert the version */
451 value[6] = strtol(p, &error, 10);
452 if (*error != '\0')
453 value[6] = 0;
454
455 return 1;
456}
457
458/* This function compares the current haproxy version with an arbitrary version
459 * string. It returns:
460 * -1 : the version in argument is older than the current haproxy version
461 * 0 : the version in argument is the same as the current haproxy version
462 * 1 : the version in argument is newer than the current haproxy version
463 *
464 * Or some errors:
465 * -2 : the current haproxy version is not parsable
466 * -3 : the version in argument is not parsable
467 */
468int compare_current_version(const char *version)
469{
470 unsigned int loc[VERSION_MAX_ELTS];
471 unsigned int mod[VERSION_MAX_ELTS];
472 int i;
473
474 /* split versions */
475 if (!split_version(haproxy_version, loc))
476 return -2;
477 if (!split_version(version, mod))
478 return -3;
479
480 /* compare versions */
481 for (i = 0; i < VERSION_MAX_ELTS; i++) {
482 if (mod[i] < loc[i])
483 return -1;
484 else if (mod[i] > loc[i])
485 return 1;
486 }
487 return 0;
488}
489
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100490static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200491{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200492 struct utsname utsname;
493
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200494 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100495 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100496
497 if (strlen(PRODUCT_URL_BUGS) > 0) {
498 char base_version[20];
499 int dots = 0;
500 char *del;
501
502 /* only retrieve the base version without distro-specific extensions */
503 for (del = haproxy_version; *del; del++) {
504 if (*del == '.')
505 dots++;
506 else if (*del < '0' || *del > '9')
507 break;
508 }
509
510 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
511 if (dots < 2)
512 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
513 else
514 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
515 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200516
517 if (uname(&utsname) == 0) {
518 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
519 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200520}
521
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100522static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100523{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100524 struct build_opts_str *item;
525
Willy Tarreau7b066db2007-12-02 11:28:59 +0100526 printf("Build options :"
527#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100528 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100529#endif
530#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100531 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100532#endif
533#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100534 "\n CC = " BUILD_CC
535#endif
536#ifdef BUILD_CFLAGS
537 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100538#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100539#ifdef BUILD_OPTIONS
540 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100541#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100542#ifdef BUILD_DEBUG
543 "\n DEBUG = " BUILD_DEBUG
544#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100545#ifdef BUILD_FEATURES
546 "\n\nFeature list : " BUILD_FEATURES
547#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200548 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100549 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200550 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100551 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200552
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100553 list_for_each_entry(item, &build_opts_list, list) {
554 puts(item->str);
555 }
556
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100557 putchar('\n');
558
Willy Tarreaube5b6852009-10-03 18:57:08 +0200559 list_pollers(stdout);
560 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200561 list_mux_proto(stdout);
562 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100563 list_services(stdout);
564 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100565 list_filters(stdout);
566 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100567}
568
Willy Tarreaubaaee002006-06-26 02:48:02 +0200569/*
570 * This function prints the command line usage and exits
571 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100572static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200573{
574 display_version();
575 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200576 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200578 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100579 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreauf4b79c42022-02-23 15:20:53 +0100581 " -dM[<byte>,help,...] debug memory (default: poison with <byte>/0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200583 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200584 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100585#if defined(USE_SYSTEMD)
586 " -Ws master-worker mode with systemd notify support.\n"
587#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200588 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200589 " -c check mode : only check config files and exit\n"
Maximilian Maderfc0cceb2021-06-06 00:50:22 +0200590 " -cc check condition : evaluate a condition and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100591 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200592 " -m limits the usable amount of memory (in MB)\n"
593 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200594 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 " -p writes pids of all children to this file\n"
Erwan Le Goasf30c5d72022-09-29 10:34:04 +0200596 " -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 +0200597#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200598 " -de disables epoll() usage even when available\n"
599#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200600#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200601 " -dk disables kqueue() usage even when available\n"
602#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200603#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000604 " -dv disables event ports usage even when available\n"
605#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200606#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 " -dp disables poll() usage even when available\n"
608#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200609#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100610 " -dS disables splice usage (broken on old kernels)\n"
611#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200612#if defined(USE_GETADDRINFO)
613 " -dG disables getaddrinfo() usage\n"
614#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000615#if defined(SO_REUSEPORT)
616 " -dR disables SO_REUSEPORT usage\n"
617#endif
Willy Tarreau654726d2021-12-28 15:43:11 +0100618#if defined(HA_HAVE_DUMP_LIBS)
619 " -dL dumps loaded object files after config checks\n"
620#endif
Willy Tarreau76871a42022-03-08 16:01:40 +0100621 " -dK{class[,...]} dump registered keywords (use 'help' for list)\n"
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100622 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100623 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200624 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200625 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Christopher Faulet678a4ce2023-02-14 16:12:54 +0100626 " -dF disable fast-forward\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200627 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200628 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200629 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200630 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100631 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632 exit(1);
633}
634
635
636
637/*********************************************************************/
638/* more specific functions ***************************************/
639/*********************************************************************/
640
William Lallemand73b85e72017-06-01 17:38:51 +0200641/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
642 * pids the signal was correctly delivered to.
643 */
William Lallemande25473c2019-04-01 11:29:56 +0200644int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200645{
646 int p;
647 int ret = 0;
648 for (p = 0; p < nb_oldpids; p++)
649 if (kill(oldpids[p], sig) == 0)
650 ret++;
651 return ret;
652}
653
William Lallemand75ea0a02017-11-15 19:02:58 +0100654/*
William Lallemand73b85e72017-06-01 17:38:51 +0200655 * remove a pid forom the olpid array and decrease nb_oldpids
656 * return 1 pid was found otherwise return 0
657 */
658
659int delete_oldpid(int pid)
660{
661 int i;
662
663 for (i = 0; i < nb_oldpids; i++) {
664 if (oldpids[i] == pid) {
665 oldpids[i] = oldpids[nb_oldpids - 1];
666 oldpids[nb_oldpids - 1] = 0;
667 nb_oldpids--;
668 return 1;
669 }
670 }
671 return 0;
672}
673
William Lallemand85b0bd92017-06-01 17:38:53 +0200674
William Lallemand73b85e72017-06-01 17:38:51 +0200675/*
676 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800677 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200678 */
William Lallemandfab0fdc2021-11-09 18:01:22 +0100679static void mworker_reexec()
William Lallemand73b85e72017-06-01 17:38:51 +0200680{
William Lallemand00417412020-06-05 14:08:41 +0200681 char **next_argv = NULL;
682 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200683 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200684 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200685 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100686 struct rlimit limit;
William Lallemand2be557f2021-11-24 18:45:37 +0100687 struct mworker_proc *current_child = NULL;
William Lallemand73b85e72017-06-01 17:38:51 +0200688
689 mworker_block_signals();
William Lallemand73b85e72017-06-01 17:38:51 +0200690 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
691
William Lallemand55a921c2022-01-28 21:17:30 +0100692 mworker_cleanup_proc();
William Lallemandbc193052018-09-11 10:06:26 +0200693 mworker_proc_list_to_env(); /* put the children description in the env */
694
William Lallemandc4810b82021-11-18 10:51:30 +0100695 /* ensure that we close correctly every listeners before reexecuting */
696 mworker_cleanlisteners();
697
William Lallemand7c756a82018-11-26 11:53:40 +0100698 /* during the reload we must ensure that every FDs that can't be
699 * reuse (ie those that are not referenced in the proc_list)
700 * are closed or they will leak. */
701
702 /* close the listeners FD */
703 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200704
William Lallemand67e371e2021-11-25 10:03:44 +0100705 if (fdtab)
706 deinit_pollers();
William Lallemandefd95472021-11-26 14:43:57 +0100707
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500708#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200709 /* close random device FDs */
710 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100711#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100712
Willy Tarreau8dca1952019-03-01 10:21:55 +0100713 /* restore the initial FD limits */
714 limit.rlim_cur = rlim_fd_cur_at_boot;
715 limit.rlim_max = rlim_fd_max_at_boot;
Willy Tarreauc06557c2022-09-22 16:12:08 +0200716 if (raise_rlim_nofile(&limit, &limit) != 0) {
Willy Tarreau8dca1952019-03-01 10:21:55 +0100717 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
718 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
719 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
720 }
721
William Lallemand73b85e72017-06-01 17:38:51 +0200722 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200723 while (old_argv[old_argc])
724 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200725
William Lallemand85b0bd92017-06-01 17:38:53 +0200726 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200727 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200728 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200729 if (next_argv == NULL)
730 goto alloc_error;
731
William Lallemand00417412020-06-05 14:08:41 +0200732 /* copy the program name */
733 next_argv[next_argc++] = old_argv[0];
734
735 /* insert the new options just after argv[0] in case we have a -- */
736
William Lallemandbefab9e2021-11-25 00:49:19 +0100737 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
738 /* add -sf <PID>* to argv */
739 if (mworker_child_nb() > 0) {
740 struct mworker_proc *child;
William Lallemand3f128872019-04-01 11:29:59 +0200741
William Lallemandbefab9e2021-11-25 00:49:19 +0100742 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200743
William Lallemandbefab9e2021-11-25 00:49:19 +0100744 list_for_each_entry(child, &proc_list, list) {
745 if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
746 current_child = child;
William Lallemand2be557f2021-11-24 18:45:37 +0100747
William Lallemandbefab9e2021-11-25 00:49:19 +0100748 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
749 continue;
750 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
751 goto alloc_error;
752 msg = NULL;
753 }
William Lallemand73b85e72017-06-01 17:38:51 +0200754 }
William Lallemand2be557f2021-11-24 18:45:37 +0100755
756 if (current_child) {
757 /* add the -x option with the socketpair of the current worker */
758 next_argv[next_argc++] = "-x";
759 if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
760 goto alloc_error;
761 msg = NULL;
762 }
William Lallemand85b0bd92017-06-01 17:38:53 +0200763 }
764
William Lallemand00417412020-06-05 14:08:41 +0200765 /* copy the previous options */
766 for (i = 1; i < old_argc; i++)
767 next_argv[next_argc++] = old_argv[i];
768
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200769 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100770 execvp(next_argv[0], next_argv);
Christopher Faulet767a84b2017-11-24 16:50:31 +0100771 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100772 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100773 return;
774
William Lallemand73b85e72017-06-01 17:38:51 +0200775alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100776 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800777 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200778 return;
779}
780
William Lallemandfab0fdc2021-11-09 18:01:22 +0100781/* reexec haproxy in waitmode */
782static void mworker_reexec_waitmode()
783{
784 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
785 mworker_reexec();
786}
787
788/* reload haproxy and emit a warning */
789void mworker_reload()
790{
William Lallemandad221f42021-11-09 18:43:59 +0100791 struct mworker_proc *child;
William Lallemandefd95472021-11-26 14:43:57 +0100792 struct per_thread_deinit_fct *ptdf;
William Lallemandad221f42021-11-09 18:43:59 +0100793
William Lallemand836bda22021-11-09 18:16:47 +0100794 ha_notice("Reloading HAProxy\n");
William Lallemandad221f42021-11-09 18:43:59 +0100795
William Lallemandefd95472021-11-26 14:43:57 +0100796 /* close the poller FD and the thread waker pipe FD */
797 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
798 ptdf->fct();
799
William Lallemandad221f42021-11-09 18:43:59 +0100800 /* increment the number of reloads */
801 list_for_each_entry(child, &proc_list, list) {
802 child->reloads++;
803 }
804
William Lallemanda46a99e2022-07-07 14:00:36 +0200805#if defined(USE_SYSTEMD)
806 if (global.tune.options & GTUNE_USE_SYSTEMD)
807 sd_notify(0, "RELOADING=1\nSTATUS=Reloading Configuration.\n");
808#endif
William Lallemandfab0fdc2021-11-09 18:01:22 +0100809 mworker_reexec();
810}
811
William Lallemandb3f2be32018-09-11 10:06:18 +0200812static void mworker_loop()
813{
814
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200815 /* Busy polling makes no sense in the master :-) */
816 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200817
William Lallemandbc193052018-09-11 10:06:26 +0200818
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100819 signal_unregister(SIGTTIN);
820 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100821 signal_unregister(SIGUSR1);
822 signal_unregister(SIGHUP);
823 signal_unregister(SIGQUIT);
824
William Lallemandb3f2be32018-09-11 10:06:18 +0200825 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
826 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100827 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
828 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200829 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
830 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
831 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
832 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
833
834 mworker_unblock_signals();
William Lallemand27f3fa52018-12-06 14:05:20 +0100835 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200836
William Lallemandbc193052018-09-11 10:06:26 +0200837 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
838 some SIGCHLD were lost */
839
William Lallemandb3f2be32018-09-11 10:06:18 +0200840 jobs++; /* this is the "master" job, we want to take care of the
841 signals even if there is no listener so the poll loop don't
842 leave */
843
844 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200845 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200846}
William Lallemandcb11fd22017-06-01 17:38:52 +0200847
848/*
849 * Reexec the process in failure mode, instead of exiting
850 */
851void reexec_on_failure()
852{
William Lallemand68836742021-11-10 10:49:06 +0100853 struct mworker_proc *child;
854
William Lallemandcb11fd22017-06-01 17:38:52 +0200855 if (!atexit_flag)
856 return;
William Lallemand68836742021-11-10 10:49:06 +0100857
858 /* get the info of the children in the env */
859 if (mworker_env_to_proc_list() < 0) {
860 exit(EXIT_FAILURE);
861 }
862
863 /* increment the number of failed reloads */
864 list_for_each_entry(child, &proc_list, list) {
865 child->failedreloads++;
866 }
867
Willy Tarreaue08acae2022-01-28 18:40:06 +0100868 /* do not keep unused FDs retrieved from the previous process */
869 sock_drop_unused_old_sockets();
870
William Lallemandfab0fdc2021-11-09 18:01:22 +0100871 usermsgs_clr(NULL);
William Lallemand68192b22022-09-24 15:44:42 +0200872 setenv("HAPROXY_LOAD_SUCCESS", "0", 1);
William Lallemand836bda22021-11-09 18:16:47 +0100873 ha_warning("Loading failure!\n");
William Lallemanda46a99e2022-07-07 14:00:36 +0200874#if defined(USE_SYSTEMD)
875 /* the sd_notify API is not able to send a reload failure signal. So
876 * the READY=1 signal still need to be sent */
877 if (global.tune.options & GTUNE_USE_SYSTEMD)
878 sd_notify(0, "READY=1\nSTATUS=Reload failed!\n");
879#endif
880
William Lallemandfab0fdc2021-11-09 18:01:22 +0100881 mworker_reexec_waitmode();
William Lallemandcb11fd22017-06-01 17:38:52 +0200882}
William Lallemand73b85e72017-06-01 17:38:51 +0200883
William Lallemand40db4ae2022-12-07 15:03:55 +0100884/*
885 * Exit with an error message upon a wait-mode failure.
886 */
887void exit_on_waitmode_failure()
888{
889 if (!atexit_flag)
890 return;
891
892 ha_alert("Non-recoverable mworker wait-mode error, exiting.\n");
893}
894
William Lallemand73b85e72017-06-01 17:38:51 +0200895
896/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200897 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
898 * a signal zero to all subscribers. This means that it's as easy as
899 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100901static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902{
903 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200904 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100905 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906}
907
908/*
909 * upon SIGTTOU, we pause everything
910 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100911static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200912{
Willy Tarreau775e0012020-09-24 16:36:26 +0200913 if (protocol_pause_all() & ERR_FATAL) {
914 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200915 ha_warning("%s", msg);
916 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200917 soft_stop();
918 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100919 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920}
921
922/*
923 * upon SIGTTIN, let's have a soft stop.
924 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100925static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926{
Willy Tarreau775e0012020-09-24 16:36:26 +0200927 if (protocol_resume_all() & ERR_FATAL) {
928 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 +0200929 ha_warning("%s", msg);
930 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200931 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932}
933
934/*
935 * this function dumps every server's state when the process receives SIGHUP.
936 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100937static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100939 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940
Christopher Faulet767a84b2017-11-24 16:50:31 +0100941 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 while (p) {
943 struct server *s = p->srv;
944
945 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
946 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100947 chunk_printf(&trash,
948 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
949 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200950 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200951 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200952 ha_warning("%s\n", trash.area);
953 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 s = s->next;
955 }
956
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200957 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
958 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100959 chunk_printf(&trash,
960 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
961 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200962 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 +0200963 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100964 chunk_printf(&trash,
965 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
966 p->id,
967 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200968 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 +0200969 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100970 chunk_printf(&trash,
971 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
972 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
973 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200974 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 +0200975 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200976 ha_warning("%s\n", trash.area);
977 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200978
979 p = p->next;
980 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200981}
982
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100983static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200984{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200985 /* dump memory usage then free everything possible */
986 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100987 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988}
989
William Lallemande1340412017-12-28 16:09:36 +0100990/*
991 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
992 * If <fd> < 0, it opens /dev/null and use it to dup
993 *
994 * In the case of chrooting, you have to open /dev/null before the chroot, and
995 * pass the <fd> to this function
996 */
997static void stdio_quiet(int fd)
998{
999 if (fd < 0)
1000 fd = open("/dev/null", O_RDWR, 0);
1001
1002 if (fd > -1) {
1003 fclose(stdin);
1004 fclose(stdout);
1005 fclose(stderr);
1006
1007 dup2(fd, 0);
1008 dup2(fd, 1);
1009 dup2(fd, 2);
1010 if (fd > 2)
1011 close(fd);
1012 return;
1013 }
1014
1015 ha_alert("Cannot open /dev/null\n");
1016 exit(EXIT_FAILURE);
1017}
1018
1019
Joseph Herlant03420902018-11-15 10:41:50 -08001020/* This function checks if cfg_cfgfiles contains directories.
1021 * If it finds one, it adds all the files (and only files) it contains
1022 * in cfg_cfgfiles in place of the directory (and removes the directory).
1023 * It adds the files in lexical order.
1024 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001025 * It doesn't add files with name starting with '.'
1026 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001027static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001028{
1029 struct wordlist *wl, *wlb;
1030 char *err = NULL;
1031
1032 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1033 struct stat file_stat;
1034 struct dirent **dir_entries = NULL;
1035 int dir_entries_nb;
1036 int dir_entries_it;
1037
1038 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001039 ha_alert("Cannot open configuration file/directory %s : %s\n",
1040 wl->s,
1041 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001042 exit(1);
1043 }
1044
1045 if (!S_ISDIR(file_stat.st_mode))
1046 continue;
1047
1048 /* from this point wl->s is a directory */
1049
1050 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1051 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001052 ha_alert("Cannot open configuration directory %s : %s\n",
1053 wl->s,
1054 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001055 exit(1);
1056 }
1057
1058 /* for each element in the directory wl->s */
1059 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1060 struct dirent *dir_entry = dir_entries[dir_entries_it];
1061 char *filename = NULL;
1062 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1063
1064 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001065 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001066 */
1067 if (dir_entry->d_name[0] == '.' ||
1068 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1069 goto next_dir_entry;
1070
1071 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001072 ha_alert("Cannot load configuration files %s : out of memory.\n",
1073 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001074 exit(1);
1075 }
1076
1077 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001078 ha_alert("Cannot open configuration file %s : %s\n",
1079 wl->s,
1080 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001081 exit(1);
1082 }
1083
1084 /* don't add anything else than regular file in cfg_cfgfiles
1085 * this way we avoid loops
1086 */
1087 if (!S_ISREG(file_stat.st_mode))
1088 goto next_dir_entry;
1089
1090 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001091 ha_alert("Cannot load configuration files %s : %s\n",
1092 filename,
1093 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001094 exit(1);
1095 }
1096
1097next_dir_entry:
1098 free(filename);
1099 free(dir_entry);
1100 }
1101
1102 free(dir_entries);
1103
1104 /* remove the current directory (wl) from cfg_cfgfiles */
1105 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001106 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001107 free(wl);
1108 }
1109
1110 free(err);
1111}
1112
Willy Tarreaubaaee002006-06-26 02:48:02 +02001113/*
William Lallemand73b85e72017-06-01 17:38:51 +02001114 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001115 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001116 * Return an allocated copy of argv
1117 */
1118
1119static char **copy_argv(int argc, char **argv)
1120{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001121 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001122
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001123 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001124 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001125 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001126 return NULL;
1127 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001128 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001129
William Lallemanddf6c5a82020-06-04 17:40:23 +02001130 /* first copy argv[0] */
1131 *newargv++ = *argv++;
1132 argc--;
1133
1134 while (argc > 0) {
1135 if (**argv != '-') {
1136 /* non options are copied but will fail in the argument parser */
1137 *newargv++ = *argv++;
1138 argc--;
1139
1140 } else {
1141 char *flag;
1142
1143 flag = *argv + 1;
1144
1145 if (flag[0] == '-' && flag[1] == 0) {
1146 /* "--\0" copy every arguments till the end of argv */
1147 *newargv++ = *argv++;
1148 argc--;
1149
1150 while (argc > 0) {
1151 *newargv++ = *argv++;
1152 argc--;
1153 }
1154 } else {
1155 switch (*flag) {
1156 case 's':
1157 /* -sf / -st and their parameters are ignored */
1158 if (flag[1] == 'f' || flag[1] == 't') {
1159 argc--;
1160 argv++;
1161 /* The list can't contain a negative value since the only
1162 way to know the end of this list is by looking for the
1163 next option or the end of the options */
1164 while (argc > 0 && argv[0][0] != '-') {
1165 argc--;
1166 argv++;
1167 }
William Lallemand398da622020-09-02 16:12:23 +02001168 } else {
1169 argc--;
1170 argv++;
1171
William Lallemanddf6c5a82020-06-04 17:40:23 +02001172 }
1173 break;
1174
1175 case 'x':
1176 /* this option and its parameter are ignored */
1177 argc--;
1178 argv++;
1179 if (argc > 0) {
1180 argc--;
1181 argv++;
1182 }
1183 break;
1184
1185 case 'C':
1186 case 'n':
1187 case 'm':
1188 case 'N':
1189 case 'L':
1190 case 'f':
1191 case 'p':
1192 case 'S':
1193 /* these options have only 1 parameter which must be copied and can start with a '-' */
1194 *newargv++ = *argv++;
1195 argc--;
1196 if (argc == 0)
1197 goto error;
1198 *newargv++ = *argv++;
1199 argc--;
1200 break;
1201 default:
1202 /* for other options just copy them without parameters, this is also done
1203 * for options like "--foo", but this will fail in the argument parser.
1204 * */
1205 *newargv++ = *argv++;
1206 argc--;
1207 break;
1208 }
William Lallemand73b85e72017-06-01 17:38:51 +02001209 }
1210 }
William Lallemand73b85e72017-06-01 17:38:51 +02001211 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001212
William Lallemanddf6c5a82020-06-04 17:40:23 +02001213 return retargv;
1214
1215error:
1216 free(retargv);
1217 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001218}
1219
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001220
1221/* Performs basic random seed initialization. The main issue with this is that
1222 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1223 * which means that there will only be 4 billion possible random sequences once
1224 * srandom() is called, regardless of the internal state. Not calling it is
1225 * even worse as we'll always produce the same randoms sequences. What we do
1226 * here is to create an initial sequence from various entropy sources, hash it
1227 * using SHA1 and keep the resulting 160 bits available globally.
1228 *
1229 * We initialize the current process with the first 32 bits before starting the
1230 * polling loop, where all this will be changed to have process specific and
1231 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001232 *
1233 * Before starting threads, it's still possible to call random() as srandom()
1234 * is initialized from this, but after threads and/or processes are started,
1235 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001236 */
1237static void ha_random_boot(char *const *argv)
1238{
1239 unsigned char message[256];
1240 unsigned char *m = message;
1241 struct timeval tv;
1242 blk_SHA_CTX ctx;
1243 unsigned long l;
1244 int fd;
1245 int i;
1246
1247 /* start with current time as pseudo-random seed */
1248 gettimeofday(&tv, NULL);
1249 write_u32(m, tv.tv_sec); m += 4;
1250 write_u32(m, tv.tv_usec); m += 4;
1251
1252 /* PID and PPID add some OS-based randomness */
1253 write_u16(m, getpid()); m += 2;
1254 write_u16(m, getppid()); m += 2;
1255
1256 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1257 fd = open("/dev/urandom", O_RDONLY);
1258 if (fd >= 0) {
1259 i = read(fd, m, 20);
1260 if (i > 0)
1261 m += i;
1262 close(fd);
1263 }
1264
1265 /* take up to 160 bits bytes from openssl (non-blocking) */
1266#ifdef USE_OPENSSL
1267 if (RAND_bytes(m, 20) == 1)
1268 m += 20;
1269#endif
1270
1271 /* take 160 bits from existing random in case it was already initialized */
1272 for (i = 0; i < 5; i++) {
1273 write_u32(m, random());
1274 m += 4;
1275 }
1276
1277 /* stack address (benefit form operating system's ASLR) */
1278 l = (unsigned long)&m;
1279 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1280
1281 /* argv address (benefit form operating system's ASLR) */
1282 l = (unsigned long)&argv;
1283 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1284
1285 /* use tv_usec again after all the operations above */
1286 gettimeofday(&tv, NULL);
1287 write_u32(m, tv.tv_usec); m += 4;
1288
1289 /*
1290 * At this point, ~84-92 bytes have been used
1291 */
1292
1293 /* finish with the hostname */
1294 strncpy((char *)m, hostname, message + sizeof(message) - m);
1295 m += strlen(hostname);
1296
1297 /* total message length */
1298 l = m - message;
1299
1300 memset(&ctx, 0, sizeof(ctx));
1301 blk_SHA1_Init(&ctx);
1302 blk_SHA1_Update(&ctx, message, l);
1303 blk_SHA1_Final(boot_seed, &ctx);
1304
1305 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001306 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001307}
1308
Willy Tarreau5a023f02019-03-01 14:19:31 +01001309/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1310 * setting, and returns it. It may return -1 meaning "unlimited" if some
1311 * unlimited proxies have been found and the global.maxconn value is not yet
1312 * set. It may also return a value greater than maxconn if it's not yet set.
1313 * Note that a value of zero means there is no need for pipes. -1 is never
1314 * returned if global.maxconn is valid.
1315 */
1316static int compute_ideal_maxpipes()
1317{
1318 struct proxy *cur;
1319 int nbfe = 0, nbbe = 0;
1320 int unlimited = 0;
1321 int pipes;
1322 int max;
1323
1324 for (cur = proxies_list; cur; cur = cur->next) {
1325 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1326 if (cur->cap & PR_CAP_FE) {
1327 max = cur->maxconn;
1328 nbfe += max;
1329 if (!max) {
1330 unlimited = 1;
1331 break;
1332 }
1333 }
1334 if (cur->cap & PR_CAP_BE) {
1335 max = cur->fullconn ? cur->fullconn : global.maxconn;
1336 nbbe += max;
1337 if (!max) {
1338 unlimited = 1;
1339 break;
1340 }
1341 }
1342 }
1343 }
1344
1345 pipes = MAX(nbfe, nbbe);
1346 if (global.maxconn) {
1347 if (pipes > global.maxconn || unlimited)
1348 pipes = global.maxconn;
1349 } else if (unlimited) {
1350 pipes = -1;
1351 }
1352
1353 return pipes >= 4 ? pipes / 4 : pipes;
1354}
1355
Willy Tarreauac350932019-03-01 15:43:14 +01001356/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1357 * rlimits and computes an ideal maxconn. It's meant to be called only when
1358 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001359 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1360 * default 100) is returned as it is expected that it will even run on tight
1361 * environments, and will maintain compatibility with previous packages that
1362 * used to rely on this value as the default one. The system will emit a
1363 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001364 */
1365static int compute_ideal_maxconn()
1366{
1367 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1368 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1369 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001370 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001371 int maxconn;
1372
1373 /* we have to take into account these elements :
1374 * - number of engine_fds, which inflates the number of FD needed per
1375 * connection by this number.
1376 * - number of pipes per connection on average : for the unlimited
1377 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1378 * fixed value of 2*pipes.
1379 * - two FDs per connection
1380 */
1381
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02001382 if (global.fd_hard_limit && remain > global.fd_hard_limit)
1383 remain = global.fd_hard_limit;
1384
Willy Tarreauac350932019-03-01 15:43:14 +01001385 /* subtract listeners and checks */
1386 remain -= global.maxsock;
1387
Willy Tarreau3f200852019-03-14 19:13:17 +01001388 /* one epoll_fd/kqueue_fd per thread */
1389 remain -= global.nbthread;
1390
1391 /* one wake-up pipe (2 fd) per thread */
1392 remain -= 2 * global.nbthread;
1393
Willy Tarreauac350932019-03-01 15:43:14 +01001394 /* Fixed pipes values : we only subtract them if they're not larger
1395 * than the remaining FDs because pipes are optional.
1396 */
1397 if (pipes >= 0 && pipes * 2 < remain)
1398 remain -= pipes * 2;
1399
1400 if (pipes < 0) {
1401 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1402 * = maxconn * (2 + 0.5 + engine_fds)
1403 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1404 */
1405 maxconn = 2 * remain / (5 + 2 * engine_fds);
1406 } else {
1407 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1408 * = maxconn * (2 + engine_fds)
1409 */
1410 maxconn = remain / (2 + engine_fds);
1411 }
1412
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001413 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001414}
1415
Willy Tarreaua409f302020-03-10 17:08:53 +01001416/* computes the estimated maxsock value for the given maxconn based on the
1417 * possibly set global.maxpipes and existing partial global.maxsock. It may
1418 * temporarily change global.maxconn for the time needed to propagate the
1419 * computations, and will reset it.
1420 */
1421static int compute_ideal_maxsock(int maxconn)
1422{
1423 int maxpipes = global.maxpipes;
1424 int maxsock = global.maxsock;
1425
1426
1427 if (!maxpipes) {
1428 int old_maxconn = global.maxconn;
1429
1430 global.maxconn = maxconn;
1431 maxpipes = compute_ideal_maxpipes();
1432 global.maxconn = old_maxconn;
1433 }
1434
1435 maxsock += maxconn * 2; /* each connection needs two sockets */
1436 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1437 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1438 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1439
1440 /* compute fd used by async engines */
1441 if (global.ssl_used_async_engines) {
1442 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1443
1444 maxsock += maxconn * sides * global.ssl_used_async_engines;
1445 }
1446 return maxsock;
1447}
1448
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001449/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001450 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1451 * value is accepted, non-zero otherwise. This is used to determine if an
1452 * automatic limit may be applied or not. When it is not, the caller knows that
1453 * the highest we can do is the rlim_max at boot. In case of error, we return
1454 * that the setting is possible, so that we defer the error processing to the
1455 * final stage in charge of enforcing this.
1456 */
1457static int check_if_maxsock_permitted(int maxsock)
1458{
1459 struct rlimit orig_limit, test_limit;
1460 int ret;
1461
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02001462 if (global.fd_hard_limit && maxsock > global.fd_hard_limit)
1463 return 0;
1464
Willy Tarreau304e17e2020-03-10 17:54:54 +01001465 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1466 return 1;
1467
1468 /* don't go further if we can't even set to what we have */
Willy Tarreauc06557c2022-09-22 16:12:08 +02001469 if (raise_rlim_nofile(NULL, &orig_limit) != 0)
Willy Tarreau304e17e2020-03-10 17:54:54 +01001470 return 1;
1471
1472 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1473 test_limit.rlim_cur = test_limit.rlim_max;
Willy Tarreauc06557c2022-09-22 16:12:08 +02001474 ret = raise_rlim_nofile(NULL, &test_limit);
Willy Tarreau304e17e2020-03-10 17:54:54 +01001475
Willy Tarreauc06557c2022-09-22 16:12:08 +02001476 if (raise_rlim_nofile(NULL, &orig_limit) != 0)
Willy Tarreau304e17e2020-03-10 17:54:54 +01001477 return 1;
1478
1479 return ret == 0;
1480}
1481
Willy Tarreau34527d52022-02-17 17:45:58 +01001482/* This performs th every basic early initialization at the end of the PREPARE
1483 * init stage. It may only assume that list heads are initialized, but not that
1484 * anything else is correct. It will initialize a number of variables that
1485 * depend on command line and will pre-parse the command line. If it fails, it
1486 * directly exits.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001487 */
Willy Tarreau34527d52022-02-17 17:45:58 +01001488static void init_early(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001489{
Kevinm48936af2010-12-22 16:08:21 +00001490 char *progname;
Willy Tarreau34527d52022-02-17 17:45:58 +01001491 char *tmp;
1492 int len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493
William Lallemandd4c0be62023-02-21 14:07:05 +01001494 setenv("HAPROXY_STARTUP_VERSION", HAPROXY_VERSION, 0);
1495
Willy Tarreau34527d52022-02-17 17:45:58 +01001496 /* First, let's initialize most global variables */
1497 totalconn = actconn = listeners = stopping = 0;
1498 killed = pid = 0;
1499
1500 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
1501 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Christopher Faulete3a5e352017-10-24 13:53:54 +02001502 global.mode = MODE_STARTING;
William Lallemand73b85e72017-06-01 17:38:51 +02001503
Willy Tarreau34527d52022-02-17 17:45:58 +01001504 /* if we were in mworker mode, we should restart in mworker mode */
1505 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1506 global.mode |= MODE_MWORKER;
David du Colombier7af46052012-05-16 14:16:48 +02001507
Willy Tarreau34527d52022-02-17 17:45:58 +01001508 /* initialize date, time, and pid */
1509 tzset();
1510 clock_init_process_date();
Willy Tarreau6093ba42023-02-07 15:52:14 +01001511 start_date = date;
Willy Tarreauc05d30e2023-04-28 14:50:29 +02001512 start_time_ns = now_ns;
Willy Tarreau34527d52022-02-17 17:45:58 +01001513 pid = getpid();
1514
1515 /* Set local host name and adjust some environment variables.
1516 * NB: POSIX does not make it mandatory for gethostname() to
1517 * NULL-terminate the string in case of truncation, and at least
1518 * FreeBSD appears not to do it.
Emeric Brun2b920a12010-09-23 18:30:22 +02001519 */
1520 memset(hostname, 0, sizeof(hostname));
1521 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001522
Willy Tarreau34527d52022-02-17 17:45:58 +01001523 /* preset some environment variables */
1524 localpeer = strdup(hostname);
1525 if (!localpeer || setenv("HAPROXY_LOCALPEER", localpeer, 1) < 0) {
Dragan Dosen4f014152020-06-18 16:56:47 +02001526 ha_alert("Cannot allocate memory for local peer.\n");
1527 exit(EXIT_FAILURE);
1528 }
Emeric Brun2b920a12010-09-23 18:30:22 +02001529
Willy Tarreau34527d52022-02-17 17:45:58 +01001530 /* Some CPU affinity stuff may have to be initialized */
1531#ifdef USE_CPU_AFFINITY
1532 {
Willy Tarreau5b093412022-07-08 09:38:30 +02001533 int g, i;
1534
1535 for (g = 0; g < MAX_TGROUPS; g++) {
1536 ha_cpuset_zero(&cpu_map[g].proc);
1537 ha_cpuset_zero(&cpu_map[g].proc_t1);
1538 for (i = 0; i < MAX_THREADS_PER_GROUP; ++i) {
1539 ha_cpuset_zero(&cpu_map[g].thread[i]);
1540 }
Willy Tarreau34527d52022-02-17 17:45:58 +01001541 }
1542 }
1543#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001544
Willy Tarreau34527d52022-02-17 17:45:58 +01001545 /* extract the program name from argv[0], it will be used for the logs
1546 * and error messages.
1547 */
1548 progname = *argv;
1549 while ((tmp = strchr(progname, '/')) != NULL)
1550 progname = tmp + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001551
Willy Tarreau34527d52022-02-17 17:45:58 +01001552 len = strlen(progname);
1553 progname = strdup(progname);
1554 if (!progname) {
1555 ha_alert("Cannot allocate memory for log_tag.\n");
1556 exit(EXIT_FAILURE);
1557 }
Willy Tarreau84310e22014-02-14 11:59:04 +01001558
Willy Tarreau34527d52022-02-17 17:45:58 +01001559 chunk_initlen(&global.log_tag, progname, len, len);
1560}
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001561
Willy Tarreau392524d2022-02-17 18:10:36 +01001562/* handles program arguments. Very minimal parsing is performed, variables are
1563 * fed with some values, and lists are completed with other ones. In case of
1564 * error, it will exit.
Willy Tarreau34527d52022-02-17 17:45:58 +01001565 */
Willy Tarreau392524d2022-02-17 18:10:36 +01001566static void init_args(int argc, char **argv)
Willy Tarreau34527d52022-02-17 17:45:58 +01001567{
Willy Tarreau34527d52022-02-17 17:45:58 +01001568 char *progname = global.log_tag.area;
Willy Tarreau392524d2022-02-17 18:10:36 +01001569 char *err_msg = NULL;
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001570
Willy Tarreau34527d52022-02-17 17:45:58 +01001571 /* pre-fill in the global tuning options before we let the cmdline
1572 * change them.
1573 */
Willy Tarreau43b78992009-01-25 15:42:27 +01001574 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001575#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001576 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001578#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001579 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001580#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001581#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001582 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001583#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001584#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001585 global.tune.options |= GTUNE_USE_EVPORTS;
1586#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001587#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001588 global.tune.options |= GTUNE_USE_SPLICE;
1589#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001590#if defined(USE_GETADDRINFO)
1591 global.tune.options |= GTUNE_USE_GAI;
1592#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001593#ifdef USE_THREAD
1594 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1595#endif
Amaury Denoyellee30f3782022-11-21 11:54:13 +01001596#ifdef USE_QUIC
1597 global.tune.options |= GTUNE_QUIC_SOCK_PER_CONN;
1598#endif
William Dauchya5194602020-03-28 19:29:58 +01001599 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600
Christopher Faulet2f7c82b2023-02-20 14:06:52 +01001601 global.tune.options |= GTUNE_USE_FAST_FWD; /* Use fast-forward by default */
1602
Willy Tarreau392524d2022-02-17 18:10:36 +01001603 /* keep a copy of original arguments for the master process */
1604 old_argv = copy_argv(argc, argv);
1605 if (!old_argv) {
1606 ha_alert("failed to copy argv.\n");
1607 exit(EXIT_FAILURE);
1608 }
1609
1610 /* skip program name and start */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001611 argc--; argv++;
1612 while (argc > 0) {
1613 char *flag;
1614
1615 if (**argv == '-') {
1616 flag = *argv+1;
1617
1618 /* 1 arg */
1619 if (*flag == 'v') {
1620 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001621 if (flag[1] == 'v') /* -vv */
1622 display_build_opts();
Tim Duesterhus77b3db02022-04-27 00:08:11 +02001623 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001624 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001625#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001626 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001627 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001628#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001629#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001630 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001631 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001632#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001633#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001634 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001635 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001636#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001637#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001638 else if (*flag == 'd' && flag[1] == 'v')
1639 global.tune.options &= ~GTUNE_USE_EVPORTS;
1640#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001641#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001642 else if (*flag == 'd' && flag[1] == 'S')
1643 global.tune.options &= ~GTUNE_USE_SPLICE;
1644#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001645#if defined(USE_GETADDRINFO)
1646 else if (*flag == 'd' && flag[1] == 'G')
1647 global.tune.options &= ~GTUNE_USE_GAI;
1648#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001649#if defined(SO_REUSEPORT)
1650 else if (*flag == 'd' && flag[1] == 'R')
Willy Tarreau785b89f2023-04-22 15:09:07 +02001651 protocol_clrf_all(PROTO_F_REUSEPORT_SUPPORTED);
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001652#endif
Christopher Faulet678a4ce2023-02-14 16:12:54 +01001653 else if (*flag == 'd' && flag[1] == 'F')
Christopher Faulet2f7c82b2023-02-20 14:06:52 +01001654 global.tune.options &= ~GTUNE_USE_FAST_FWD;
Emeric Brun850efd52014-01-29 12:24:34 +01001655 else if (*flag == 'd' && flag[1] == 'V')
1656 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001657 else if (*flag == 'V')
1658 arg_mode |= MODE_VERBOSE;
Erwan Le Goasb0c05012022-09-14 17:51:55 +02001659 else if (*flag == 'd' && flag[1] == 'C') {
Erwan Le Goasf30c5d72022-09-29 10:34:04 +02001660 char *end;
1661 char *key;
1662
1663 key = flag + 2;
1664 for (;key && *key; key = end) {
1665 end = strchr(key, ',');
1666 if (end)
1667 *(end++) = 0;
1668
1669 if (strcmp(key, "line") == 0)
1670 arg_mode |= MODE_DUMP_NB_L;
1671
1672 }
Erwan Le Goasb0c05012022-09-14 17:51:55 +02001673 arg_mode |= MODE_DUMP_CFG;
1674 HA_ATOMIC_STORE(&global.anon_key, atoll(flag + 2));
1675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676 else if (*flag == 'd' && flag[1] == 'b')
1677 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001678 else if (*flag == 'd' && flag[1] == 'D')
1679 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001680 else if (*flag == 'd' && flag[1] == 'W')
1681 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreauef301b72022-02-23 14:15:18 +01001682 else if (*flag == 'd' && flag[1] == 'M') {
Willy Tarreau1408b1f2022-02-18 18:54:40 +01001683 int ret = pool_parse_debugging(flag + 2, &err_msg);
1684
1685 if (ret <= -1) {
1686 if (ret < -1)
1687 ha_alert("-dM: %s\n", err_msg);
1688 else
1689 printf("%s\n", err_msg);
1690 ha_free(&err_msg);
1691 exit(ret < -1 ? EXIT_FAILURE : 0);
1692 } else if (ret == 0) {
1693 ha_warning("-dM: %s\n", err_msg);
1694 ha_free(&err_msg);
1695 }
Willy Tarreauef301b72022-02-23 14:15:18 +01001696 }
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001697 else if (*flag == 'd' && flag[1] == 'r')
1698 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreau654726d2021-12-28 15:43:11 +01001699#if defined(HA_HAVE_DUMP_LIBS)
1700 else if (*flag == 'd' && flag[1] == 'L')
1701 arg_mode |= MODE_DUMP_LIBS;
1702#endif
Willy Tarreau76871a42022-03-08 16:01:40 +01001703 else if (*flag == 'd' && flag[1] == 'K') {
1704 arg_mode |= MODE_DUMP_KWD;
1705 kwd_dump = flag + 2;
1706 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001707 else if (*flag == 'd')
1708 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001709 else if (*flag == 'c' && flag[1] == 'c') {
1710 arg_mode |= MODE_CHECK_CONDITION;
1711 argv++;
1712 argc--;
1713 check_condition = *argv;
1714 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001715 else if (*flag == 'c')
1716 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001717 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001718 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001719 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001720 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001721#if defined(USE_SYSTEMD)
1722 global.tune.options |= GTUNE_USE_SYSTEMD;
1723#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001724 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 +01001725 usage(progname);
1726#endif
1727 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001728 else if (*flag == 'W')
1729 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001730 else if (*flag == 'q')
1731 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001732 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001733 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001734 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001735 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001736 }
William Lallemand4fc09692017-06-19 16:37:19 +02001737 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001738 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001739 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001740
Olivier Houchardf73629d2017-04-05 22:33:04 +02001741 argv++;
1742 argc--;
1743 }
William Lallemande7361152018-10-26 14:47:36 +02001744 else if (*flag == 'S') {
1745 struct wordlist *c;
1746
William Lallemanda6b32492020-06-04 23:49:20 +02001747 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001748 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1749 usage(progname);
1750 }
1751 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1752 ha_alert("Cannot allocate memory\n");
1753 exit(EXIT_FAILURE);
1754 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001755 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001756
1757 argv++;
1758 argc--;
1759 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001760 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1761 /* list of pids to finish ('f') or terminate ('t') */
1762
1763 if (flag[1] == 'f')
1764 oldpids_sig = SIGUSR1; /* finish then exit */
1765 else
1766 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001767 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001768 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001769 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1770 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001771 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001772 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001774 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001775 errno = 0;
1776 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1777 if (errno) {
1778 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1779 flag,
1780 *argv, strerror(errno));
1781 exit(1);
1782 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001783 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001784 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001785 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1786 flag, endptr);
1787 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001788 }
Chris Lane236062f2018-02-05 23:15:44 +00001789 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001790 if (oldpids[nb_oldpids] <= 0)
1791 usage(progname);
1792 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001793 }
1794 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001795 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1796 /* now that's a cfgfile list */
1797 argv++; argc--;
1798 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001799 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001800 ha_alert("Cannot load configuration file/directory %s : %s\n",
1801 *argv,
1802 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001803 exit(1);
1804 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001805 argv++; argc--;
1806 }
1807 break;
1808 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001809 else { /* >=2 args */
1810 argv++; argc--;
1811 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001812 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001813
1814 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001815 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001816 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001817 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001818 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001819 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001820 free(localpeer);
1821 if ((localpeer = strdup(*argv)) == NULL) {
1822 ha_alert("Cannot allocate memory for local peer.\n");
1823 exit(EXIT_FAILURE);
1824 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001825 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001826 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001827 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001828 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001829 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001830 ha_alert("Cannot load configuration file/directory %s : %s\n",
1831 *argv,
1832 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001833 exit(1);
1834 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001835 break;
Willy Tarreau392524d2022-02-17 18:10:36 +01001836 case 'p' :
1837 free(global.pidfile);
1838 if ((global.pidfile = strdup(*argv)) == NULL) {
1839 ha_alert("Cannot allocate memory for pidfile.\n");
1840 exit(EXIT_FAILURE);
1841 }
1842 break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001843 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001844 }
1845 }
1846 }
1847 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001848 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001849 argv++; argc--;
1850 }
Willy Tarreau392524d2022-02-17 18:10:36 +01001851 free(err_msg);
1852}
1853
Willy Tarreau76871a42022-03-08 16:01:40 +01001854/* call the various keyword dump functions based on the comma-delimited list of
1855 * classes in kwd_dump.
1856 */
1857static void dump_registered_keywords(void)
1858{
1859 char *end;
1860 int all __maybe_unused = 0;
1861
1862 for (; kwd_dump && *kwd_dump; kwd_dump = end) {
1863 end = strchr(kwd_dump, ',');
1864 if (end)
1865 *(end++) = 0;
1866
1867 if (strcmp(kwd_dump, "help") == 0) {
1868 printf("# List of supported keyword classes:\n");
1869 printf("all: list all keywords\n");
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001870 printf("acl: ACL keywords\n");
Willy Tarreauca1acd62022-03-29 15:02:44 +02001871 printf("cfg: configuration keywords\n");
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001872 printf("cli: CLI keywords\n");
Willy Tarreau29d799d2022-03-29 16:59:49 +02001873 printf("cnv: sample converter keywords\n");
Willy Tarreau3b65e142022-03-29 15:03:09 +02001874 printf("flt: filter names\n");
Willy Tarreauf78813f2022-03-29 16:51:29 +02001875 printf("smp: sample fetch functions\n");
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001876 printf("svc: service names\n");
Willy Tarreau76871a42022-03-08 16:01:40 +01001877 continue;
1878 }
1879 else if (strcmp(kwd_dump, "all") == 0) {
1880 all = 1;
1881 }
Willy Tarreauca1acd62022-03-29 15:02:44 +02001882
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001883 if (all || strcmp(kwd_dump, "acl") == 0) {
1884 printf("# List of registered ACL keywords:\n");
1885 acl_dump_kwd();
1886 }
1887
Willy Tarreauca1acd62022-03-29 15:02:44 +02001888 if (all || strcmp(kwd_dump, "cfg") == 0) {
1889 printf("# List of registered configuration keywords:\n");
1890 cfg_dump_registered_keywords();
1891 }
Willy Tarreau3b65e142022-03-29 15:03:09 +02001892
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001893 if (all || strcmp(kwd_dump, "cli") == 0) {
1894 printf("# List of registered CLI keywords:\n");
1895 cli_list_keywords();
1896 }
1897
Willy Tarreau29d799d2022-03-29 16:59:49 +02001898 if (all || strcmp(kwd_dump, "cnv") == 0) {
1899 printf("# List of registered sample converter functions:\n");
1900 smp_dump_conv_kw();
1901 }
1902
Willy Tarreau3b65e142022-03-29 15:03:09 +02001903 if (all || strcmp(kwd_dump, "flt") == 0) {
1904 printf("# List of registered filter names:\n");
1905 flt_dump_kws(NULL);
1906 }
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001907
Willy Tarreauf78813f2022-03-29 16:51:29 +02001908 if (all || strcmp(kwd_dump, "smp") == 0) {
1909 printf("# List of registered sample fetch functions:\n");
1910 smp_dump_fetch_kw();
1911 }
1912
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001913 if (all || strcmp(kwd_dump, "svc") == 0) {
1914 printf("# List of registered service names:\n");
1915 list_services(NULL);
1916 }
Willy Tarreau76871a42022-03-08 16:01:40 +01001917 }
1918}
1919
Amaury Denoyelle28ea31c2022-11-14 16:18:46 +01001920/* Generate a random cluster-secret in case the setting is not provided in the
1921 * configuration. This allows to use features which rely on it albeit with some
1922 * limitations.
1923 */
1924static void generate_random_cluster_secret()
1925{
1926 /* used as a default random cluster-secret if none defined. */
1927 uint64_t rand = ha_random64();
1928
1929 /* The caller must not overwrite an already defined secret. */
1930 BUG_ON(global.cluster_secret);
1931
1932 global.cluster_secret = malloc(8);
1933 if (!global.cluster_secret)
1934 return;
1935
1936 memcpy(global.cluster_secret, &rand, sizeof(rand));
1937 global.cluster_secret[7] = '\0';
1938}
1939
Willy Tarreau392524d2022-02-17 18:10:36 +01001940/*
1941 * This function initializes all the necessary variables. It only returns
1942 * if everything is OK. If something fails, it exits.
1943 */
1944static void init(int argc, char **argv)
1945{
1946 char *progname = global.log_tag.area;
1947 int err_code = 0;
1948 struct wordlist *wl;
1949 struct proxy *px;
1950 struct post_check_fct *pcf;
William Lallemandb53eb872022-04-21 18:02:53 +02001951 struct pre_check_fct *prcf;
Willy Tarreau392524d2022-02-17 18:10:36 +01001952 int ideal_maxconn;
1953
William Lallemand151dbbe2022-12-02 17:17:43 +01001954#ifdef USE_OPENSSL
1955#ifdef USE_OPENSSL_WOLFSSL
1956 wolfSSL_Init();
1957 wolfSSL_Debugging_ON();
1958#endif
1959#if (HA_OPENSSL_VERSION_NUMBER < 0x1010000fL)
William Lallemand44c80ce2022-12-02 17:06:59 +01001960 /* Initialize the error strings of OpenSSL
1961 * It only needs to be done explicitly with older versions of the SSL
1962 * library. On newer versions, errors strings are loaded during start
1963 * up. */
1964 SSL_load_error_strings();
1965#endif
William Lallemand151dbbe2022-12-02 17:17:43 +01001966#endif
William Lallemand44c80ce2022-12-02 17:06:59 +01001967
William Lallemandeba6a542022-09-26 12:54:39 +02001968 startup_logs_init();
1969
Willy Tarreau392524d2022-02-17 18:10:36 +01001970 if (!init_trash_buffers(1)) {
1971 ha_alert("failed to initialize trash buffers.\n");
1972 exit(1);
1973 }
1974
1975 if (init_acl() != 0)
1976 exit(1);
1977
1978 /* Initialise lua. */
1979 hlua_init();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001980
Christopher Faulete3a5e352017-10-24 13:53:54 +02001981 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001982 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Erwan Le Goasf30c5d72022-09-29 10:34:04 +02001983 | MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS | MODE_DUMP_KWD
1984 | MODE_DUMP_CFG | MODE_DUMP_NB_L));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001985
William Lallemand944e6192018-11-21 15:48:31 +01001986 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001987 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001988 global.mode |= MODE_MWORKER_WAIT;
1989 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001990 }
1991
William Lallemand40db4ae2022-12-07 15:03:55 +01001992 /* set the atexit functions when not doing configuration check */
1993 if (!(global.mode & (MODE_CHECK | MODE_CHECK_CONDITION))
1994 && (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
1995
1996 if (global.mode & MODE_MWORKER) {
1997 atexit_flag = 1;
1998 atexit(reexec_on_failure);
1999 } else if (global.mode & MODE_MWORKER_WAIT) {
2000 atexit_flag = 1;
2001 atexit(exit_on_waitmode_failure);
2002 }
William Lallemandcb11fd22017-06-01 17:38:52 +02002003 }
2004
Willy Tarreau576132e2011-09-10 19:26:56 +02002005 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002006 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02002007 exit(1);
2008 }
2009
Amaury Denoyelle11124302021-06-04 18:22:08 +02002010 usermsgs_clr("config");
2011
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002012 if (global.mode & MODE_CHECK_CONDITION) {
2013 int result;
2014
2015 uint32_t err;
2016 const char *errptr;
2017 char *errmsg = NULL;
2018
2019 char *args[MAX_LINE_ARGS+1];
2020 int arg = sizeof(args) / sizeof(*args);
William Lallemand89e236f2022-05-06 17:22:36 +02002021 size_t outlen;
Willy Tarreauc8194c32021-07-16 16:38:58 +02002022 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002023
William Lallemand89e236f2022-05-06 17:22:36 +02002024 if (!check_condition)
2025 usage(progname);
2026
2027 outlen = strlen(check_condition) + 1;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002028 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02002029 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002030 &errptr);
2031
2032 if (err & PARSE_ERR_QUOTE) {
2033 ha_alert("Syntax Error in condition: Unmatched quote.\n");
2034 exit(2);
2035 }
2036
2037 if (err & PARSE_ERR_HEX) {
2038 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
2039 exit(2);
2040 }
2041
2042 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
2043 ha_alert("Error in condition: Line too long.\n");
2044 exit(2);
2045 }
2046
Willy Tarreauc8194c32021-07-16 16:38:58 +02002047 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002048 ha_alert("Error in condition: Too many words.\n");
2049 exit(2);
2050 }
2051
2052 if (err) {
2053 ha_alert("Unhandled error in condition, please report this to the developers.\n");
2054 exit(2);
2055 }
2056
Willy Tarreauc8194c32021-07-16 16:38:58 +02002057 /* remerge all words into a single expression */
2058 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
2059 ;
2060
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02002061 result = cfg_eval_condition(args, &errmsg, &errptr);
2062
2063 if (result < 0) {
2064 if (errmsg)
2065 ha_alert("Failed to evaluate condition: %s\n", errmsg);
2066
2067 exit(2);
2068 }
2069
2070 exit(result ? 0 : 1);
2071 }
2072
William Lallemand944e6192018-11-21 15:48:31 +01002073 /* in wait mode, we don't try to read the configuration files */
2074 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01002075 char *env_cfgfiles = NULL;
2076 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01002077
William Lallemand944e6192018-11-21 15:48:31 +01002078 /* handle cfgfiles that are actually directories */
2079 cfgfiles_expand_directories();
2080
2081 if (LIST_ISEMPTY(&cfg_cfgfiles))
2082 usage(progname);
2083
Sébastien Gross537b9e72022-11-30 22:36:50 +01002084 /* temporary create environment variables with default
2085 * values to ease user configuration. Do not forget to
2086 * unset them after the list_for_each_entry loop.
2087 */
2088 setenv("HAPROXY_HTTP_LOG_FMT", default_http_log_format, 1);
2089 setenv("HAPROXY_HTTPS_LOG_FMT", default_https_log_format, 1);
2090 setenv("HAPROXY_TCP_LOG_FMT", default_tcp_log_format, 1);
Sébaastien Gross2a1bcf12023-02-23 12:54:25 -05002091 setenv("HAPROXY_BRANCH", PRODUCT_BRANCH, 1);
William Lallemand944e6192018-11-21 15:48:31 +01002092 list_for_each_entry(wl, &cfg_cfgfiles, list) {
2093 int ret;
2094
Christopher Faulet4e366822021-01-12 18:57:38 +01002095 if (env_err == 0) {
2096 if (!memprintf(&env_cfgfiles, "%s%s%s",
2097 (env_cfgfiles ? env_cfgfiles : ""),
2098 (env_cfgfiles ? ";" : ""), wl->s))
2099 env_err = 1;
2100 }
William Lallemand7b302d82019-05-20 11:15:37 +02002101
William Lallemand944e6192018-11-21 15:48:31 +01002102 ret = readcfgfile(wl->s);
2103 if (ret == -1) {
2104 ha_alert("Could not open configuration file %s : %s\n",
2105 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01002106 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002107 exit(1);
2108 }
2109 if (ret & (ERR_ABORT|ERR_FATAL))
2110 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
2111 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01002112 if (err_code & ERR_ABORT) {
2113 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002114 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01002115 }
Willy Tarreauc4382422009-12-06 13:10:44 +01002116 }
Sébastien Gross537b9e72022-11-30 22:36:50 +01002117 /* remove temporary environment variables. */
Sébaastien Gross2a1bcf12023-02-23 12:54:25 -05002118 unsetenv("HAPROXY_BRANCH");
Sébastien Gross537b9e72022-11-30 22:36:50 +01002119 unsetenv("HAPROXY_HTTP_LOG_FMT");
2120 unsetenv("HAPROXY_HTTPS_LOG_FMT");
2121 unsetenv("HAPROXY_TCP_LOG_FMT");
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02002122
William Lallemand944e6192018-11-21 15:48:31 +01002123 /* do not try to resolve arguments nor to spot inconsistencies when
2124 * the configuration contains fatal errors caused by files not found
2125 * or failed memory allocations.
2126 */
2127 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2128 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01002129 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002130 exit(1);
2131 }
Christopher Faulet4e366822021-01-12 18:57:38 +01002132 if (env_err) {
2133 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
2134 exit(1);
2135 }
2136 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
2137 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02002138
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02002139 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002140 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01002141 struct mworker_proc *tmproc;
2142
William Lallemand482f9a92019-04-12 16:15:00 +02002143 setenv("HAPROXY_MWORKER", "1", 1);
2144
William Lallemand16dd1b32018-11-19 18:46:18 +01002145 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
2146
William Lallemand56be0e02022-01-28 21:11:41 +01002147 tmproc = mworker_proc_new();
William Lallemand16dd1b32018-11-19 18:46:18 +01002148 if (!tmproc) {
2149 ha_alert("Cannot allocate process structures.\n");
2150 exit(EXIT_FAILURE);
2151 }
William Lallemand8f7069a2019-04-12 16:09:23 +02002152 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01002153 tmproc->pid = pid;
William Lallemand5a7f83a2023-02-17 16:23:52 +01002154 tmproc->timestamp = start_date.tv_sec;
William Lallemand16dd1b32018-11-19 18:46:18 +01002155 proc_self = tmproc;
2156
Willy Tarreau2b718102021-04-21 07:32:39 +02002157 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01002158 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002159
William Lallemand56be0e02022-01-28 21:11:41 +01002160 tmproc = mworker_proc_new();
Willy Tarreau6185a032021-06-15 08:02:06 +02002161 if (!tmproc) {
2162 ha_alert("Cannot allocate process structures.\n");
2163 exit(EXIT_FAILURE);
2164 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002165 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
William Lallemandce83b4a2018-10-26 14:47:30 +02002166
Willy Tarreau6185a032021-06-15 08:02:06 +02002167 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
2168 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02002169 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002170
2171 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01002172 }
Willy Tarreau53bfac82022-07-22 17:35:49 +02002173
2174 if (global.mode & MODE_MWORKER_WAIT) {
2175 /* in exec mode, there's always exactly one thread. Failure to
2176 * set these ones now will result in nbthread being detected
2177 * automatically.
2178 */
2179 global.nbtgroups = 1;
2180 global.nbthread = 1;
2181 }
2182
William Lallemand944e6192018-11-21 15:48:31 +01002183 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
2184 struct wordlist *it, *c;
2185
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02002186 /* get the info of the children in the env */
2187 if (mworker_env_to_proc_list() < 0) {
2188 exit(EXIT_FAILURE);
2189 }
William Lallemande7361152018-10-26 14:47:36 +02002190
William Lallemand550db6d2018-11-06 17:37:12 +01002191 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemandec059c22022-09-22 17:26:23 +02002192 char *path = NULL;
William Lallemande7361152018-10-26 14:47:36 +02002193
William Lallemand550db6d2018-11-06 17:37:12 +01002194 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02002195 ha_alert("Can't create the master's CLI.\n");
2196 exit(EXIT_FAILURE);
2197 }
William Lallemande7361152018-10-26 14:47:36 +02002198
William Lallemand550db6d2018-11-06 17:37:12 +01002199 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
2200
William Lallemand21623b52022-09-24 15:51:27 +02002201 if (mworker_cli_proxy_new_listener(c->s) == NULL) {
William Lallemand550db6d2018-11-06 17:37:12 +01002202 ha_alert("Can't create the master's CLI.\n");
2203 exit(EXIT_FAILURE);
2204 }
Willy Tarreau2b718102021-04-21 07:32:39 +02002205 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01002206 free(c->s);
2207 free(c);
2208 }
William Lallemande57b7022022-12-07 14:25:41 +01002209 /* Creates the mcli_reload listener, which is the listener used
2210 * to retrieve the master CLI session which asked for the reload.
2211 *
2212 * ipc_fd[1] will be used as a listener, and ipc_fd[0]
2213 * will be used to send the FD of the session.
2214 *
2215 * Both FDs will be kept in the master. The sockets are
2216 * created only if they weren't inherited.
2217 */
2218 if ((proc_self->ipc_fd[1] == -1) &&
2219 socketpair(AF_UNIX, SOCK_STREAM, 0, proc_self->ipc_fd) < 0) {
2220 ha_alert("cannot create the mcli_reload socketpair.\n");
2221 exit(EXIT_FAILURE);
2222 }
2223
William Lallemandec059c22022-09-22 17:26:23 +02002224 /* Create the mcli_reload listener from the proc_self struct */
2225 memprintf(&path, "sockpair@%d", proc_self->ipc_fd[1]);
William Lallemand56f73b22022-09-24 15:56:25 +02002226 mcli_reload_bind_conf = mworker_cli_proxy_new_listener(path);
2227 if (mcli_reload_bind_conf == NULL) {
William Lallemandec059c22022-09-22 17:26:23 +02002228 ha_alert("Cannot create the mcli_reload listener.\n");
2229 exit(EXIT_FAILURE);
2230 }
2231 ha_free(&path);
William Lallemand550db6d2018-11-06 17:37:12 +01002232 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002233 }
2234
Eric Salama5ba83352021-03-16 15:11:17 +01002235 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
2236 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
2237 }
2238
Christopher Faulet27c8d202021-10-13 09:50:53 +02002239 /* destroy unreferenced defaults proxies */
2240 proxy_destroy_all_unref_defaults();
2241
William Lallemandb53eb872022-04-21 18:02:53 +02002242 list_for_each_entry(prcf, &pre_check_list, list)
2243 err_code |= prcf->fct();
Willy Tarreaue90904d2021-02-12 14:08:31 +01002244
William Lallemand8b9a2df2022-05-04 14:29:46 +02002245 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2246 ha_alert("Fatal errors found in configuration.\n");
2247 exit(1);
2248 }
2249
Willy Tarreauda4aa692023-05-17 09:02:21 +02002250 /* update the ready date that will be used to count the startup time
2251 * during config checks (e.g. to schedule certain tasks if needed)
2252 */
2253 clock_update_date(0, 1);
Willy Tarreauc7b93082023-05-16 19:19:36 +02002254 clock_adjust_now_offset();
Willy Tarreauda4aa692023-05-17 09:02:21 +02002255 ready_date = date;
2256
Willy Tarreauc7b93082023-05-16 19:19:36 +02002257
Willy Tarreau57c3e752022-12-08 08:13:20 +01002258 /* Note: global.nbthread will be initialized as part of this call */
Willy Tarreaubb925012009-07-23 13:36:36 +02002259 err_code |= check_config_validity();
Willy Tarreauda4aa692023-05-17 09:02:21 +02002260
2261 /* update the ready date to also account for the check time */
2262 clock_update_date(0, 1);
Willy Tarreauc7b93082023-05-16 19:19:36 +02002263 clock_adjust_now_offset();
Willy Tarreauda4aa692023-05-17 09:02:21 +02002264 ready_date = date;
2265
Christopher Fauletc1692962019-08-12 09:51:07 +02002266 for (px = proxies_list; px; px = px->next) {
2267 struct server *srv;
2268 struct post_proxy_check_fct *ppcf;
2269 struct post_server_check_fct *pscf;
2270
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002271 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002272 continue;
2273
Christopher Fauletc1692962019-08-12 09:51:07 +02002274 list_for_each_entry(pscf, &post_server_check_list, list) {
2275 for (srv = px->srv; srv; srv = srv->next)
2276 err_code |= pscf->fct(srv);
2277 }
2278 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2279 err_code |= ppcf->fct(px);
2280 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002281 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002282 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002283 exit(1);
2284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002285
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002286 err_code |= pattern_finalize_config();
2287 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2288 ha_alert("Failed to finalize pattern config.\n");
2289 exit(1);
2290 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002291
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002292 if (global.rlimit_memmax_all)
2293 global.rlimit_memmax = global.rlimit_memmax_all;
2294
Willy Tarreaue5733232019-05-22 19:24:06 +02002295#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002296 err_code |= netns_init();
2297 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002298 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002299 exit(1);
2300 }
2301#endif
2302
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002303 /* Apply server states */
2304 apply_server_state();
2305
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002306 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002307 srv_compute_all_admin_states(px);
2308
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002309 /* Apply servers' configured address */
2310 err_code |= srv_init_addr();
2311 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002312 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002313 exit(1);
2314 }
2315
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002316 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2317 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2318 exit(1);
2319 }
2320
Willy Tarreau654726d2021-12-28 15:43:11 +01002321#if defined(HA_HAVE_DUMP_LIBS)
2322 if (global.mode & MODE_DUMP_LIBS) {
2323 qfprintf(stdout, "List of loaded object files:\n");
2324 chunk_reset(&trash);
Willy Tarreau9ef27422023-03-22 11:37:54 +01002325 if (dump_libs(&trash, ((arg_mode & (MODE_QUIET|MODE_VERBOSE)) == MODE_VERBOSE)))
Willy Tarreau654726d2021-12-28 15:43:11 +01002326 printf("%s", trash.area);
2327 }
2328#endif
2329
Willy Tarreau76871a42022-03-08 16:01:40 +01002330 if (global.mode & MODE_DUMP_KWD)
2331 dump_registered_keywords();
2332
Willy Tarreaubaaee002006-06-26 02:48:02 +02002333 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002334 struct peers *pr;
2335 struct proxy *px;
2336
Willy Tarreaubebd2122020-04-15 16:06:11 +02002337 if (warned & WARN_ANY)
2338 qfprintf(stdout, "Warnings were found.\n");
2339
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002340 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002341 if (pr->peers_fe)
2342 break;
2343
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002344 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002345 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002346 break;
2347
Emeric Brunbc5c8212021-08-13 09:32:50 +02002348 if (!px) {
2349 /* We may only have log-forward section */
2350 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002351 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002352 break;
2353 }
2354
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002355 if (pr || px) {
2356 /* At least one peer or one listener has been found */
2357 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002358 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002359 }
2360 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2361 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002363
Erwan Le Goasb0c05012022-09-14 17:51:55 +02002364 if (global.mode & MODE_DUMP_CFG)
2365 deinit_and_exit(0);
2366
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002367 if (global.mode & MODE_DIAG) {
2368 cfg_run_diagnostics();
2369 }
2370
Remi Tricot-Le Breton51944462022-05-16 16:24:31 +02002371#ifdef USE_OPENSSL
William Lallemand3b8bafd2022-07-19 18:13:29 +02002372
Remi Tricot-Le Breton51944462022-05-16 16:24:31 +02002373 /* Initialize SSL random generator. Must be called before chroot for
2374 * access to /dev/urandom, and before ha_random_boot() which may use
2375 * RAND_bytes().
2376 */
2377 if (!ssl_initialize_random()) {
2378 ha_alert("OpenSSL random data generator initialization failed.\n");
2379 exit(EXIT_FAILURE);
2380 }
2381#endif
2382 ha_random_boot(argv); // the argv pointer brings some kernel-fed entropy
2383
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002384 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002385 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002386
Willy Tarreaue6945732016-12-21 19:57:00 +01002387 list_for_each_entry(pcf, &post_check_list, list) {
2388 err_code |= pcf->fct();
2389 if (err_code & (ERR_ABORT|ERR_FATAL))
2390 exit(1);
2391 }
2392
William Lallemand0a012aa2022-06-21 11:11:50 +02002393 /* set the default maxconn in the master, but let it be rewritable with -n */
2394 if (global.mode & MODE_MWORKER_WAIT)
William Lallemand2078d4b2023-03-09 14:28:44 +01002395 global.maxconn = MASTER_MAXCONN;
William Lallemand0a012aa2022-06-21 11:11:50 +02002396
Willy Tarreaubaaee002006-06-26 02:48:02 +02002397 if (cfg_maxconn > 0)
2398 global.maxconn = cfg_maxconn;
2399
Willy Tarreau4975d142021-03-13 11:00:33 +01002400 if (global.cli_fe)
2401 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002402
2403 if (cfg_peers) {
2404 /* peers also need to bypass global maxconn */
2405 struct peers *p = cfg_peers;
2406
2407 for (p = cfg_peers; p; p = p->next)
2408 if (p->peers_fe)
2409 global.maxsock += p->peers_fe->maxconn;
2410 }
2411
Willy Tarreaud0256482015-01-15 21:45:22 +01002412 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002413 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2414 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2415 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2416 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002417 *
2418 * If memmax is set, then it depends on which values are set. If
2419 * maxsslconn is set, we use memmax to determine how many cleartext
2420 * connections may be added, and set maxconn to the sum of the two.
2421 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2422 * the remaining amount of memory between memmax and the cleartext
2423 * connections. If neither are set, then it is considered that all
2424 * connections are SSL-capable, and maxconn is computed based on this,
2425 * then maxsslconn accordingly. We need to know if SSL is used on the
2426 * frontends, backends, or both, because when it's used on both sides,
2427 * we need twice the value for maxsslconn, but we only count the
2428 * handshake once since it is not performed on the two sides at the
2429 * same time (frontend-side is terminated before backend-side begins).
2430 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002431 * ssl_handshake_cost during its initialization. In any case, if
2432 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2433 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002434 */
Willy Tarreauac350932019-03-01 15:43:14 +01002435 ideal_maxconn = compute_ideal_maxconn();
2436
Willy Tarreaud0256482015-01-15 21:45:22 +01002437 if (!global.rlimit_memmax) {
2438 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002439 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002440 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2441 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2442 }
2443 }
2444#ifdef USE_OPENSSL
2445 else if (!global.maxconn && !global.maxsslconn &&
2446 (global.ssl_used_frontend || global.ssl_used_backend)) {
2447 /* memmax is set, compute everything automatically. Here we want
2448 * to ensure that all SSL connections will be served. We take
2449 * care of the number of sides where SSL is used, and consider
2450 * the worst case : SSL used on both sides and doing a handshake
2451 * simultaneously. Note that we can't have more than maxconn
2452 * handshakes at a time by definition, so for the worst case of
2453 * two SSL conns per connection, we count a single handshake.
2454 */
2455 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2456 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002457 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002458
Willy Tarreau2cb3be72022-05-24 07:43:57 +02002459 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002460 mem -= global.maxzlibmem;
2461 mem = mem * MEM_USABLE_RATIO;
2462
Willy Tarreau304e17e2020-03-10 17:54:54 +01002463 /* Principle: we test once to set maxconn according to the free
2464 * memory. If it results in values the system rejects, we try a
2465 * second time by respecting rlim_fd_max. If it fails again, we
2466 * go back to the initial value and will let the final code
2467 * dealing with rlimit report the error. That's up to 3 attempts.
2468 */
2469 do {
2470 global.maxconn = mem /
2471 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2472 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2473 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002474
Willy Tarreau304e17e2020-03-10 17:54:54 +01002475 if (retried == 1)
2476 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2477 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002478#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002479 if (global.maxconn > SYSTEM_MAXCONN)
2480 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002481#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002482 global.maxsslconn = sides * global.maxconn;
2483
2484 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2485 break;
2486 } while (retried++ < 2);
2487
Willy Tarreaud0256482015-01-15 21:45:22 +01002488 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2489 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2490 global.maxconn, global.maxsslconn);
2491 }
2492 else if (!global.maxsslconn &&
2493 (global.ssl_used_frontend || global.ssl_used_backend)) {
2494 /* memmax and maxconn are known, compute maxsslconn automatically.
2495 * maxsslconn being forced, we don't know how many of it will be
2496 * on each side if both sides are being used. The worst case is
2497 * when all connections use only one SSL instance because
2498 * handshakes may be on two sides at the same time.
2499 */
2500 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2501 int64_t mem = global.rlimit_memmax * 1048576ULL;
2502 int64_t sslmem;
2503
Willy Tarreau8e5b9582022-05-26 08:55:05 +02002504 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002505 mem -= global.maxzlibmem;
2506 mem = mem * MEM_USABLE_RATIO;
2507
Willy Tarreau87b09662015-04-03 00:22:06 +02002508 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002509 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2510 global.maxsslconn = round_2dig(global.maxsslconn);
2511
2512 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002513 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2514 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2515 "without SSL is %d, but %d was found and SSL is in use.\n",
2516 global.rlimit_memmax,
2517 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2518 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002519 exit(1);
2520 }
2521
2522 if (global.maxsslconn > sides * global.maxconn)
2523 global.maxsslconn = sides * global.maxconn;
2524
2525 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2526 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2527 }
2528#endif
2529 else if (!global.maxconn) {
2530 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2531 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2532 int64_t mem = global.rlimit_memmax * 1048576ULL;
2533 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002534 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002535
2536 if (global.ssl_used_frontend || global.ssl_used_backend)
Willy Tarreau8e5b9582022-05-26 08:55:05 +02002537 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002538
2539 mem -= global.maxzlibmem;
2540 mem = mem * MEM_USABLE_RATIO;
2541
2542 clearmem = mem;
2543 if (sides)
2544 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2545
Willy Tarreau304e17e2020-03-10 17:54:54 +01002546 /* Principle: we test once to set maxconn according to the free
2547 * memory. If it results in values the system rejects, we try a
2548 * second time by respecting rlim_fd_max. If it fails again, we
2549 * go back to the initial value and will let the final code
2550 * dealing with rlimit report the error. That's up to 3 attempts.
2551 */
2552 do {
2553 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2554 if (retried == 1)
2555 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2556 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002557#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002558 if (global.maxconn > SYSTEM_MAXCONN)
2559 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002560#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002561
Willy Tarreau304e17e2020-03-10 17:54:54 +01002562 if (clearmem <= 0 || !global.maxconn) {
2563 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2564 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2565 "is %d, but %d was found.\n",
2566 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002567 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002568 global.maxsslconn);
2569 exit(1);
2570 }
2571
2572 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2573 break;
2574 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002575
2576 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2577 if (sides && global.maxsslconn > sides * global.maxconn) {
2578 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2579 "to be limited to %d. Better reduce global.maxsslconn to get more "
2580 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2581 }
2582 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2583 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002584 }
2585
Willy Tarreaua409f302020-03-10 17:08:53 +01002586 global.maxsock = compute_ideal_maxsock(global.maxconn);
2587 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002588 if (!global.maxpipes)
2589 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590
Olivier Houchard88698d92019-04-16 19:07:22 +02002591 /* update connection pool thresholds */
2592 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2593 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2594
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002595 proxy_adjust_all_maxconn();
2596
Willy Tarreau1db37712007-06-03 17:16:49 +02002597 if (global.tune.maxpollevents <= 0)
2598 global.tune.maxpollevents = MAX_POLL_EVENTS;
2599
Willy Tarreau060a7612021-03-10 11:06:26 +01002600 if (global.tune.runqueue_depth <= 0) {
2601 /* tests on various thread counts from 1 to 64 have shown an
2602 * optimal queue depth following roughly 1/sqrt(threads).
2603 */
2604 int s = my_flsl(global.nbthread);
2605 s += (global.nbthread / s); // roughly twice the sqrt.
2606 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2607 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002608
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002609 if (global.tune.recv_enough == 0)
2610 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2611
Willy Tarreau27a674e2009-08-17 07:23:33 +02002612 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2613 global.tune.maxrewrite = global.tune.bufsize / 2;
2614
Amaury Denoyelle11124302021-06-04 18:22:08 +02002615 usermsgs_clr(NULL);
2616
Willy Tarreaubaaee002006-06-26 02:48:02 +02002617 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2618 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002619 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002620 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2621 }
2622
William Lallemand095ba4c2017-06-01 17:38:50 +02002623 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002624 /* command line daemon mode inhibits foreground and debug modes mode */
2625 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002626 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002627 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002628
2629 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002630
William Lallemand095ba4c2017-06-01 17:38:50 +02002631 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002632 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002633 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002634 }
2635
Christopher Faulet3ef26392017-08-29 16:46:57 +02002636 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002637 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002638 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002639 exit(1);
2640 }
2641
Christopher Faulet96d44832017-11-14 22:02:30 +01002642 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002643 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002644 exit(1);
2645 }
2646
Amaury Denoyelle28ea31c2022-11-14 16:18:46 +01002647 if (!global.cluster_secret)
2648 generate_random_cluster_secret();
2649
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002650 /*
2651 * Note: we could register external pollers here.
2652 * Built-in pollers have been registered before main().
2653 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002654
Willy Tarreau43b78992009-01-25 15:42:27 +01002655 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002656 disable_poller("kqueue");
2657
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002658 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2659 disable_poller("evports");
2660
Willy Tarreau43b78992009-01-25 15:42:27 +01002661 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002662 disable_poller("epoll");
2663
Willy Tarreau43b78992009-01-25 15:42:27 +01002664 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002665 disable_poller("poll");
2666
Willy Tarreau43b78992009-01-25 15:42:27 +01002667 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002668 disable_poller("select");
2669
2670 /* Note: we could disable any poller by name here */
2671
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002672 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002673 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002674 fprintf(stderr, "\n");
2675 list_filters(stderr);
2676 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002677
Willy Tarreau4f60f162007-04-08 16:39:58 +02002678 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002679 ha_alert("No polling mechanism available.\n"
Willy Tarreaue5715bf2022-07-09 23:38:46 +02002680 " This may happen when using thread-groups with old pollers (poll/select), or\n"
2681 " it is possible that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
Christopher Faulet767a84b2017-11-24 16:50:31 +01002682 " is too low on this platform to support maxconn and the number of listeners\n"
2683 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2684 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2685 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2686 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2687 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2688 " check build settings using 'haproxy -vv'.\n\n",
2689 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002690 exit(1);
2691 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002692 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2693 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002694 }
2695
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002696 if (!global.node)
2697 global.node = strdup(hostname);
2698
Willy Tarreau02b092f2020-10-07 18:36:54 +02002699 /* stop disabled proxies */
2700 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002701 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002702 stop_proxy(px);
2703 }
2704
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002705 if (!hlua_post_init())
2706 exit(1);
Willy Tarreau284cfc62022-12-19 08:15:57 +01002707
2708 /* Set the per-thread pool cache size to the default value if not set.
2709 * This is the right place to decide to automatically adjust it (e.g.
2710 * check L2 cache size, thread counts or take into account certain
2711 * expensive pools).
2712 */
2713 if (!global.tune.pool_cache_size)
2714 global.tune.pool_cache_size = CONFIG_HAP_POOL_CACHE_SIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002715}
2716
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002717void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002718{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002719 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002720 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002721 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002722 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002723 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002724 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002725 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002726 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002727 struct per_thread_init_fct *tif, *tifb;
2728 struct per_thread_deinit_fct *tdf, *tdfb;
2729 struct per_thread_alloc_fct *taf, *tafb;
2730 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002731 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002732 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002733 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreau65009eb2022-04-27 18:02:54 +02002734 struct pre_check_fct *prcf, *prcfb;
Willy Tarreau226866e2022-04-27 18:07:24 +02002735 struct cfg_postparser *pprs, *pprsb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002736 int cur_fd;
2737
Willy Tarreaue98d3852022-11-15 09:34:07 +01002738 /* the user may want to skip this phase */
2739 if (global.tune.options & GTUNE_QUICK_EXIT)
2740 return;
2741
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002742 /* At this point the listeners state is weird:
2743 * - most listeners are still bound and referenced in their protocol
2744 * - some might be zombies that are not in their proto anymore, but
2745 * still appear in their proxy's listeners with a valid FD.
2746 * - some might be stopped and still appear in their proxy as FD #-1
2747 * - among all of them, some might be inherited hence shared and we're
2748 * not allowed to pause them or whatever, we must just close them.
2749 * - finally some are not listeners (pipes, logs, stdout, etc) and
2750 * must be left intact.
2751 *
2752 * The safe way to proceed is to unbind (and close) whatever is not yet
2753 * unbound so that no more receiver/listener remains alive. Then close
2754 * remaining listener FDs, which correspond to zombie listeners (those
2755 * belonging to disabled proxies that were in another process).
2756 * objt_listener() would be cleaner here but not converted yet.
2757 */
2758 protocol_unbind_all();
2759
2760 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002761 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002762 continue;
2763
Willy Tarreaua74cb382020-10-15 21:29:49 +02002764 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002765 struct listener *l = fdtab[cur_fd].owner;
2766
2767 BUG_ON(l->state != LI_INIT);
2768 unbind_listener(l);
2769 }
2770 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002771
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002772 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002773 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002774 /* build a list of unique uri_auths */
2775 if (!ua)
2776 ua = p->uri_auth;
2777 else {
2778 /* check if p->uri_auth is unique */
2779 for (uap = ua; uap; uap=uap->next)
2780 if (uap == p->uri_auth)
2781 break;
2782
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002783 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002784 /* add it, if it is */
2785 p->uri_auth->next = ua;
2786 ua = p->uri_auth;
2787 }
William Lallemand0f99e342011-10-12 17:50:54 +02002788 }
2789
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002790 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002791 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002792 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002793 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002794
Aurelien DARRAGON9b1d15f2023-03-09 12:07:09 +01002795 /* we don't need to free sink_proxies_list proxies since it is
2796 * already handled in sink_deinit()
2797 */
Aurelien DARRAGONcca33552023-03-09 12:21:12 +01002798 p = cfg_log_forward;
2799 /* we need to manually clean cfg_log_forward proxy list */
2800 while (p) {
2801 p0 = p;
2802 p = p->next;
2803 free_proxy(p0);
2804 }
Aurelien DARRAGON9b1d15f2023-03-09 12:07:09 +01002805
Christopher Faulet27c8d202021-10-13 09:50:53 +02002806 /* destroy all referenced defaults proxies */
2807 proxy_destroy_all_unref_defaults();
2808
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002809 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002810 struct stat_scope *scope, *scopep;
2811
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002812 uap = ua;
2813 ua = ua->next;
2814
Willy Tarreaua534fea2008-08-03 12:19:50 +02002815 free(uap->uri_prefix);
2816 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002817 free(uap->node);
2818 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002819
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002820 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002821 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002822
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002823 scope = uap->scope;
2824 while (scope) {
2825 scopep = scope;
2826 scope = scope->next;
2827
2828 free(scopep->px_id);
2829 free(scopep);
2830 }
2831
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002832 free(uap);
2833 }
2834
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002835 userlist_free(userlist);
2836
David Carlier834cb2e2015-09-25 12:02:25 +01002837 cfg_unregister_sections();
2838
Christopher Faulet0132d062017-07-26 15:33:35 +02002839 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002840
Willy Tarreau05554e62016-12-21 20:46:26 +01002841 list_for_each_entry(pdf, &post_deinit_list, list)
2842 pdf->fct();
2843
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002844 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002845 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002846 ha_free(&global.chroot);
Frédéric Lécaille372508c2022-05-06 08:53:16 +02002847 ha_free(&global.cluster_secret);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002848 ha_free(&global.pidfile);
2849 ha_free(&global.node);
2850 ha_free(&global.desc);
2851 ha_free(&oldpids);
2852 ha_free(&old_argv);
2853 ha_free(&localpeer);
2854 ha_free(&global.server_state_base);
2855 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002856 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002857 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002858
William Lallemand0f99e342011-10-12 17:50:54 +02002859 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2c701db2023-01-26 15:32:12 +01002860 LIST_DEL_INIT(&log->list);
2861 free_logsrv(log);
2862 }
2863
Willy Tarreau477ecd82010-01-03 21:12:30 +01002864 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002865 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002866 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002867 free(wl);
2868 }
2869
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002870 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2871 if (bol->must_free)
2872 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002873 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002874 free(bol);
2875 }
2876
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002877 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002878 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002879 free(pxdf);
2880 }
2881
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002882 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002883 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002884 free(pdf);
2885 }
2886
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002887 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002888 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002889 free(srvdf);
2890 }
2891
Tim Duesterhusfc854942020-09-10 19:46:42 +02002892 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002893 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002894 free(pcf);
2895 }
2896
Tim Duesterhus34bef072020-07-04 11:49:50 +02002897 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002898 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002899 free(pscf);
2900 }
2901
Tim Duesterhus53508d62020-09-10 19:46:40 +02002902 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002903 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002904 free(ppcf);
2905 }
2906
Willy Tarreau65009eb2022-04-27 18:02:54 +02002907 list_for_each_entry_safe(prcf, prcfb, &pre_check_list, list) {
2908 LIST_DELETE(&prcf->list);
2909 free(prcf);
2910 }
2911
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002912 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002913 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002914 free(tif);
2915 }
2916
2917 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002918 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002919 free(tdf);
2920 }
2921
2922 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002923 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002924 free(taf);
2925 }
2926
2927 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002928 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002929 free(tff);
2930 }
2931
Willy Tarreau226866e2022-04-27 18:07:24 +02002932 list_for_each_entry_safe(pprs, pprsb, &postparsers, list) {
2933 LIST_DELETE(&pprs->list);
2934 free(pprs);
2935 }
2936
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002937 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002938 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002939 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940} /* end deinit() */
2941
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002942__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002943{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002944 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002945 deinit();
2946 exit(status);
2947}
William Lallemand72160322018-11-06 17:37:16 +01002948
Willy Tarreau918ff602011-07-25 16:33:49 +02002949/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002950void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002951{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002952 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002953
Willy Tarreau3e820a12023-02-17 08:36:42 +01002954 _HA_ATOMIC_OR(&th_ctx->flags, TH_FL_IN_LOOP);
2955
Willy Tarreau55542642021-10-08 09:33:24 +02002956 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002957 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002958 wake_expired_tasks();
2959
William Lallemand1aab50b2018-06-07 09:46:01 +02002960 /* check if we caught some signals and process them in the
2961 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002962 if (signal_queue_len && tid == 0) {
2963 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002964 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002965 }
2966
2967 /* Process a few tasks */
2968 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002969
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002970 /* also stop if we failed to cleanly stop all tasks */
2971 if (killed > 1)
2972 break;
2973
Matthias Wirtheea152e2022-09-09 10:21:00 +02002974 /* expire immediately if events or signals are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002975 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002976 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002977 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002978 else {
Willy Tarreaue7475c82022-06-20 09:23:24 +02002979 _HA_ATOMIC_OR(&th_ctx->flags, TH_FL_SLEEPING);
Willy Tarreaudce4ad72022-06-22 15:38:38 +02002980 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_NOTIFIED);
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002981 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002982 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002983 activity[tid].wake_tasks++;
Willy Tarreaue7475c82022-06-20 09:23:24 +02002984 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_SLEEPING);
Matthias Wirtheea152e2022-09-09 10:21:00 +02002985 } else if (signal_queue_len) {
2986 /* this check is required after setting TH_FL_SLEEPING to avoid
2987 * a race with wakeup on signals using wake_threads() */
2988 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_SLEEPING);
Olivier Houchard79321b92018-07-26 17:55:11 +02002989 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002990 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002991 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002992
Willy Tarreau4f46a352020-03-23 09:27:28 +01002993 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002994 int i;
2995
2996 if (stopping) {
Amaury Denoyelle5907fed2023-03-08 10:37:45 +01002997 /* stop muxes/quic-conns before acknowledging stopping */
Willy Tarreau24cfc9f2022-07-04 14:07:29 +02002998 if (!(tg_ctx->stopping_threads & ti->ltid_bit)) {
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002999 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
Amaury Denoyelle5907fed2023-03-08 10:37:45 +01003000#ifdef USE_QUIC
3001 quic_handle_stopping();
3002#endif
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02003003 wake = 1;
3004 }
3005
Willy Tarreauef422ce2022-06-28 19:29:29 +02003006 if (_HA_ATOMIC_OR_FETCH(&tg_ctx->stopping_threads, ti->ltid_bit) == ti->ltid_bit &&
3007 _HA_ATOMIC_OR_FETCH(&stopping_tgroup_mask, tg->tgid_bit) == tg->tgid_bit) {
3008 /* first one to detect it, notify all threads that stopping was just set */
3009 for (i = 0; i < global.nbthread; i++) {
Willy Tarreaub2f38c12023-01-19 19:14:18 +01003010 if (_HA_ATOMIC_LOAD(&ha_thread_info[i].tg->threads_enabled) &
Willy Tarreauef422ce2022-06-28 19:29:29 +02003011 ha_thread_info[i].ltid_bit &
3012 ~_HA_ATOMIC_LOAD(&ha_thread_info[i].tg_ctx->stopping_threads))
Willy Tarreaud6455742020-05-13 14:30:25 +02003013 wake_thread(i);
Willy Tarreauef422ce2022-06-28 19:29:29 +02003014 }
Willy Tarreaud6455742020-05-13 14:30:25 +02003015 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02003016 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01003017
3018 /* stop when there's nothing left to do */
3019 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreauef422ce2022-06-28 19:29:29 +02003020 (_HA_ATOMIC_LOAD(&stopping_tgroup_mask) & all_tgroups_mask) == all_tgroups_mask) {
3021 /* check that all threads are aware of the stopping status */
3022 for (i = 0; i < global.nbtgroups; i++)
Willy Tarreaub2f38c12023-01-19 19:14:18 +01003023 if ((_HA_ATOMIC_LOAD(&ha_tgroup_ctx[i].stopping_threads) &
3024 _HA_ATOMIC_LOAD(&ha_tgroup_info[i].threads_enabled)) !=
3025 _HA_ATOMIC_LOAD(&ha_tgroup_info[i].threads_enabled))
Willy Tarreauef422ce2022-06-28 19:29:29 +02003026 break;
3027#ifdef USE_THREAD
3028 if (i == global.nbtgroups) {
3029 /* all are OK, let's wake them all and stop */
3030 for (i = 0; i < global.nbthread; i++)
Willy Tarreaub2f38c12023-01-19 19:14:18 +01003031 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 +02003032 wake_thread(i);
3033 break;
3034 }
3035#endif
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02003036 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01003037 }
3038
Willy Tarreauc49ba522019-12-11 08:12:23 +01003039 /* If we have to sleep, measure how long */
3040 next = wake ? TICK_ETERNITY : next_timer_expiry();
3041
Willy Tarreau58b458d2008-06-29 22:40:23 +02003042 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02003043 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02003044
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01003045 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02003046 }
Willy Tarreau3e820a12023-02-17 08:36:42 +01003047
3048 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_IN_LOOP);
Willy Tarreau4f60f162007-04-08 16:39:58 +02003049}
3050
Christopher Faulet1d17c102017-08-29 15:38:48 +02003051static void *run_thread_poll_loop(void *data)
3052{
Willy Tarreau082b6282019-05-22 14:42:12 +02003053 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02003054 struct per_thread_init_fct *ptif;
3055 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02003056 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02003057 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02003058 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
3059 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02003060
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003061 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02003062 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02003063 clock_set_local_source();
Aurelien DARRAGON739281b2023-01-27 15:13:28 +01003064 /* thread is started, from now on it is not idle nor harmless */
3065 thread_harmless_end();
3066 thread_idle_end();
Willy Tarreau3e820a12023-02-17 08:36:42 +01003067 _HA_ATOMIC_OR(&th_ctx->flags, TH_FL_STARTED);
Willy Tarreau91e6df02019-05-03 17:21:18 +02003068
Willy Tarreau6ec902a2019-06-07 14:41:11 +02003069 /* Now, initialize one thread init at a time. This is better since
3070 * some init code is a bit tricky and may release global resources
3071 * after reallocating them locally. This will also ensure there is
3072 * no race on file descriptors allocation.
3073 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02003074#ifdef USE_THREAD
3075 pthread_mutex_lock(&init_mutex);
3076#endif
3077 /* The first thread must set the number of threads left */
3078 if (!init_left)
3079 init_left = global.nbthread;
3080 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02003081
Willy Tarreau55542642021-10-08 09:33:24 +02003082 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003083
Willy Tarreau082b6282019-05-22 14:42:12 +02003084 /* per-thread alloc calls performed here are not allowed to snoop on
3085 * other threads, so they are free to initialize at their own rhythm
3086 * as long as they act as if they were alone. None of them may rely
3087 * on resources initialized by the other ones.
3088 */
3089 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
3090 if (!ptaf->fct()) {
3091 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02003092#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08003093 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02003094#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02003095 exit(1);
3096 }
3097 }
3098
Willy Tarreau3078e9f2019-05-20 10:50:43 +02003099 /* per-thread init calls performed here are not allowed to snoop on
3100 * other threads, so they are free to initialize at their own rhythm
3101 * as long as they act as if they were alone.
3102 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02003103 list_for_each_entry(ptif, &per_thread_init_list, list) {
3104 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003105 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02003106#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08003107 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02003108#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003109 exit(1);
3110 }
3111 }
3112
Willy Tarreau71092822019-06-10 09:51:04 +02003113 /* enabling protocols will result in fd_insert() calls to be performed,
3114 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02003115 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02003116 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02003117 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02003118 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02003119
Willy Tarreau34a150c2019-06-11 09:16:41 +02003120#ifdef USE_THREAD
3121 pthread_cond_broadcast(&init_cond);
3122 pthread_mutex_unlock(&init_mutex);
3123
3124 /* now wait for other threads to finish starting */
3125 pthread_mutex_lock(&init_mutex);
3126 while (init_left)
3127 pthread_cond_wait(&init_cond, &init_mutex);
3128 pthread_mutex_unlock(&init_mutex);
3129#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02003130
Willy Tarreaua45a8b52019-12-06 16:31:45 +01003131#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
3132 /* Let's refrain from using setuid executables. This way the impact of
3133 * an eventual vulnerability in a library remains limited. It may
3134 * impact external checks but who cares about them anyway ? In the
3135 * worst case it's possible to disable the option. Obviously we do this
3136 * in workers only. We can't hard-fail on this one as it really is
3137 * implementation dependent though we're interested in feedback, hence
3138 * the warning.
3139 */
3140 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
3141 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02003142 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 +01003143 ha_warning("Failed to disable setuid, please report to developers with detailed "
3144 "information about your operating system. You can silence this warning "
3145 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
3146 }
3147 }
3148#endif
3149
Willy Tarreaud96f1122019-12-03 07:07:36 +01003150#if defined(RLIMIT_NPROC)
3151 /* all threads have started, it's now time to prevent any new thread
3152 * or process from starting. Obviously we do this in workers only. We
3153 * can't hard-fail on this one as it really is implementation dependent
3154 * though we're interested in feedback, hence the warning.
3155 */
3156 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
3157 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
3158 static int warn_fail;
3159
Willy Tarreau18515722021-04-06 11:57:41 +02003160 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01003161 ha_warning("Failed to disable forks, please report to developers with detailed "
3162 "information about your operating system. You can silence this warning "
3163 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
3164 }
3165 }
3166#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003167 run_poll_loop();
3168
3169 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
3170 ptdf->fct();
3171
Willy Tarreau082b6282019-05-22 14:42:12 +02003172 list_for_each_entry(ptff, &per_thread_free_list, list)
3173 ptff->fct();
3174
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003175#ifdef USE_THREAD
Willy Tarreau291f6ff2022-07-04 13:36:16 +02003176 if (!_HA_ATOMIC_AND_FETCH(&ha_tgroup_info[ti->tgid-1].threads_enabled, ~ti->ltid_bit))
Willy Tarreaucce203a2022-06-24 15:55:11 +02003177 _HA_ATOMIC_AND(&all_tgroups_mask, ~tg->tgid_bit);
Willy Tarreauad92fdf2022-07-06 10:17:21 +02003178 if (!_HA_ATOMIC_AND_FETCH(&tg_ctx->stopping_threads, ~ti->ltid_bit))
3179 _HA_ATOMIC_AND(&stopping_tgroup_mask, ~tg->tgid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003180 if (tid > 0)
3181 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02003182#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003183 return NULL;
3184}
Christopher Faulet1d17c102017-08-29 15:38:48 +02003185
William Dauchyf9af9d72019-11-17 15:47:16 +01003186/* set uid/gid depending on global settings */
3187static void set_identity(const char *program_name)
3188{
3189 if (global.gid) {
3190 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
3191 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
3192 " without 'uid'/'user' is generally useless.\n", program_name);
3193
3194 if (setgid(global.gid) == -1) {
3195 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
3196 protocol_unbind_all();
3197 exit(1);
3198 }
3199 }
3200
3201 if (global.uid && setuid(global.uid) == -1) {
3202 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
3203 protocol_unbind_all();
3204 exit(1);
3205 }
3206}
3207
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208int main(int argc, char **argv)
3209{
3210 int err, retry;
3211 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02003212 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02003213 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
3214
Willy Tarreau41afd902022-07-21 09:55:22 +02003215 /* Catch broken toolchains */
3216 if (sizeof(long) != sizeof(void *) || (intovf + 0x7FFFFFFF >= intovf)) {
3217 const char *msg;
3218
3219 if (sizeof(long) != sizeof(void *))
3220 /* Apparently MingW64 was not made for us and can also break openssl */
3221 msg = "The compiler this program was built with uses unsupported integral type sizes.\n"
3222 "Most likely it follows the unsupported LLP64 model. Never try to link HAProxy\n"
3223 "against libraries built with that compiler either! Please only use a compiler\n"
3224 "producing ILP32 or LP64 programs for both programs and libraries.\n";
3225 else if (intovf + 0x7FFFFFFF >= intovf)
3226 /* Catch forced CFLAGS that miss 2-complement integer overflow */
3227 msg = "The source code was miscompiled by the compiler, which usually indicates that\n"
3228 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
3229 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
3230 "and INSTALL files to decide on the best way to pass your local build options.\n";
3231 else
3232 msg = "Bug in the compiler bug detection code, please report it to developers!\n";
3233
Willy Tarreau1335da32021-07-14 17:54:01 +02003234 fprintf(stderr,
3235 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
Willy Tarreau41afd902022-07-21 09:55:22 +02003236 "%s"
3237 "\nBuild options :"
Willy Tarreau1335da32021-07-14 17:54:01 +02003238#ifdef BUILD_TARGET
Willy Tarreau41afd902022-07-21 09:55:22 +02003239 "\n TARGET = " BUILD_TARGET
Willy Tarreau1335da32021-07-14 17:54:01 +02003240#endif
3241#ifdef BUILD_CPU
Willy Tarreau41afd902022-07-21 09:55:22 +02003242 "\n CPU = " BUILD_CPU
Willy Tarreau1335da32021-07-14 17:54:01 +02003243#endif
3244#ifdef BUILD_CC
Willy Tarreau41afd902022-07-21 09:55:22 +02003245 "\n CC = " BUILD_CC
Willy Tarreau1335da32021-07-14 17:54:01 +02003246#endif
3247#ifdef BUILD_CFLAGS
Willy Tarreau41afd902022-07-21 09:55:22 +02003248 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau1335da32021-07-14 17:54:01 +02003249#endif
3250#ifdef BUILD_OPTIONS
Willy Tarreau41afd902022-07-21 09:55:22 +02003251 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau1335da32021-07-14 17:54:01 +02003252#endif
3253#ifdef BUILD_DEBUG
Willy Tarreau41afd902022-07-21 09:55:22 +02003254 "\n DEBUG = " BUILD_DEBUG
Willy Tarreau1335da32021-07-14 17:54:01 +02003255#endif
Willy Tarreau41afd902022-07-21 09:55:22 +02003256 "\n\n", msg);
3257
Willy Tarreau1335da32021-07-14 17:54:01 +02003258 return 1;
3259 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260
Olivier Houchard5fa300d2018-02-03 15:15:21 +01003261 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003262
Willy Tarreaubf696402019-03-01 10:09:28 +01003263 /* take a copy of initial limits before we possibly change them */
3264 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02003265
3266 if (limit.rlim_max == RLIM_INFINITY)
3267 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01003268 rlim_fd_cur_at_boot = limit.rlim_cur;
3269 rlim_fd_max_at_boot = limit.rlim_max;
3270
Willy Tarreau5794fb02018-11-25 18:43:29 +01003271 /* process all initcalls in order of potential dependency */
3272 RUN_INITCALLS(STG_PREPARE);
3273 RUN_INITCALLS(STG_LOCK);
Willy Tarreau3ebe4d92022-02-18 14:51:49 +01003274 RUN_INITCALLS(STG_REGISTER);
Willy Tarreau34527d52022-02-17 17:45:58 +01003275
3276 /* now's time to initialize early boot variables */
3277 init_early(argc, argv);
3278
Willy Tarreau18f96d02022-02-23 17:25:00 +01003279 /* handles argument parsing */
3280 init_args(argc, argv);
3281
Willy Tarreau5794fb02018-11-25 18:43:29 +01003282 RUN_INITCALLS(STG_ALLOC);
3283 RUN_INITCALLS(STG_POOL);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003284 RUN_INITCALLS(STG_INIT);
3285
Willy Tarreau34527d52022-02-17 17:45:58 +01003286 /* this is the late init where the config is parsed */
Emeric Bruncf20bf12010-10-22 16:06:11 +02003287 init(argc, argv);
Willy Tarreau34527d52022-02-17 17:45:58 +01003288
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003289 signal_register_fct(SIGQUIT, dump, SIGQUIT);
3290 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
3291 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02003292 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293
Willy Tarreaue437c442010-03-17 18:02:46 +01003294 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
3295 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
3296 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003297 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003298 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003299
Willy Tarreaudc23a922011-02-16 11:10:36 +01003300 /* ulimits */
3301 if (!global.rlimit_nofile)
3302 global.rlimit_nofile = global.maxsock;
3303
3304 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01003305 limit.rlim_cur = global.rlimit_nofile;
3306 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
3307
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003308 if ((global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit) ||
Willy Tarreauc06557c2022-09-22 16:12:08 +02003309 raise_rlim_nofile(NULL, &limit) != 0) {
Willy Tarreauef635472016-06-21 11:48:18 +02003310 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003311 if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
3312 limit.rlim_cur = global.fd_hard_limit;
3313
William Dauchy0fec3ab2019-10-27 20:08:11 +01003314 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3315 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
3316 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003317 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003318 }
3319 else {
3320 /* try to set it to the max possible at least */
3321 limit.rlim_cur = limit.rlim_max;
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003322 if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
3323 limit.rlim_cur = global.fd_hard_limit;
3324
Willy Tarreauc06557c2022-09-22 16:12:08 +02003325 if (raise_rlim_nofile(&limit, &limit) == 0)
William Dauchy0fec3ab2019-10-27 20:08:11 +01003326 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02003327
William Dauchya5194602020-03-28 19:29:58 +01003328 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003329 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
3330 global.rlimit_nofile = limit.rlim_cur;
3331 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01003332 }
3333 }
3334
3335 if (global.rlimit_memmax) {
3336 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01003337 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01003338#ifdef RLIMIT_AS
3339 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003340 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3341 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3342 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003343 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003344 }
3345 else
William Dauchya5194602020-03-28 19:29:58 +01003346 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003347 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003348 }
3349#else
3350 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003351 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3352 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3353 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003354 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003355 }
3356 else
William Dauchya5194602020-03-28 19:29:58 +01003357 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003358 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003359 }
3360#endif
3361 }
3362
William Lallemandf82afbb2022-01-07 18:19:42 +01003363 /* Try to get the listeners FD from the previous process using
3364 * _getsocks on the stat socket, it must never been done in wait mode
3365 * and check mode
3366 */
3367 if (old_unixsocket &&
3368 !(global.mode & (MODE_MWORKER_WAIT|MODE_CHECK|MODE_CHECK_CONDITION))) {
William Lallemand85b0bd92017-06-01 17:38:53 +02003369 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02003370 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003371 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02003372 if (!(global.mode & MODE_MWORKER))
3373 exit(1);
3374 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02003375 }
3376 }
William Lallemand85b0bd92017-06-01 17:38:53 +02003377
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 /* We will loop at most 100 times with 10 ms delay each time.
3379 * That's at most 1 second. We only send a signal to old pids
3380 * if we cannot grab at least one port.
3381 */
3382 retry = MAX_START_RETRIES;
3383 err = ERR_NONE;
3384 while (retry >= 0) {
3385 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003386 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003387 /* exit the loop on no error or fatal error */
3388 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003389 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003390 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003391 break;
3392
3393 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3394 * listening sockets. So on those platforms, it would be wiser to
3395 * simply send SIGUSR1, which will not be undoable.
3396 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003397 if (tell_old_pids(SIGTTOU) == 0) {
3398 /* no need to wait if we can't contact old pids */
3399 retry = 0;
3400 continue;
3401 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 /* give some time to old processes to stop listening */
3403 w.tv_sec = 0;
3404 w.tv_usec = 10*1000;
3405 select(0, NULL, NULL, NULL, &w);
3406 retry--;
3407 }
3408
Willy Tarreaue91bff22020-09-02 11:11:43 +02003409 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003410 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003411 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Aurelien DARRAGON28a6d482023-01-17 16:30:52 +01003412 if (retry != MAX_START_RETRIES && nb_oldpids)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 tell_old_pids(SIGTTIN);
Aurelien DARRAGON28a6d482023-01-17 16:30:52 +01003414 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003415 exit(1);
3416 }
3417
William Lallemand944e6192018-11-21 15:48:31 +01003418 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003419 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003420 /* Note: we don't have to send anything to the old pids because we
3421 * never stopped them. */
3422 exit(1);
3423 }
3424
Willy Tarreaue91bff22020-09-02 11:11:43 +02003425 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003426 * the previous process gave us, we don't need them anymore
3427 */
Willy Tarreaub5101162022-01-28 18:28:18 +01003428 sock_drop_unused_old_sockets();
Willy Tarreaudd815982007-10-16 12:25:14 +02003429
Willy Tarreaubaaee002006-06-26 02:48:02 +02003430 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003431 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3432 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003433
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434 /* MODE_QUIET can inhibit alerts and warnings below this line */
3435
PiBa-NL149a81a2017-12-25 21:03:31 +01003436 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3437 /* either stdin/out/err are already closed or should stay as they are. */
3438 if ((global.mode & MODE_DAEMON)) {
3439 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3440 global.mode &= ~MODE_VERBOSE;
3441 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3442 }
3443 } else {
3444 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3445 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003446 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003447 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003448 }
3449
3450 /* open log & pid files before the chroot */
William Lallemand7b820a62022-02-14 09:02:14 +01003451 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) &&
3452 !(global.mode & MODE_MWORKER_WAIT) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003453 unlink(global.pidfile);
3454 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3455 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003456 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003457 if (nb_oldpids)
3458 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003459 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003460 exit(1);
3461 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003462 }
3463
Willy Tarreaub38651a2007-03-24 17:24:39 +01003464 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003465 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3466 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003467 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003468 exit(1);
3469 }
3470
Jackie Tapia749f74c2020-07-22 18:59:40 -05003471 /* If the user is not root, we'll still let them try the configuration
3472 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003473 */
3474 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003475 ha_warning("[%s.main()] Some options which require full privileges"
3476 " might not work well.\n"
3477 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003478
William Lallemand095ba4c2017-06-01 17:38:50 +02003479 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3480
3481 /* chroot if needed */
3482 if (global.chroot != NULL) {
3483 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003484 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003485 if (nb_oldpids)
3486 tell_old_pids(SIGTTIN);
3487 protocol_unbind_all();
3488 exit(1);
3489 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003490 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003491 }
3492
William Lallemand944e6192018-11-21 15:48:31 +01003493 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003494 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003495
William Lallemand27edc4b2019-05-07 17:49:33 +02003496 /* send a SIGTERM to workers who have a too high reloads number */
3497 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3498 mworker_kill_max_reloads(SIGTERM);
3499
Willy Tarreaubaaee002006-06-26 02:48:02 +02003500 /* Note that any error at this stage will be fatal because we will not
3501 * be able to restart the old pids.
3502 */
3503
William Dauchyf9af9d72019-11-17 15:47:16 +01003504 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3505 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003506
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507 /* check ulimits */
3508 limit.rlim_cur = limit.rlim_max = 0;
3509 getrlimit(RLIMIT_NOFILE, &limit);
3510 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003511 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3512 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3513 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3514 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3515 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003516 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003517 }
3518 else
3519 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003520 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003521 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3522 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003523 }
3524
Patrick Hemmer425d7ad2023-05-23 13:02:08 -04003525 if (global.prealloc_fd && fcntl((int)limit.rlim_cur - 1, F_GETFD) == -1) {
3526 if (dup2(0, (int)limit.rlim_cur - 1) == -1)
Aurelien DARRAGON33bbeec2023-05-26 14:04:18 +02003527 ha_warning("[%s.main()] Unable to preallocate file descriptor %d : %s",
3528 argv[0], (int)limit.rlim_cur - 1, strerror(errno));
Patrick Hemmer425d7ad2023-05-23 13:02:08 -04003529 else
3530 close((int)limit.rlim_cur - 1);
3531 }
3532
Willy Tarreauda4aa692023-05-17 09:02:21 +02003533 /* update the ready date a last time to also account for final setup time */
3534 clock_update_date(0, 1);
Willy Tarreauc7b93082023-05-16 19:19:36 +02003535 clock_adjust_now_offset();
Willy Tarreauda4aa692023-05-17 09:02:21 +02003536 ready_date = date;
3537
William Lallemand944e6192018-11-21 15:48:31 +01003538 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003539 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003540 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003541 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003542
William Lallemand095ba4c2017-06-01 17:38:50 +02003543 /*
3544 * if daemon + mworker: must fork here to let a master
3545 * process live in background before forking children
3546 */
William Lallemand73b85e72017-06-01 17:38:51 +02003547
3548 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3549 && (global.mode & MODE_MWORKER)
3550 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003551 ret = fork();
3552 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003553 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003554 protocol_unbind_all();
3555 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003556 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003557 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003558 } else /* change the process group ID in the child (master process) */
3559 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003560 }
William Lallemande20b6a62017-06-01 17:38:55 +02003561
William Lallemande20b6a62017-06-01 17:38:55 +02003562
William Lallemanddeed7802017-11-06 11:00:04 +01003563 /* if in master-worker mode, write the PID of the father */
3564 if (global.mode & MODE_MWORKER) {
3565 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003566 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003567 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003568 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003569 }
3570
Willy Tarreaubaaee002006-06-26 02:48:02 +02003571 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003572 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemandeba6a542022-09-26 12:54:39 +02003573 struct ring *tmp_startup_logs = NULL;
3574
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003575 if (global.mode & MODE_MWORKER)
3576 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003577
William Lallemandeba6a542022-09-26 12:54:39 +02003578 /* at this point the worker must have his own startup_logs buffer */
3579 tmp_startup_logs = startup_logs_dup(startup_logs);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003580 ret = fork();
3581 if (ret < 0) {
3582 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3583 protocol_unbind_all();
3584 exit(1); /* there has been an error */
3585 }
3586 else if (ret == 0) { /* child breaks here */
William Lallemandeba6a542022-09-26 12:54:39 +02003587 startup_logs_free(startup_logs);
3588 startup_logs = tmp_startup_logs;
Willy Tarreau3c032f22021-07-21 10:17:02 +02003589 /* This one must not be exported, it's internal! */
3590 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003591 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003592 }
3593 else { /* parent here */
3594 in_parent = 1;
3595
William Lallemand944e6192018-11-21 15:48:31 +01003596 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3597 char pidstr[100];
3598 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003599 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003600 }
3601 if (global.mode & MODE_MWORKER) {
3602 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003603
William Lallemand5d71a6b2021-11-09 15:25:31 +01003604 ha_notice("New worker (%d) forked\n", ret);
William Lallemand944e6192018-11-21 15:48:31 +01003605 /* find the right mworker_proc */
3606 list_for_each_entry(child, &proc_list, list) {
William Lallemandd4835a92022-07-21 00:52:43 +02003607 if (child->reloads == 0 &&
3608 child->options & PROC_O_TYPE_WORKER &&
3609 child->pid == -1) {
William Lallemand5a7f83a2023-02-17 16:23:52 +01003610 child->timestamp = date.tv_sec;
William Lallemand944e6192018-11-21 15:48:31 +01003611 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003612 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003613 break;
3614 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003615 }
3616 }
William Lallemand944e6192018-11-21 15:48:31 +01003617 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003618
William Lallemand944e6192018-11-21 15:48:31 +01003619 } else {
3620 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003621 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003622 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003623
3624#ifdef USE_CPU_AFFINITY
Willy Tarreau5b093412022-07-08 09:38:30 +02003625 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 +02003626
David CARLIERdf91cbd2022-01-06 18:53:50 +00003627#if defined(CPUSET_USE_CPUSET) || defined(__DragonFly__)
Willy Tarreau5b093412022-07-08 09:38:30 +02003628 struct hap_cpuset *set = &cpu_map[0].proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003629 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
David CARLIERdf91cbd2022-01-06 18:53:50 +00003630#elif defined(__FreeBSD__)
Willy Tarreau5b093412022-07-08 09:38:30 +02003631 struct hap_cpuset *set = &cpu_map[0].proc;
David CARLIERdf91cbd2022-01-06 18:53:50 +00003632 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003633#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003634 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003635#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003636 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003637 if (pidfd >= 0) {
3638 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3639 close(pidfd);
3640 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003641
3642 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003643 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003644
Willy Tarreaud67ff342021-06-15 07:58:09 +02003645 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003646 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
William Lallemandfab0fdc2021-11-09 18:01:22 +01003647 master = 1;
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003648
3649 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3650 (global.mode & MODE_DAEMON)) {
3651 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003652 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3653 stdio_quiet(-1);
3654
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003655 global.mode &= ~MODE_VERBOSE;
3656 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003657 }
3658
William Lallemandfab0fdc2021-11-09 18:01:22 +01003659 if (global.mode & MODE_MWORKER_WAIT) {
3660 /* only the wait mode handles the master CLI */
3661 mworker_loop();
3662 } else {
3663
William Lallemanda46a99e2022-07-07 14:00:36 +02003664#if defined(USE_SYSTEMD)
3665 if (global.tune.options & GTUNE_USE_SYSTEMD)
3666 sd_notifyf(0, "READY=1\nMAINPID=%lu\nSTATUS=Ready.\n", (unsigned long)getpid());
3667#endif
William Lallemandfab0fdc2021-11-09 18:01:22 +01003668 /* if not in wait mode, reload in wait mode to free the memory */
William Lallemand68192b22022-09-24 15:44:42 +02003669 setenv("HAPROXY_LOAD_SUCCESS", "1", 1);
William Lallemand836bda22021-11-09 18:16:47 +01003670 ha_notice("Loading success.\n");
William Lallemand68836742021-11-10 10:49:06 +01003671 proc_self->failedreloads = 0; /* reset the number of failure */
William Lallemandfab0fdc2021-11-09 18:01:22 +01003672 mworker_reexec_waitmode();
3673 }
William Lallemand1499b9b2017-06-07 15:04:47 +02003674 /* should never get there */
3675 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003676 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003677#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003678 ssl_free_dh();
3679#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003680 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003681 }
3682
William Lallemandcb11fd22017-06-01 17:38:52 +02003683 /* child must never use the atexit function */
3684 atexit_flag = 0;
3685
William Lallemandbc193052018-09-11 10:06:26 +02003686 /* close useless master sockets */
3687 if (global.mode & MODE_MWORKER) {
3688 struct mworker_proc *child, *it;
3689 master = 0;
3690
William Lallemand309dc9a2018-10-26 14:47:45 +02003691 mworker_cli_proxy_stop();
3692
William Lallemandbc193052018-09-11 10:06:26 +02003693 /* free proc struct of other processes */
3694 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003695 /* close the FD of the master side for all
3696 * workers, we don't need to close the worker
3697 * side of other workers since it's done with
3698 * the bind_proc */
William Lallemand7e018782022-01-28 21:56:24 +01003699 if (child->ipc_fd[0] >= 0) {
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003700 close(child->ipc_fd[0]);
William Lallemand7e018782022-01-28 21:56:24 +01003701 child->ipc_fd[0] = -1;
3702 }
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003703 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandd4835a92022-07-21 00:52:43 +02003704 child->reloads == 0 &&
3705 child->pid == -1) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003706 /* keep this struct if this is our pid */
3707 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003708 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003709 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003710 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003711 mworker_free_child(child);
3712 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003713 }
3714 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003715
William Lallemande1340412017-12-28 16:09:36 +01003716 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3717 devnullfd = open("/dev/null", O_RDWR, 0);
3718 if (devnullfd < 0) {
3719 ha_alert("Cannot open /dev/null\n");
3720 exit(EXIT_FAILURE);
3721 }
3722 }
3723
William Lallemand095ba4c2017-06-01 17:38:50 +02003724 /* Must chroot and setgid/setuid in the children */
3725 /* chroot if needed */
3726 if (global.chroot != NULL) {
3727 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003728 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003729 if (nb_oldpids)
3730 tell_old_pids(SIGTTIN);
3731 protocol_unbind_all();
3732 exit(1);
3733 }
3734 }
3735
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003736 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003737 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003738
William Lallemand7f80eb22017-05-26 18:19:55 +02003739 /* pass through every cli socket, and check if it's bound to
3740 * the current process and if it exposes listeners sockets.
3741 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3742 * */
3743
Willy Tarreau4975d142021-03-13 11:00:33 +01003744 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003745 struct bind_conf *bind_conf;
3746
Willy Tarreau4975d142021-03-13 11:00:33 +01003747 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003748 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003749 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3750 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003751 }
3752 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003753 }
3754
William Lallemand2e8fad92018-11-13 16:18:23 +01003755 /*
3756 * This is only done in daemon mode because we might want the
3757 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3758 * we should now close the 3 first FDs to ensure that we can
3759 * detach from the TTY. We MUST NOT do it in other cases since
3760 * it would have already be done, and 0-2 would have been
3761 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003762 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003763 if ((global.mode & MODE_DAEMON) &&
3764 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003765 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003766 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003767 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003768 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3769 }
3770 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003771 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3772 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003773 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003774 }
3775
William Dauchye039f262019-11-17 15:47:15 +01003776 /* try our best to re-enable core dumps depending on system capabilities.
3777 * What is addressed here :
3778 * - remove file size limits
3779 * - remove core size limits
3780 * - mark the process dumpable again if it lost it due to user/group
3781 */
3782 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3783 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3784
3785#if defined(RLIMIT_FSIZE)
3786 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3787 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3788 ha_alert("[%s.main()] Failed to set the raise the maximum "
3789 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003790 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003791 }
3792 else
3793 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003794 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003795 }
3796#endif
3797
3798#if defined(RLIMIT_CORE)
3799 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3800 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3801 ha_alert("[%s.main()] Failed to set the raise the core "
3802 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003803 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003804 }
3805 else
3806 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003807 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003808 }
3809#endif
3810
3811#if defined(USE_PRCTL)
3812 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3813 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3814 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003815#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003816 {
3817 int traceable = PROC_TRACE_CTL_ENABLE;
3818 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3819 ha_warning("[%s.main()] Failed to set the traceable flag, "
3820 "no core will be dumped.\n", argv[0]);
3821 }
William Dauchye039f262019-11-17 15:47:15 +01003822#endif
3823 }
3824
Christopher Faulete3a5e352017-10-24 13:53:54 +02003825 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003826 reset_usermsgs_ctx();
3827
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003828 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003829 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003830
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003831 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003832 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003833
3834 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003835 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003836
3837 /* wait for all threads to terminate */
3838 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003839
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003840 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841}
3842
Willy Tarreaubaaee002006-06-26 02:48:02 +02003843/*
3844 * Local variables:
3845 * c-indent-level: 8
3846 * c-basic-offset: 8
3847 * End:
3848 */