blob: ab37f3e141fa667d3703f365095681eebba9f4c7 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
Willy Tarreaua5357cd2021-05-09 06:14:25 +02002 * HAProxy : High Availability-enabled HTTP/TCP proxy
Willy Tarreau2454d6e2022-02-01 18:06:59 +01003 * Copyright 2000-2022 Willy Tarreau <willy@haproxy.org>.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
Ilya Shipitsin46a030c2020-07-05 16:36:08 +050010 * Please refer to RFC7230 - RFC7235 information about HTTP protocol, and
11 * RFC6265 for information about cookies usage. More generally, the IETF HTTP
Willy Tarreaubaaee002006-06-26 02:48:02 +020012 * Working Group's web site should be consulted for protocol related changes :
13 *
14 * http://ftp.ics.uci.edu/pub/ietf/http/
15 *
16 * Pending bugs (may be not fixed because never reproduced) :
17 * - solaris only : sometimes, an HTTP proxy with only a dispatch address causes
18 * the proxy to terminate (no core) if the client breaks the connection during
19 * the response. Seen on 1.1.8pre4, but never reproduced. May not be related to
20 * the snprintf() bug since requests were simple (GET / HTTP/1.0), but may be
21 * related to missing setsid() (fixed in 1.1.15)
22 * - a proxy with an invalid config will prevent the startup even if disabled.
23 *
24 * ChangeLog has moved to the CHANGELOG file.
25 *
Willy Tarreaubaaee002006-06-26 02:48:02 +020026 */
27
David Carlier7ece0962015-12-08 21:43:09 +000028#define _GNU_SOURCE
Willy Tarreaubaaee002006-06-26 02:48:02 +020029#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <string.h>
33#include <ctype.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020034#include <dirent.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020035#include <sys/stat.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <sys/time.h>
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <netinet/tcp.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42#include <netdb.h>
43#include <fcntl.h>
44#include <errno.h>
45#include <signal.h>
46#include <stdarg.h>
47#include <sys/resource.h>
Tim Duesterhusdfad6a42020-04-18 16:02:47 +020048#include <sys/utsname.h>
Marc-Antoine Perennou992709b2013-02-12 10:53:52 +010049#include <sys/wait.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <time.h>
51#include <syslog.h>
Michael Schererab012dd2013-01-12 18:35:19 +010052#include <grp.h>
Willy Tarreaud10385a2021-10-06 22:22:40 +020053
Willy Tarreau5e03dfa2021-10-06 22:53:51 +020054#ifdef USE_THREAD
55#include <pthread.h>
56#endif
57
Willy Tarreaufc6c0322012-11-16 16:12:27 +010058#ifdef USE_CPU_AFFINITY
Willy Tarreaufc6c0322012-11-16 16:12:27 +010059#include <sched.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000060#if defined(__FreeBSD__) || defined(__DragonFly__)
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020061#include <sys/param.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000062#ifdef __FreeBSD__
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020063#include <sys/cpuset.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000064#endif
David Carlier5e4c8e22019-09-13 05:12:58 +010065#endif
Willy Tarreaufc6c0322012-11-16 16:12:27 +010066#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020067
Willy Tarreau636848a2019-04-15 19:38:50 +020068#if defined(USE_PRCTL)
69#include <sys/prctl.h>
70#endif
71
devnexen@gmail.com21185972021-08-21 09:13:10 +010072#if defined(USE_PROCCTL)
73#include <sys/procctl.h>
74#endif
75
Willy Tarreaubaaee002006-06-26 02:48:02 +020076#ifdef DEBUG_FULL
77#include <assert.h>
78#endif
Tim Duesterhusd6942c82017-11-20 15:58:35 +010079#if defined(USE_SYSTEMD)
80#include <systemd/sd-daemon.h>
81#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020082
Willy Tarreau6c3a6812020-03-06 18:57:15 +010083#include <import/sha1.h>
84
Willy Tarreaub2551052020-06-09 09:07:15 +020085#include <haproxy/acl.h>
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +010086#include <haproxy/action.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020087#include <haproxy/activity.h>
88#include <haproxy/api.h>
89#include <haproxy/arg.h>
90#include <haproxy/auth.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020091#include <haproxy/base64.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020092#include <haproxy/capture-t.h>
Willy Tarreau66243b42021-07-16 15:39:28 +020093#include <haproxy/cfgcond.h>
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +020094#include <haproxy/cfgdiag.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020095#include <haproxy/cfgparse.h>
Willy Tarreauc13ed532020-06-02 10:22:45 +020096#include <haproxy/chunk.h>
Willy Tarreau83487a82020-06-04 20:19:54 +020097#include <haproxy/cli.h>
Willy Tarreau55542642021-10-08 09:33:24 +020098#include <haproxy/clock.h>
Willy Tarreau7ea393d2020-06-04 18:02:10 +020099#include <haproxy/connection.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200100#ifdef USE_CPU_AFFINITY
Amaury Denoyelle982fb532021-04-21 18:39:58 +0200101#include <haproxy/cpuset.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200102#endif
Willy Tarreaueb92deb2020-06-04 10:53:16 +0200103#include <haproxy/dns.h>
Willy Tarreau2741c8c2020-06-02 11:28:02 +0200104#include <haproxy/dynbuf.h>
Willy Tarreau8d366972020-05-27 16:10:29 +0200105#include <haproxy/errors.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200106#include <haproxy/fd.h>
Willy Tarreauc7babd82020-06-04 21:29:29 +0200107#include <haproxy/filters.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200108#include <haproxy/global.h>
Willy Tarreau86416052020-06-04 09:20:54 +0200109#include <haproxy/hlua.h>
Willy Tarreauc761f842020-06-04 11:40:28 +0200110#include <haproxy/http_rules.h>
Willy Tarreau853b2972020-05-27 18:01:47 +0200111#include <haproxy/list.h>
Willy Tarreau213e9902020-06-04 14:58:24 +0200112#include <haproxy/listener.h>
Willy Tarreauaeed4a82020-06-04 22:01:04 +0200113#include <haproxy/log.h>
Willy Tarreaub5abe5b2020-06-04 14:07:37 +0200114#include <haproxy/mworker.h>
Willy Tarreau7a00efb2020-06-02 17:02:59 +0200115#include <haproxy/namespace.h>
Willy Tarreau6131d6a2020-06-02 16:48:09 +0200116#include <haproxy/net_helper.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +0200117#include <haproxy/openssl-compat.h>
Frédéric Lécaille1d96d6e2022-05-23 16:38:14 +0200118#include <haproxy/quic_tp-t.h>
Willy Tarreau225a90a2020-06-04 15:06:28 +0200119#include <haproxy/pattern.h>
Willy Tarreau3c2a7c22020-06-04 18:38:21 +0200120#include <haproxy/peers.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200121#include <haproxy/pool.h>
122#include <haproxy/protocol.h>
Willy Tarreaubf3b06b2020-08-26 10:23:40 +0200123#include <haproxy/proto_tcp.h>
Willy Tarreaua264d962020-06-04 22:29:18 +0200124#include <haproxy/proxy.h>
Willy Tarreau7cd8b6e2020-06-02 17:32:26 +0200125#include <haproxy/regex.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200126#include <haproxy/sample.h>
Willy Tarreau1e56f922020-06-04 23:20:13 +0200127#include <haproxy/server.h>
Willy Tarreau48d25b32020-06-04 18:58:52 +0200128#include <haproxy/session.h>
Willy Tarreau3727a8a2020-06-04 17:37:26 +0200129#include <haproxy/signal.h>
Willy Tarreau063d47d2020-08-28 16:29:53 +0200130#include <haproxy/sock.h>
Willy Tarreau25140cc2020-08-28 15:40:33 +0200131#include <haproxy/sock_inet.h>
Willy Tarreau209108d2020-06-04 20:30:20 +0200132#include <haproxy/ssl_sock.h>
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +0200133#include <haproxy/stats-t.h>
Willy Tarreaudfd3de82020-06-04 23:46:14 +0200134#include <haproxy/stream.h>
Willy Tarreaucea0e1b2020-06-04 17:25:40 +0200135#include <haproxy/task.h>
Willy Tarreau3f567e42020-05-28 15:29:19 +0200136#include <haproxy/thread.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200137#include <haproxy/time.h>
138#include <haproxy/tools.h>
139#include <haproxy/uri_auth-t.h>
Willy Tarreaua1718922020-06-04 16:25:31 +0200140#include <haproxy/vars.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200141#include <haproxy/version.h>
Frédéric Lécaille92862102022-05-20 16:29:10 +0200142#include <haproxy/xprt_quic-t.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200143
Willy Tarreaubaaee002006-06-26 02:48:02 +0200144
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100145/* array of init calls for older platforms */
146DECLARE_INIT_STAGES;
147
Willy Tarreauf4596402021-04-10 16:53:05 +0200148/* create a read_mostly section to hold variables which are accessed a lot
149 * but which almost never change. The purpose is to isolate them in their
150 * own cache lines where they don't risk to be perturbated by write accesses
151 * to neighbor variables. We need to create an empty aligned variable for
152 * this. The fact that the variable is of size zero means that it will be
153 * eliminated at link time if no other variable uses it, but alignment will
154 * be respected.
155 */
156empty_t __read_mostly_align HA_SECTION("read_mostly") ALIGNED(64);
157
Willy Tarreauf0d3b732021-05-06 16:30:32 +0200158#ifdef BUILD_FEATURES
159const char *build_features = BUILD_FEATURES;
160#else
161const char *build_features = "";
162#endif
163
Willy Tarreau477ecd82010-01-03 21:12:30 +0100164/* list of config files */
165static struct list cfg_cfgfiles = LIST_HEAD_INIT(cfg_cfgfiles);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200166int pid; /* current process id */
167
Willy Tarreauef422ce2022-06-28 19:29:29 +0200168static unsigned long stopping_tgroup_mask; /* Thread groups acknowledging stopping */
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100169
Willy Tarreaubaaee002006-06-26 02:48:02 +0200170/* global options */
171struct global global = {
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100172 .hard_stop_after = TICK_ETERNITY,
Remi Tricot-Le Bretonb5d968d2022-04-08 18:04:18 +0200173 .close_spread_time = TICK_ETERNITY,
174 .close_spread_end = TICK_ETERNITY,
Amaury Denoyelle0f50cb92021-03-26 18:50:33 +0100175 .numa_cpu_mapping = 1,
Willy Tarreau149ab772019-01-26 14:27:06 +0100176 .nbthread = 0,
William Lallemand5f232402012-04-05 18:02:55 +0200177 .req_count = 0,
William Lallemand0f99e342011-10-12 17:50:54 +0200178 .logsrvs = LIST_HEAD_INIT(global.logsrvs),
Willy Tarreau197715a2022-04-25 19:29:10 +0200179 .maxzlibmem = DEFAULT_MAXZLIBMEM * 1024U * 1024U,
William Lallemandd85f9172012-11-09 17:05:39 +0100180 .comp_rate_lim = 0,
Emeric Brun850efd52014-01-29 12:24:34 +0100181 .ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED,
Emeric Bruned760922010-10-22 17:59:25 +0200182 .unix_bind = {
183 .ux = {
184 .uid = -1,
185 .gid = -1,
186 .mode = 0,
187 }
188 },
Willy Tarreau27a674e2009-08-17 07:23:33 +0200189 .tune = {
Willy Tarreau7ac908b2019-02-27 12:02:18 +0100190 .options = GTUNE_LISTENER_MQ,
Willy Tarreauc77d3642018-12-12 06:19:42 +0100191 .bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
Christopher Faulet546c4692020-01-22 14:31:21 +0100192 .maxrewrite = MAXREWRITE,
Willy Tarreaua24adf02014-11-27 01:11:56 +0100193 .reserved_bufs = RESERVED_BUFS,
Willy Tarreauf3045d22015-04-29 16:24:50 +0200194 .pattern_cache = DEFAULT_PAT_LRU_SIZE,
Olivier Houchard88698d92019-04-16 19:07:22 +0200195 .pool_low_ratio = 20,
196 .pool_high_ratio = 25,
Christopher Faulet41ba36f2019-07-19 09:36:45 +0200197 .max_http_hdr = MAX_HTTP_HDR,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200198#ifdef USE_OPENSSL
Emeric Brun46635772012-11-14 11:32:56 +0100199 .sslcachesize = SSLCACHESIZE,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200200#endif
William Lallemandf3747832012-11-09 12:33:10 +0100201 .comp_maxlevel = 1,
Willy Tarreau7e312732014-02-12 16:35:14 +0100202#ifdef DEFAULT_IDLE_TIMER
203 .idle_timer = DEFAULT_IDLE_TIMER,
204#else
205 .idle_timer = 1000, /* 1 second */
206#endif
Amaury Denoyelle97e84c62022-04-19 18:26:55 +0200207#ifdef USE_QUIC
Frédéric Lécailleaee67572022-05-23 18:29:39 +0200208 .quic_backend_max_idle_timeout = QUIC_TP_DFLT_BACK_MAX_IDLE_TIMEOUT,
209 .quic_frontend_max_idle_timeout = QUIC_TP_DFLT_FRONT_MAX_IDLE_TIMEOUT,
210 .quic_frontend_max_streams_bidi = QUIC_TP_DFLT_FRONT_MAX_STREAMS_BIDI,
Frédéric Lécaille92862102022-05-20 16:29:10 +0200211 .quic_retry_threshold = QUIC_DFLT_RETRY_THRESHOLD,
Amaury Denoyelle97e84c62022-04-19 18:26:55 +0200212 .quic_streams_buf = 30,
213#endif /* USE_QUIC */
Willy Tarreau27a674e2009-08-17 07:23:33 +0200214 },
Emeric Brun76d88952012-10-05 15:47:31 +0200215#ifdef USE_OPENSSL
216#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200217 .maxsslconn = DEFAULT_MAXSSLCONN,
218#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200219#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220 /* others NULL OK */
221};
222
223/*********************************************************************/
224
225int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100226int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200227int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100228int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100229int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100230int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreau392524d2022-02-17 18:10:36 +0100231int arg_mode = 0; /* MODE_DEBUG etc as passed on command line ... */
232char *change_dir = NULL; /* set when -C is passed */
233char *check_condition = NULL; /* check condition passed to -cc */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500235/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236 * or kill. We will send them a signal every 10 ms until we can bind to all
237 * our ports. With 200 retries, that's about 2 seconds.
238 */
239#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240static int *oldpids = NULL;
241static int oldpids_sig; /* use USR1 or TERM */
242
Olivier Houchardf73629d2017-04-05 22:33:04 +0200243/* Path to the unix socket we use to retrieve listener sockets from the old process */
244static const char *old_unixsocket;
245
William Lallemandcb11fd22017-06-01 17:38:52 +0200246int atexit_flag = 0;
247
Willy Tarreaubb545b42010-08-25 12:58:59 +0200248int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249const int zero = 0;
250const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200251const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100253char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200254char *localpeer = NULL;
Willy Tarreau76871a42022-03-08 16:01:40 +0100255static char *kwd_dump = NULL; // list of keyword dumps to produce
Willy Tarreaubaaee002006-06-26 02:48:02 +0200256
William Lallemand00417412020-06-05 14:08:41 +0200257static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200258
William Lallemandbc193052018-09-11 10:06:26 +0200259struct list proc_list = LIST_HEAD_INIT(proc_list);
260
261int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100262unsigned int rlim_fd_cur_at_boot = 0;
263unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200264
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100265/* per-boot randomness */
266unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
267
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200268/* takes the thread config in argument or NULL for any thread */
William Lallemandb3f2be32018-09-11 10:06:18 +0200269static void *run_thread_poll_loop(void *data);
270
Willy Tarreauff055502014-04-28 22:27:06 +0200271/* bitfield of a few warnings to emit just once (WARN_*) */
272unsigned int warned = 0;
273
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200274/* set if experimental features have been used for the current process */
Willy Tarreauedd42682022-02-25 10:10:00 +0100275unsigned int tainted = 0;
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200276
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200277unsigned int experimental_directives_allowed = 0;
278
279int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
280 char **errmsg)
281{
282 if (kw->flags & KWF_EXPERIMENTAL) {
283 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200284 memprintf(errmsg, "parsing [%s:%d] : '%s' directive is experimental, must be allowed via a global 'expose-experimental-directives'",
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200285 file, linenum, kw->kw);
286 return 1;
287 }
288 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
289 }
290
291 return 0;
292}
293
William Lallemande7361152018-10-26 14:47:36 +0200294/* master CLI configuration (-S flag) */
295struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100296
297/* These are strings to be reported in the output of "haproxy -vv". They may
298 * either be constants (in which case must_free must be zero) or dynamically
299 * allocated strings to pass to free() on exit, and in this case must_free
300 * must be non-zero.
301 */
302struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
303struct build_opts_str {
304 struct list list;
305 const char *str;
306 int must_free;
307};
308
Willy Tarreaubaaee002006-06-26 02:48:02 +0200309/*********************************************************************/
310/* general purpose functions ***************************************/
311/*********************************************************************/
312
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100313/* used to register some build option strings at boot. Set must_free to
314 * non-zero if the string must be freed upon exit.
315 */
316void hap_register_build_opts(const char *str, int must_free)
317{
318 struct build_opts_str *b;
319
320 b = calloc(1, sizeof(*b));
321 if (!b) {
322 fprintf(stderr, "out of memory\n");
323 exit(1);
324 }
325 b->str = str;
326 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200327 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100328}
329
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200330#define VERSION_MAX_ELTS 7
331
332/* This function splits an haproxy version string into an array of integers.
333 * The syntax of the supported version string is the following:
334 *
335 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
336 *
337 * This validates for example:
338 * 1.2.1-pre2, 1.2.1, 1.2.10.1, 1.3.16-rc1, 1.4-dev3, 1.5-dev18, 1.5-dev18-43
339 * 2.4-dev18-f6818d-20
340 *
341 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
342 * one fixed place in the array. The tags take a numeric value called <e> which
343 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
344 * considered as zero (henxe 1.5 and 1.5.0 are the same).
345 *
346 * The resulting values are:
347 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
348 * 1.2.1 1, 2, 1, 0, 3, 0, 0
349 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
350 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
351 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
352 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
353 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
354 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
355 *
356 * The function returns non-zero if the conversion succeeded, or zero if it
357 * failed.
358 */
359int split_version(const char *version, unsigned int *value)
360{
361 const char *p, *s;
362 char *error;
363 int nelts;
364
365 /* Initialize array with zeroes */
366 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
367 value[nelts] = 0;
368 value[4] = 3;
369
370 p = version;
371
372 /* If the version number is empty, return false */
373 if (*p == '\0')
374 return 0;
375
376 /* Convert first number <a> */
377 value[0] = strtol(p, &error, 10);
378 p = error + 1;
379 if (*error == '\0')
380 return 1;
381 if (*error == '-')
382 goto split_version_tag;
383 if (*error != '.')
384 return 0;
385
386 /* Convert first number <b> */
387 value[1] = strtol(p, &error, 10);
388 p = error + 1;
389 if (*error == '\0')
390 return 1;
391 if (*error == '-')
392 goto split_version_tag;
393 if (*error != '.')
394 return 0;
395
396 /* Convert first number <c> */
397 value[2] = strtol(p, &error, 10);
398 p = error + 1;
399 if (*error == '\0')
400 return 1;
401 if (*error == '-')
402 goto split_version_tag;
403 if (*error != '.')
404 return 0;
405
406 /* Convert first number <d> */
407 value[3] = strtol(p, &error, 10);
408 p = error + 1;
409 if (*error == '\0')
410 return 1;
411 if (*error != '-')
412 return 0;
413
414 split_version_tag:
415 /* Check for commit number */
416 if (*p >= '0' && *p <= '9')
417 goto split_version_commit;
418
419 /* Read tag */
420 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
421 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
422 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
423 else
424 goto split_version_commit;
425
426 /* Convert tag number */
427 value[5] = strtol(p, &error, 10);
428 p = error + 1;
429 if (*error == '\0')
430 return 1;
431 if (*error != '-')
432 return 0;
433
434 split_version_commit:
435 /* Search the last "-" */
436 s = strrchr(p, '-');
437 if (s) {
438 s++;
439 if (*s == '\0')
440 return 0;
441 value[6] = strtol(s, &error, 10);
442 if (*error != '\0')
443 value[6] = 0;
444 return 1;
445 }
446
447 /* convert the version */
448 value[6] = strtol(p, &error, 10);
449 if (*error != '\0')
450 value[6] = 0;
451
452 return 1;
453}
454
455/* This function compares the current haproxy version with an arbitrary version
456 * string. It returns:
457 * -1 : the version in argument is older than the current haproxy version
458 * 0 : the version in argument is the same as the current haproxy version
459 * 1 : the version in argument is newer than the current haproxy version
460 *
461 * Or some errors:
462 * -2 : the current haproxy version is not parsable
463 * -3 : the version in argument is not parsable
464 */
465int compare_current_version(const char *version)
466{
467 unsigned int loc[VERSION_MAX_ELTS];
468 unsigned int mod[VERSION_MAX_ELTS];
469 int i;
470
471 /* split versions */
472 if (!split_version(haproxy_version, loc))
473 return -2;
474 if (!split_version(version, mod))
475 return -3;
476
477 /* compare versions */
478 for (i = 0; i < VERSION_MAX_ELTS; i++) {
479 if (mod[i] < loc[i])
480 return -1;
481 else if (mod[i] > loc[i])
482 return 1;
483 }
484 return 0;
485}
486
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100487static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200488{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200489 struct utsname utsname;
490
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200491 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100492 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100493
494 if (strlen(PRODUCT_URL_BUGS) > 0) {
495 char base_version[20];
496 int dots = 0;
497 char *del;
498
499 /* only retrieve the base version without distro-specific extensions */
500 for (del = haproxy_version; *del; del++) {
501 if (*del == '.')
502 dots++;
503 else if (*del < '0' || *del > '9')
504 break;
505 }
506
507 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
508 if (dots < 2)
509 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
510 else
511 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
512 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200513
514 if (uname(&utsname) == 0) {
515 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
516 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200517}
518
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100519static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100520{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100521 struct build_opts_str *item;
522
Willy Tarreau7b066db2007-12-02 11:28:59 +0100523 printf("Build options :"
524#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100525 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100526#endif
527#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100528 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100529#endif
530#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100531 "\n CC = " BUILD_CC
532#endif
533#ifdef BUILD_CFLAGS
534 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100535#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100536#ifdef BUILD_OPTIONS
537 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100538#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100539#ifdef BUILD_DEBUG
540 "\n DEBUG = " BUILD_DEBUG
541#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100542#ifdef BUILD_FEATURES
543 "\n\nFeature list : " BUILD_FEATURES
544#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200545 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100546 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200547 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100548 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200549
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100550 list_for_each_entry(item, &build_opts_list, list) {
551 puts(item->str);
552 }
553
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100554 putchar('\n');
555
Willy Tarreaube5b6852009-10-03 18:57:08 +0200556 list_pollers(stdout);
557 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200558 list_mux_proto(stdout);
559 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100560 list_services(stdout);
561 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100562 list_filters(stdout);
563 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100564}
565
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566/*
567 * This function prints the command line usage and exits
568 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100569static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200570{
571 display_version();
572 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200573 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200574 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200575 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100576 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreauf4b79c42022-02-23 15:20:53 +0100578 " -dM[<byte>,help,...] debug memory (default: poison with <byte>/0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200580 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200581 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100582#if defined(USE_SYSTEMD)
583 " -Ws master-worker mode with systemd notify support.\n"
584#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200586 " -c check mode : only check config files and exit\n"
Maximilian Maderfc0cceb2021-06-06 00:50:22 +0200587 " -cc check condition : evaluate a condition and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100588 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 " -m limits the usable amount of memory (in MB)\n"
590 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200591 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200592 " -p writes pids of all children to this file\n"
Erwan Le Goasf30c5d72022-09-29 10:34:04 +0200593 " -dC[[key],line] display the configuration file, if there is a key, the file will be anonymised\n"
Willy Tarreaue5733232019-05-22 19:24:06 +0200594#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 " -de disables epoll() usage even when available\n"
596#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200597#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200598 " -dk disables kqueue() usage even when available\n"
599#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200600#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000601 " -dv disables event ports usage even when available\n"
602#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200603#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200604 " -dp disables poll() usage even when available\n"
605#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200606#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100607 " -dS disables splice usage (broken on old kernels)\n"
608#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200609#if defined(USE_GETADDRINFO)
610 " -dG disables getaddrinfo() usage\n"
611#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000612#if defined(SO_REUSEPORT)
613 " -dR disables SO_REUSEPORT usage\n"
614#endif
Willy Tarreau654726d2021-12-28 15:43:11 +0100615#if defined(HA_HAVE_DUMP_LIBS)
616 " -dL dumps loaded object files after config checks\n"
617#endif
Willy Tarreau76871a42022-03-08 16:01:40 +0100618 " -dK{class[,...]} dump registered keywords (use 'help' for list)\n"
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100619 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100620 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200621 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200622 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200623 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200624 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200625 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200626 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100627 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 exit(1);
629}
630
631
632
633/*********************************************************************/
634/* more specific functions ***************************************/
635/*********************************************************************/
636
William Lallemand73b85e72017-06-01 17:38:51 +0200637/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
638 * pids the signal was correctly delivered to.
639 */
William Lallemande25473c2019-04-01 11:29:56 +0200640int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200641{
642 int p;
643 int ret = 0;
644 for (p = 0; p < nb_oldpids; p++)
645 if (kill(oldpids[p], sig) == 0)
646 ret++;
647 return ret;
648}
649
William Lallemand75ea0a02017-11-15 19:02:58 +0100650/*
William Lallemand73b85e72017-06-01 17:38:51 +0200651 * remove a pid forom the olpid array and decrease nb_oldpids
652 * return 1 pid was found otherwise return 0
653 */
654
655int delete_oldpid(int pid)
656{
657 int i;
658
659 for (i = 0; i < nb_oldpids; i++) {
660 if (oldpids[i] == pid) {
661 oldpids[i] = oldpids[nb_oldpids - 1];
662 oldpids[nb_oldpids - 1] = 0;
663 nb_oldpids--;
664 return 1;
665 }
666 }
667 return 0;
668}
669
William Lallemand85b0bd92017-06-01 17:38:53 +0200670
William Lallemand73b85e72017-06-01 17:38:51 +0200671/*
672 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800673 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200674 */
William Lallemandfab0fdc2021-11-09 18:01:22 +0100675static void mworker_reexec()
William Lallemand73b85e72017-06-01 17:38:51 +0200676{
William Lallemand00417412020-06-05 14:08:41 +0200677 char **next_argv = NULL;
678 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200679 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200680 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200681 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100682 struct rlimit limit;
William Lallemand2be557f2021-11-24 18:45:37 +0100683 struct mworker_proc *current_child = NULL;
William Lallemand73b85e72017-06-01 17:38:51 +0200684
685 mworker_block_signals();
William Lallemand73b85e72017-06-01 17:38:51 +0200686 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
687
William Lallemand55a921c2022-01-28 21:17:30 +0100688 mworker_cleanup_proc();
William Lallemandbc193052018-09-11 10:06:26 +0200689 mworker_proc_list_to_env(); /* put the children description in the env */
690
William Lallemandc4810b82021-11-18 10:51:30 +0100691 /* ensure that we close correctly every listeners before reexecuting */
692 mworker_cleanlisteners();
693
William Lallemand7c756a82018-11-26 11:53:40 +0100694 /* during the reload we must ensure that every FDs that can't be
695 * reuse (ie those that are not referenced in the proc_list)
696 * are closed or they will leak. */
697
698 /* close the listeners FD */
699 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200700
William Lallemand67e371e2021-11-25 10:03:44 +0100701 if (fdtab)
702 deinit_pollers();
William Lallemandefd95472021-11-26 14:43:57 +0100703
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500704#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200705 /* close random device FDs */
706 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100707#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100708
Willy Tarreau8dca1952019-03-01 10:21:55 +0100709 /* restore the initial FD limits */
710 limit.rlim_cur = rlim_fd_cur_at_boot;
711 limit.rlim_max = rlim_fd_max_at_boot;
712 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
713 getrlimit(RLIMIT_NOFILE, &limit);
714 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
715 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
716 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
717 }
718
William Lallemand73b85e72017-06-01 17:38:51 +0200719 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200720 while (old_argv[old_argc])
721 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200722
William Lallemand85b0bd92017-06-01 17:38:53 +0200723 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200724 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200725 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200726 if (next_argv == NULL)
727 goto alloc_error;
728
William Lallemand00417412020-06-05 14:08:41 +0200729 /* copy the program name */
730 next_argv[next_argc++] = old_argv[0];
731
732 /* insert the new options just after argv[0] in case we have a -- */
733
William Lallemandbefab9e2021-11-25 00:49:19 +0100734 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
735 /* add -sf <PID>* to argv */
736 if (mworker_child_nb() > 0) {
737 struct mworker_proc *child;
William Lallemand3f128872019-04-01 11:29:59 +0200738
William Lallemandbefab9e2021-11-25 00:49:19 +0100739 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200740
William Lallemandbefab9e2021-11-25 00:49:19 +0100741 list_for_each_entry(child, &proc_list, list) {
742 if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
743 current_child = child;
William Lallemand2be557f2021-11-24 18:45:37 +0100744
William Lallemandbefab9e2021-11-25 00:49:19 +0100745 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
746 continue;
747 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
748 goto alloc_error;
749 msg = NULL;
750 }
William Lallemand73b85e72017-06-01 17:38:51 +0200751 }
William Lallemand2be557f2021-11-24 18:45:37 +0100752
753 if (current_child) {
754 /* add the -x option with the socketpair of the current worker */
755 next_argv[next_argc++] = "-x";
756 if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
757 goto alloc_error;
758 msg = NULL;
759 }
William Lallemand85b0bd92017-06-01 17:38:53 +0200760 }
761
William Lallemand00417412020-06-05 14:08:41 +0200762 /* copy the previous options */
763 for (i = 1; i < old_argc; i++)
764 next_argv[next_argc++] = old_argv[i];
765
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200766 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100767 execvp(next_argv[0], next_argv);
Christopher Faulet767a84b2017-11-24 16:50:31 +0100768 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100769 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100770 return;
771
William Lallemand73b85e72017-06-01 17:38:51 +0200772alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100773 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800774 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200775 return;
776}
777
William Lallemandfab0fdc2021-11-09 18:01:22 +0100778/* reexec haproxy in waitmode */
779static void mworker_reexec_waitmode()
780{
781 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
782 mworker_reexec();
783}
784
785/* reload haproxy and emit a warning */
786void mworker_reload()
787{
William Lallemandad221f42021-11-09 18:43:59 +0100788 struct mworker_proc *child;
William Lallemandefd95472021-11-26 14:43:57 +0100789 struct per_thread_deinit_fct *ptdf;
William Lallemandad221f42021-11-09 18:43:59 +0100790
William Lallemand836bda22021-11-09 18:16:47 +0100791 ha_notice("Reloading HAProxy\n");
William Lallemandad221f42021-11-09 18:43:59 +0100792
William Lallemandefd95472021-11-26 14:43:57 +0100793 /* close the poller FD and the thread waker pipe FD */
794 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
795 ptdf->fct();
796
William Lallemandad221f42021-11-09 18:43:59 +0100797 /* increment the number of reloads */
798 list_for_each_entry(child, &proc_list, list) {
799 child->reloads++;
800 }
801
William Lallemanda46a99e2022-07-07 14:00:36 +0200802#if defined(USE_SYSTEMD)
803 if (global.tune.options & GTUNE_USE_SYSTEMD)
804 sd_notify(0, "RELOADING=1\nSTATUS=Reloading Configuration.\n");
805#endif
William Lallemandfab0fdc2021-11-09 18:01:22 +0100806 mworker_reexec();
807}
808
William Lallemandb3f2be32018-09-11 10:06:18 +0200809static void mworker_loop()
810{
811
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200812 /* Busy polling makes no sense in the master :-) */
813 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200814
William Lallemandbc193052018-09-11 10:06:26 +0200815
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100816 signal_unregister(SIGTTIN);
817 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100818 signal_unregister(SIGUSR1);
819 signal_unregister(SIGHUP);
820 signal_unregister(SIGQUIT);
821
William Lallemandb3f2be32018-09-11 10:06:18 +0200822 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
823 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100824 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
825 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200826 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
827 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
828 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
829 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
830
831 mworker_unblock_signals();
William Lallemand27f3fa52018-12-06 14:05:20 +0100832 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200833
William Lallemandbc193052018-09-11 10:06:26 +0200834 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
835 some SIGCHLD were lost */
836
William Lallemandb3f2be32018-09-11 10:06:18 +0200837 jobs++; /* this is the "master" job, we want to take care of the
838 signals even if there is no listener so the poll loop don't
839 leave */
840
841 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200842 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200843}
William Lallemandcb11fd22017-06-01 17:38:52 +0200844
845/*
846 * Reexec the process in failure mode, instead of exiting
847 */
848void reexec_on_failure()
849{
William Lallemand68836742021-11-10 10:49:06 +0100850 struct mworker_proc *child;
851
William Lallemandcb11fd22017-06-01 17:38:52 +0200852 if (!atexit_flag)
853 return;
William Lallemand68836742021-11-10 10:49:06 +0100854
855 /* get the info of the children in the env */
856 if (mworker_env_to_proc_list() < 0) {
857 exit(EXIT_FAILURE);
858 }
859
860 /* increment the number of failed reloads */
861 list_for_each_entry(child, &proc_list, list) {
862 child->failedreloads++;
863 }
864
Willy Tarreaue08acae2022-01-28 18:40:06 +0100865 /* do not keep unused FDs retrieved from the previous process */
866 sock_drop_unused_old_sockets();
867
William Lallemandfab0fdc2021-11-09 18:01:22 +0100868 usermsgs_clr(NULL);
William Lallemand68192b22022-09-24 15:44:42 +0200869 setenv("HAPROXY_LOAD_SUCCESS", "0", 1);
William Lallemand836bda22021-11-09 18:16:47 +0100870 ha_warning("Loading failure!\n");
William Lallemanda46a99e2022-07-07 14:00:36 +0200871#if defined(USE_SYSTEMD)
872 /* the sd_notify API is not able to send a reload failure signal. So
873 * the READY=1 signal still need to be sent */
874 if (global.tune.options & GTUNE_USE_SYSTEMD)
875 sd_notify(0, "READY=1\nSTATUS=Reload failed!\n");
876#endif
877
William Lallemandfab0fdc2021-11-09 18:01:22 +0100878 mworker_reexec_waitmode();
William Lallemandcb11fd22017-06-01 17:38:52 +0200879}
William Lallemand73b85e72017-06-01 17:38:51 +0200880
881
882/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200883 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
884 * a signal zero to all subscribers. This means that it's as easy as
885 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100887static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888{
889 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200890 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100891 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892}
893
894/*
895 * upon SIGTTOU, we pause everything
896 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100897static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898{
Willy Tarreau775e0012020-09-24 16:36:26 +0200899 if (protocol_pause_all() & ERR_FATAL) {
900 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200901 ha_warning("%s", msg);
902 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200903 soft_stop();
904 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100905 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906}
907
908/*
909 * upon SIGTTIN, let's have a soft stop.
910 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100911static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200912{
Willy Tarreau775e0012020-09-24 16:36:26 +0200913 if (protocol_resume_all() & ERR_FATAL) {
914 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 +0200915 ha_warning("%s", msg);
916 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200917 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918}
919
920/*
921 * this function dumps every server's state when the process receives SIGHUP.
922 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100923static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100925 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926
Christopher Faulet767a84b2017-11-24 16:50:31 +0100927 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200928 while (p) {
929 struct server *s = p->srv;
930
931 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
932 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100933 chunk_printf(&trash,
934 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
935 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200936 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200937 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200938 ha_warning("%s\n", trash.area);
939 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200940 s = s->next;
941 }
942
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200943 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
944 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100945 chunk_printf(&trash,
946 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
947 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200948 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 +0200949 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100950 chunk_printf(&trash,
951 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
952 p->id,
953 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200954 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 +0200955 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100956 chunk_printf(&trash,
957 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
958 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
959 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200960 p->feconn, p->beconn, p->totpend, p->queue.length, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200962 ha_warning("%s\n", trash.area);
963 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964
965 p = p->next;
966 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967}
968
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100969static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200971 /* dump memory usage then free everything possible */
972 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100973 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974}
975
William Lallemande1340412017-12-28 16:09:36 +0100976/*
977 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
978 * If <fd> < 0, it opens /dev/null and use it to dup
979 *
980 * In the case of chrooting, you have to open /dev/null before the chroot, and
981 * pass the <fd> to this function
982 */
983static void stdio_quiet(int fd)
984{
985 if (fd < 0)
986 fd = open("/dev/null", O_RDWR, 0);
987
988 if (fd > -1) {
989 fclose(stdin);
990 fclose(stdout);
991 fclose(stderr);
992
993 dup2(fd, 0);
994 dup2(fd, 1);
995 dup2(fd, 2);
996 if (fd > 2)
997 close(fd);
998 return;
999 }
1000
1001 ha_alert("Cannot open /dev/null\n");
1002 exit(EXIT_FAILURE);
1003}
1004
1005
Joseph Herlant03420902018-11-15 10:41:50 -08001006/* This function checks if cfg_cfgfiles contains directories.
1007 * If it finds one, it adds all the files (and only files) it contains
1008 * in cfg_cfgfiles in place of the directory (and removes the directory).
1009 * It adds the files in lexical order.
1010 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001011 * It doesn't add files with name starting with '.'
1012 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001013static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001014{
1015 struct wordlist *wl, *wlb;
1016 char *err = NULL;
1017
1018 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1019 struct stat file_stat;
1020 struct dirent **dir_entries = NULL;
1021 int dir_entries_nb;
1022 int dir_entries_it;
1023
1024 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001025 ha_alert("Cannot open configuration file/directory %s : %s\n",
1026 wl->s,
1027 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001028 exit(1);
1029 }
1030
1031 if (!S_ISDIR(file_stat.st_mode))
1032 continue;
1033
1034 /* from this point wl->s is a directory */
1035
1036 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1037 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001038 ha_alert("Cannot open configuration directory %s : %s\n",
1039 wl->s,
1040 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001041 exit(1);
1042 }
1043
1044 /* for each element in the directory wl->s */
1045 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1046 struct dirent *dir_entry = dir_entries[dir_entries_it];
1047 char *filename = NULL;
1048 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1049
1050 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001051 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001052 */
1053 if (dir_entry->d_name[0] == '.' ||
1054 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1055 goto next_dir_entry;
1056
1057 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001058 ha_alert("Cannot load configuration files %s : out of memory.\n",
1059 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001060 exit(1);
1061 }
1062
1063 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001064 ha_alert("Cannot open configuration file %s : %s\n",
1065 wl->s,
1066 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001067 exit(1);
1068 }
1069
1070 /* don't add anything else than regular file in cfg_cfgfiles
1071 * this way we avoid loops
1072 */
1073 if (!S_ISREG(file_stat.st_mode))
1074 goto next_dir_entry;
1075
1076 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001077 ha_alert("Cannot load configuration files %s : %s\n",
1078 filename,
1079 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001080 exit(1);
1081 }
1082
1083next_dir_entry:
1084 free(filename);
1085 free(dir_entry);
1086 }
1087
1088 free(dir_entries);
1089
1090 /* remove the current directory (wl) from cfg_cfgfiles */
1091 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001092 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001093 free(wl);
1094 }
1095
1096 free(err);
1097}
1098
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099/*
William Lallemand73b85e72017-06-01 17:38:51 +02001100 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001101 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001102 * Return an allocated copy of argv
1103 */
1104
1105static char **copy_argv(int argc, char **argv)
1106{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001107 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001108
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001109 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001110 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001111 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001112 return NULL;
1113 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001114 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001115
William Lallemanddf6c5a82020-06-04 17:40:23 +02001116 /* first copy argv[0] */
1117 *newargv++ = *argv++;
1118 argc--;
1119
1120 while (argc > 0) {
1121 if (**argv != '-') {
1122 /* non options are copied but will fail in the argument parser */
1123 *newargv++ = *argv++;
1124 argc--;
1125
1126 } else {
1127 char *flag;
1128
1129 flag = *argv + 1;
1130
1131 if (flag[0] == '-' && flag[1] == 0) {
1132 /* "--\0" copy every arguments till the end of argv */
1133 *newargv++ = *argv++;
1134 argc--;
1135
1136 while (argc > 0) {
1137 *newargv++ = *argv++;
1138 argc--;
1139 }
1140 } else {
1141 switch (*flag) {
1142 case 's':
1143 /* -sf / -st and their parameters are ignored */
1144 if (flag[1] == 'f' || flag[1] == 't') {
1145 argc--;
1146 argv++;
1147 /* The list can't contain a negative value since the only
1148 way to know the end of this list is by looking for the
1149 next option or the end of the options */
1150 while (argc > 0 && argv[0][0] != '-') {
1151 argc--;
1152 argv++;
1153 }
William Lallemand398da622020-09-02 16:12:23 +02001154 } else {
1155 argc--;
1156 argv++;
1157
William Lallemanddf6c5a82020-06-04 17:40:23 +02001158 }
1159 break;
1160
1161 case 'x':
1162 /* this option and its parameter are ignored */
1163 argc--;
1164 argv++;
1165 if (argc > 0) {
1166 argc--;
1167 argv++;
1168 }
1169 break;
1170
1171 case 'C':
1172 case 'n':
1173 case 'm':
1174 case 'N':
1175 case 'L':
1176 case 'f':
1177 case 'p':
1178 case 'S':
1179 /* these options have only 1 parameter which must be copied and can start with a '-' */
1180 *newargv++ = *argv++;
1181 argc--;
1182 if (argc == 0)
1183 goto error;
1184 *newargv++ = *argv++;
1185 argc--;
1186 break;
1187 default:
1188 /* for other options just copy them without parameters, this is also done
1189 * for options like "--foo", but this will fail in the argument parser.
1190 * */
1191 *newargv++ = *argv++;
1192 argc--;
1193 break;
1194 }
William Lallemand73b85e72017-06-01 17:38:51 +02001195 }
1196 }
William Lallemand73b85e72017-06-01 17:38:51 +02001197 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001198
William Lallemanddf6c5a82020-06-04 17:40:23 +02001199 return retargv;
1200
1201error:
1202 free(retargv);
1203 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001204}
1205
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001206
1207/* Performs basic random seed initialization. The main issue with this is that
1208 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1209 * which means that there will only be 4 billion possible random sequences once
1210 * srandom() is called, regardless of the internal state. Not calling it is
1211 * even worse as we'll always produce the same randoms sequences. What we do
1212 * here is to create an initial sequence from various entropy sources, hash it
1213 * using SHA1 and keep the resulting 160 bits available globally.
1214 *
1215 * We initialize the current process with the first 32 bits before starting the
1216 * polling loop, where all this will be changed to have process specific and
1217 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001218 *
1219 * Before starting threads, it's still possible to call random() as srandom()
1220 * is initialized from this, but after threads and/or processes are started,
1221 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001222 */
1223static void ha_random_boot(char *const *argv)
1224{
1225 unsigned char message[256];
1226 unsigned char *m = message;
1227 struct timeval tv;
1228 blk_SHA_CTX ctx;
1229 unsigned long l;
1230 int fd;
1231 int i;
1232
1233 /* start with current time as pseudo-random seed */
1234 gettimeofday(&tv, NULL);
1235 write_u32(m, tv.tv_sec); m += 4;
1236 write_u32(m, tv.tv_usec); m += 4;
1237
1238 /* PID and PPID add some OS-based randomness */
1239 write_u16(m, getpid()); m += 2;
1240 write_u16(m, getppid()); m += 2;
1241
1242 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1243 fd = open("/dev/urandom", O_RDONLY);
1244 if (fd >= 0) {
1245 i = read(fd, m, 20);
1246 if (i > 0)
1247 m += i;
1248 close(fd);
1249 }
1250
1251 /* take up to 160 bits bytes from openssl (non-blocking) */
1252#ifdef USE_OPENSSL
1253 if (RAND_bytes(m, 20) == 1)
1254 m += 20;
1255#endif
1256
1257 /* take 160 bits from existing random in case it was already initialized */
1258 for (i = 0; i < 5; i++) {
1259 write_u32(m, random());
1260 m += 4;
1261 }
1262
1263 /* stack address (benefit form operating system's ASLR) */
1264 l = (unsigned long)&m;
1265 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1266
1267 /* argv address (benefit form operating system's ASLR) */
1268 l = (unsigned long)&argv;
1269 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1270
1271 /* use tv_usec again after all the operations above */
1272 gettimeofday(&tv, NULL);
1273 write_u32(m, tv.tv_usec); m += 4;
1274
1275 /*
1276 * At this point, ~84-92 bytes have been used
1277 */
1278
1279 /* finish with the hostname */
1280 strncpy((char *)m, hostname, message + sizeof(message) - m);
1281 m += strlen(hostname);
1282
1283 /* total message length */
1284 l = m - message;
1285
1286 memset(&ctx, 0, sizeof(ctx));
1287 blk_SHA1_Init(&ctx);
1288 blk_SHA1_Update(&ctx, message, l);
1289 blk_SHA1_Final(boot_seed, &ctx);
1290
1291 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001292 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001293}
1294
Willy Tarreau5a023f02019-03-01 14:19:31 +01001295/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1296 * setting, and returns it. It may return -1 meaning "unlimited" if some
1297 * unlimited proxies have been found and the global.maxconn value is not yet
1298 * set. It may also return a value greater than maxconn if it's not yet set.
1299 * Note that a value of zero means there is no need for pipes. -1 is never
1300 * returned if global.maxconn is valid.
1301 */
1302static int compute_ideal_maxpipes()
1303{
1304 struct proxy *cur;
1305 int nbfe = 0, nbbe = 0;
1306 int unlimited = 0;
1307 int pipes;
1308 int max;
1309
1310 for (cur = proxies_list; cur; cur = cur->next) {
1311 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1312 if (cur->cap & PR_CAP_FE) {
1313 max = cur->maxconn;
1314 nbfe += max;
1315 if (!max) {
1316 unlimited = 1;
1317 break;
1318 }
1319 }
1320 if (cur->cap & PR_CAP_BE) {
1321 max = cur->fullconn ? cur->fullconn : global.maxconn;
1322 nbbe += max;
1323 if (!max) {
1324 unlimited = 1;
1325 break;
1326 }
1327 }
1328 }
1329 }
1330
1331 pipes = MAX(nbfe, nbbe);
1332 if (global.maxconn) {
1333 if (pipes > global.maxconn || unlimited)
1334 pipes = global.maxconn;
1335 } else if (unlimited) {
1336 pipes = -1;
1337 }
1338
1339 return pipes >= 4 ? pipes / 4 : pipes;
1340}
1341
Willy Tarreauac350932019-03-01 15:43:14 +01001342/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1343 * rlimits and computes an ideal maxconn. It's meant to be called only when
1344 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001345 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1346 * default 100) is returned as it is expected that it will even run on tight
1347 * environments, and will maintain compatibility with previous packages that
1348 * used to rely on this value as the default one. The system will emit a
1349 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001350 */
1351static int compute_ideal_maxconn()
1352{
1353 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1354 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1355 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001356 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001357 int maxconn;
1358
1359 /* we have to take into account these elements :
1360 * - number of engine_fds, which inflates the number of FD needed per
1361 * connection by this number.
1362 * - number of pipes per connection on average : for the unlimited
1363 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1364 * fixed value of 2*pipes.
1365 * - two FDs per connection
1366 */
1367
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02001368 if (global.fd_hard_limit && remain > global.fd_hard_limit)
1369 remain = global.fd_hard_limit;
1370
Willy Tarreauac350932019-03-01 15:43:14 +01001371 /* subtract listeners and checks */
1372 remain -= global.maxsock;
1373
Willy Tarreau3f200852019-03-14 19:13:17 +01001374 /* one epoll_fd/kqueue_fd per thread */
1375 remain -= global.nbthread;
1376
1377 /* one wake-up pipe (2 fd) per thread */
1378 remain -= 2 * global.nbthread;
1379
Willy Tarreauac350932019-03-01 15:43:14 +01001380 /* Fixed pipes values : we only subtract them if they're not larger
1381 * than the remaining FDs because pipes are optional.
1382 */
1383 if (pipes >= 0 && pipes * 2 < remain)
1384 remain -= pipes * 2;
1385
1386 if (pipes < 0) {
1387 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1388 * = maxconn * (2 + 0.5 + engine_fds)
1389 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1390 */
1391 maxconn = 2 * remain / (5 + 2 * engine_fds);
1392 } else {
1393 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1394 * = maxconn * (2 + engine_fds)
1395 */
1396 maxconn = remain / (2 + engine_fds);
1397 }
1398
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001399 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001400}
1401
Willy Tarreaua409f302020-03-10 17:08:53 +01001402/* computes the estimated maxsock value for the given maxconn based on the
1403 * possibly set global.maxpipes and existing partial global.maxsock. It may
1404 * temporarily change global.maxconn for the time needed to propagate the
1405 * computations, and will reset it.
1406 */
1407static int compute_ideal_maxsock(int maxconn)
1408{
1409 int maxpipes = global.maxpipes;
1410 int maxsock = global.maxsock;
1411
1412
1413 if (!maxpipes) {
1414 int old_maxconn = global.maxconn;
1415
1416 global.maxconn = maxconn;
1417 maxpipes = compute_ideal_maxpipes();
1418 global.maxconn = old_maxconn;
1419 }
1420
1421 maxsock += maxconn * 2; /* each connection needs two sockets */
1422 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1423 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1424 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1425
1426 /* compute fd used by async engines */
1427 if (global.ssl_used_async_engines) {
1428 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1429
1430 maxsock += maxconn * sides * global.ssl_used_async_engines;
1431 }
1432 return maxsock;
1433}
1434
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001435/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001436 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1437 * value is accepted, non-zero otherwise. This is used to determine if an
1438 * automatic limit may be applied or not. When it is not, the caller knows that
1439 * the highest we can do is the rlim_max at boot. In case of error, we return
1440 * that the setting is possible, so that we defer the error processing to the
1441 * final stage in charge of enforcing this.
1442 */
1443static int check_if_maxsock_permitted(int maxsock)
1444{
1445 struct rlimit orig_limit, test_limit;
1446 int ret;
1447
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02001448 if (global.fd_hard_limit && maxsock > global.fd_hard_limit)
1449 return 0;
1450
Willy Tarreau304e17e2020-03-10 17:54:54 +01001451 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1452 return 1;
1453
1454 /* don't go further if we can't even set to what we have */
1455 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1456 return 1;
1457
1458 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1459 test_limit.rlim_cur = test_limit.rlim_max;
1460 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1461
1462 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1463 return 1;
1464
1465 return ret == 0;
1466}
1467
Willy Tarreau34527d52022-02-17 17:45:58 +01001468/* This performs th every basic early initialization at the end of the PREPARE
1469 * init stage. It may only assume that list heads are initialized, but not that
1470 * anything else is correct. It will initialize a number of variables that
1471 * depend on command line and will pre-parse the command line. If it fails, it
1472 * directly exits.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473 */
Willy Tarreau34527d52022-02-17 17:45:58 +01001474static void init_early(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001475{
Kevinm48936af2010-12-22 16:08:21 +00001476 char *progname;
Willy Tarreau34527d52022-02-17 17:45:58 +01001477 char *tmp;
1478 int len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001479
Willy Tarreau34527d52022-02-17 17:45:58 +01001480 /* First, let's initialize most global variables */
1481 totalconn = actconn = listeners = stopping = 0;
1482 killed = pid = 0;
1483
1484 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
1485 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Christopher Faulete3a5e352017-10-24 13:53:54 +02001486 global.mode = MODE_STARTING;
William Lallemand73b85e72017-06-01 17:38:51 +02001487
Willy Tarreau34527d52022-02-17 17:45:58 +01001488 /* if we were in mworker mode, we should restart in mworker mode */
1489 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1490 global.mode |= MODE_MWORKER;
David du Colombier7af46052012-05-16 14:16:48 +02001491
Willy Tarreau34527d52022-02-17 17:45:58 +01001492 /* initialize date, time, and pid */
1493 tzset();
1494 clock_init_process_date();
1495 start_date = now;
1496 pid = getpid();
1497
1498 /* Set local host name and adjust some environment variables.
1499 * NB: POSIX does not make it mandatory for gethostname() to
1500 * NULL-terminate the string in case of truncation, and at least
1501 * FreeBSD appears not to do it.
Emeric Brun2b920a12010-09-23 18:30:22 +02001502 */
1503 memset(hostname, 0, sizeof(hostname));
1504 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001505
Willy Tarreau34527d52022-02-17 17:45:58 +01001506 /* preset some environment variables */
1507 localpeer = strdup(hostname);
1508 if (!localpeer || setenv("HAPROXY_LOCALPEER", localpeer, 1) < 0) {
Dragan Dosen4f014152020-06-18 16:56:47 +02001509 ha_alert("Cannot allocate memory for local peer.\n");
1510 exit(EXIT_FAILURE);
1511 }
Emeric Brun2b920a12010-09-23 18:30:22 +02001512
Willy Tarreau34527d52022-02-17 17:45:58 +01001513 /* Some CPU affinity stuff may have to be initialized */
1514#ifdef USE_CPU_AFFINITY
1515 {
Willy Tarreau5b093412022-07-08 09:38:30 +02001516 int g, i;
1517
1518 for (g = 0; g < MAX_TGROUPS; g++) {
1519 ha_cpuset_zero(&cpu_map[g].proc);
1520 ha_cpuset_zero(&cpu_map[g].proc_t1);
1521 for (i = 0; i < MAX_THREADS_PER_GROUP; ++i) {
1522 ha_cpuset_zero(&cpu_map[g].thread[i]);
1523 }
Willy Tarreau34527d52022-02-17 17:45:58 +01001524 }
1525 }
1526#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001527
Willy Tarreau34527d52022-02-17 17:45:58 +01001528 /* extract the program name from argv[0], it will be used for the logs
1529 * and error messages.
1530 */
1531 progname = *argv;
1532 while ((tmp = strchr(progname, '/')) != NULL)
1533 progname = tmp + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001534
Willy Tarreau34527d52022-02-17 17:45:58 +01001535 len = strlen(progname);
1536 progname = strdup(progname);
1537 if (!progname) {
1538 ha_alert("Cannot allocate memory for log_tag.\n");
1539 exit(EXIT_FAILURE);
1540 }
Willy Tarreau84310e22014-02-14 11:59:04 +01001541
Willy Tarreau34527d52022-02-17 17:45:58 +01001542 chunk_initlen(&global.log_tag, progname, len, len);
1543}
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001544
Willy Tarreau392524d2022-02-17 18:10:36 +01001545/* handles program arguments. Very minimal parsing is performed, variables are
1546 * fed with some values, and lists are completed with other ones. In case of
1547 * error, it will exit.
Willy Tarreau34527d52022-02-17 17:45:58 +01001548 */
Willy Tarreau392524d2022-02-17 18:10:36 +01001549static void init_args(int argc, char **argv)
Willy Tarreau34527d52022-02-17 17:45:58 +01001550{
Willy Tarreau34527d52022-02-17 17:45:58 +01001551 char *progname = global.log_tag.area;
Willy Tarreau392524d2022-02-17 18:10:36 +01001552 char *err_msg = NULL;
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001553
Willy Tarreau34527d52022-02-17 17:45:58 +01001554 /* pre-fill in the global tuning options before we let the cmdline
1555 * change them.
1556 */
Willy Tarreau43b78992009-01-25 15:42:27 +01001557 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001558#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001559 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001561#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001562 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001564#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001565 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001566#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001567#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001568 global.tune.options |= GTUNE_USE_EVPORTS;
1569#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001570#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001571 global.tune.options |= GTUNE_USE_SPLICE;
1572#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001573#if defined(USE_GETADDRINFO)
1574 global.tune.options |= GTUNE_USE_GAI;
1575#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001576#if defined(SO_REUSEPORT)
1577 global.tune.options |= GTUNE_USE_REUSEPORT;
1578#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001579#ifdef USE_THREAD
1580 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1581#endif
William Dauchya5194602020-03-28 19:29:58 +01001582 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583
Willy Tarreau392524d2022-02-17 18:10:36 +01001584 /* keep a copy of original arguments for the master process */
1585 old_argv = copy_argv(argc, argv);
1586 if (!old_argv) {
1587 ha_alert("failed to copy argv.\n");
1588 exit(EXIT_FAILURE);
1589 }
1590
1591 /* skip program name and start */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592 argc--; argv++;
1593 while (argc > 0) {
1594 char *flag;
1595
1596 if (**argv == '-') {
1597 flag = *argv+1;
1598
1599 /* 1 arg */
1600 if (*flag == 'v') {
1601 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001602 if (flag[1] == 'v') /* -vv */
1603 display_build_opts();
Tim Duesterhus77b3db02022-04-27 00:08:11 +02001604 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001606#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001608 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001610#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001611 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001612 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001614#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001615 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001616 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001617#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001618#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001619 else if (*flag == 'd' && flag[1] == 'v')
1620 global.tune.options &= ~GTUNE_USE_EVPORTS;
1621#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001622#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001623 else if (*flag == 'd' && flag[1] == 'S')
1624 global.tune.options &= ~GTUNE_USE_SPLICE;
1625#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001626#if defined(USE_GETADDRINFO)
1627 else if (*flag == 'd' && flag[1] == 'G')
1628 global.tune.options &= ~GTUNE_USE_GAI;
1629#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001630#if defined(SO_REUSEPORT)
1631 else if (*flag == 'd' && flag[1] == 'R')
1632 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1633#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001634 else if (*flag == 'd' && flag[1] == 'V')
1635 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001636 else if (*flag == 'V')
1637 arg_mode |= MODE_VERBOSE;
Erwan Le Goasb0c05012022-09-14 17:51:55 +02001638 else if (*flag == 'd' && flag[1] == 'C') {
Erwan Le Goasf30c5d72022-09-29 10:34:04 +02001639 char *end;
1640 char *key;
1641
1642 key = flag + 2;
1643 for (;key && *key; key = end) {
1644 end = strchr(key, ',');
1645 if (end)
1646 *(end++) = 0;
1647
1648 if (strcmp(key, "line") == 0)
1649 arg_mode |= MODE_DUMP_NB_L;
1650
1651 }
Erwan Le Goasb0c05012022-09-14 17:51:55 +02001652 arg_mode |= MODE_DUMP_CFG;
1653 HA_ATOMIC_STORE(&global.anon_key, atoll(flag + 2));
1654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001655 else if (*flag == 'd' && flag[1] == 'b')
1656 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001657 else if (*flag == 'd' && flag[1] == 'D')
1658 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001659 else if (*flag == 'd' && flag[1] == 'W')
1660 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreauef301b72022-02-23 14:15:18 +01001661 else if (*flag == 'd' && flag[1] == 'M') {
Willy Tarreau1408b1f2022-02-18 18:54:40 +01001662 int ret = pool_parse_debugging(flag + 2, &err_msg);
1663
1664 if (ret <= -1) {
1665 if (ret < -1)
1666 ha_alert("-dM: %s\n", err_msg);
1667 else
1668 printf("%s\n", err_msg);
1669 ha_free(&err_msg);
1670 exit(ret < -1 ? EXIT_FAILURE : 0);
1671 } else if (ret == 0) {
1672 ha_warning("-dM: %s\n", err_msg);
1673 ha_free(&err_msg);
1674 }
Willy Tarreauef301b72022-02-23 14:15:18 +01001675 }
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001676 else if (*flag == 'd' && flag[1] == 'r')
1677 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreau654726d2021-12-28 15:43:11 +01001678#if defined(HA_HAVE_DUMP_LIBS)
1679 else if (*flag == 'd' && flag[1] == 'L')
1680 arg_mode |= MODE_DUMP_LIBS;
1681#endif
Willy Tarreau76871a42022-03-08 16:01:40 +01001682 else if (*flag == 'd' && flag[1] == 'K') {
1683 arg_mode |= MODE_DUMP_KWD;
1684 kwd_dump = flag + 2;
1685 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 else if (*flag == 'd')
1687 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001688 else if (*flag == 'c' && flag[1] == 'c') {
1689 arg_mode |= MODE_CHECK_CONDITION;
1690 argv++;
1691 argc--;
1692 check_condition = *argv;
1693 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001694 else if (*flag == 'c')
1695 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001696 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001697 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001698 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001699 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001700#if defined(USE_SYSTEMD)
1701 global.tune.options |= GTUNE_USE_SYSTEMD;
1702#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001703 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 +01001704 usage(progname);
1705#endif
1706 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001707 else if (*flag == 'W')
1708 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001709 else if (*flag == 'q')
1710 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001711 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001712 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001713 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001714 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001715 }
William Lallemand4fc09692017-06-19 16:37:19 +02001716 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001717 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001718 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001719
Olivier Houchardf73629d2017-04-05 22:33:04 +02001720 argv++;
1721 argc--;
1722 }
William Lallemande7361152018-10-26 14:47:36 +02001723 else if (*flag == 'S') {
1724 struct wordlist *c;
1725
William Lallemanda6b32492020-06-04 23:49:20 +02001726 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001727 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1728 usage(progname);
1729 }
1730 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1731 ha_alert("Cannot allocate memory\n");
1732 exit(EXIT_FAILURE);
1733 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001734 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001735
1736 argv++;
1737 argc--;
1738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1740 /* list of pids to finish ('f') or terminate ('t') */
1741
1742 if (flag[1] == 'f')
1743 oldpids_sig = SIGUSR1; /* finish then exit */
1744 else
1745 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001746 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001747 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001748 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1749 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001750 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001751 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001753 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001754 errno = 0;
1755 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1756 if (errno) {
1757 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1758 flag,
1759 *argv, strerror(errno));
1760 exit(1);
1761 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001762 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001763 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001764 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1765 flag, endptr);
1766 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001767 }
Chris Lane236062f2018-02-05 23:15:44 +00001768 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001769 if (oldpids[nb_oldpids] <= 0)
1770 usage(progname);
1771 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001772 }
1773 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001774 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1775 /* now that's a cfgfile list */
1776 argv++; argc--;
1777 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001778 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001779 ha_alert("Cannot load configuration file/directory %s : %s\n",
1780 *argv,
1781 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001782 exit(1);
1783 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001784 argv++; argc--;
1785 }
1786 break;
1787 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001788 else { /* >=2 args */
1789 argv++; argc--;
1790 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001791 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792
1793 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001794 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001795 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001796 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001797 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001798 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001799 free(localpeer);
1800 if ((localpeer = strdup(*argv)) == NULL) {
1801 ha_alert("Cannot allocate memory for local peer.\n");
1802 exit(EXIT_FAILURE);
1803 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001804 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001805 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001806 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001807 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001808 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001809 ha_alert("Cannot load configuration file/directory %s : %s\n",
1810 *argv,
1811 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001812 exit(1);
1813 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001814 break;
Willy Tarreau392524d2022-02-17 18:10:36 +01001815 case 'p' :
1816 free(global.pidfile);
1817 if ((global.pidfile = strdup(*argv)) == NULL) {
1818 ha_alert("Cannot allocate memory for pidfile.\n");
1819 exit(EXIT_FAILURE);
1820 }
1821 break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001822 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001823 }
1824 }
1825 }
1826 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001827 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001828 argv++; argc--;
1829 }
Willy Tarreau392524d2022-02-17 18:10:36 +01001830 free(err_msg);
1831}
1832
Willy Tarreau76871a42022-03-08 16:01:40 +01001833/* call the various keyword dump functions based on the comma-delimited list of
1834 * classes in kwd_dump.
1835 */
1836static void dump_registered_keywords(void)
1837{
1838 char *end;
1839 int all __maybe_unused = 0;
1840
1841 for (; kwd_dump && *kwd_dump; kwd_dump = end) {
1842 end = strchr(kwd_dump, ',');
1843 if (end)
1844 *(end++) = 0;
1845
1846 if (strcmp(kwd_dump, "help") == 0) {
1847 printf("# List of supported keyword classes:\n");
1848 printf("all: list all keywords\n");
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001849 printf("acl: ACL keywords\n");
Willy Tarreauca1acd62022-03-29 15:02:44 +02001850 printf("cfg: configuration keywords\n");
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001851 printf("cli: CLI keywords\n");
Willy Tarreau29d799d2022-03-29 16:59:49 +02001852 printf("cnv: sample converter keywords\n");
Willy Tarreau3b65e142022-03-29 15:03:09 +02001853 printf("flt: filter names\n");
Willy Tarreauf78813f2022-03-29 16:51:29 +02001854 printf("smp: sample fetch functions\n");
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001855 printf("svc: service names\n");
Willy Tarreau76871a42022-03-08 16:01:40 +01001856 continue;
1857 }
1858 else if (strcmp(kwd_dump, "all") == 0) {
1859 all = 1;
1860 }
Willy Tarreauca1acd62022-03-29 15:02:44 +02001861
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001862 if (all || strcmp(kwd_dump, "acl") == 0) {
1863 printf("# List of registered ACL keywords:\n");
1864 acl_dump_kwd();
1865 }
1866
Willy Tarreauca1acd62022-03-29 15:02:44 +02001867 if (all || strcmp(kwd_dump, "cfg") == 0) {
1868 printf("# List of registered configuration keywords:\n");
1869 cfg_dump_registered_keywords();
1870 }
Willy Tarreau3b65e142022-03-29 15:03:09 +02001871
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001872 if (all || strcmp(kwd_dump, "cli") == 0) {
1873 printf("# List of registered CLI keywords:\n");
1874 cli_list_keywords();
1875 }
1876
Willy Tarreau29d799d2022-03-29 16:59:49 +02001877 if (all || strcmp(kwd_dump, "cnv") == 0) {
1878 printf("# List of registered sample converter functions:\n");
1879 smp_dump_conv_kw();
1880 }
1881
Willy Tarreau3b65e142022-03-29 15:03:09 +02001882 if (all || strcmp(kwd_dump, "flt") == 0) {
1883 printf("# List of registered filter names:\n");
1884 flt_dump_kws(NULL);
1885 }
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001886
Willy Tarreauf78813f2022-03-29 16:51:29 +02001887 if (all || strcmp(kwd_dump, "smp") == 0) {
1888 printf("# List of registered sample fetch functions:\n");
1889 smp_dump_fetch_kw();
1890 }
1891
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001892 if (all || strcmp(kwd_dump, "svc") == 0) {
1893 printf("# List of registered service names:\n");
1894 list_services(NULL);
1895 }
Willy Tarreau76871a42022-03-08 16:01:40 +01001896 }
1897}
1898
Willy Tarreau392524d2022-02-17 18:10:36 +01001899/*
1900 * This function initializes all the necessary variables. It only returns
1901 * if everything is OK. If something fails, it exits.
1902 */
1903static void init(int argc, char **argv)
1904{
1905 char *progname = global.log_tag.area;
1906 int err_code = 0;
1907 struct wordlist *wl;
1908 struct proxy *px;
1909 struct post_check_fct *pcf;
William Lallemandb53eb872022-04-21 18:02:53 +02001910 struct pre_check_fct *prcf;
Willy Tarreau392524d2022-02-17 18:10:36 +01001911 int ideal_maxconn;
1912
1913 if (!init_trash_buffers(1)) {
1914 ha_alert("failed to initialize trash buffers.\n");
1915 exit(1);
1916 }
1917
1918 if (init_acl() != 0)
1919 exit(1);
1920
1921 /* Initialise lua. */
1922 hlua_init();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923
Christopher Faulete3a5e352017-10-24 13:53:54 +02001924 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001925 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Erwan Le Goasf30c5d72022-09-29 10:34:04 +02001926 | MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS | MODE_DUMP_KWD
1927 | MODE_DUMP_CFG | MODE_DUMP_NB_L));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001928
William Lallemand944e6192018-11-21 15:48:31 +01001929 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001930 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001931 global.mode |= MODE_MWORKER_WAIT;
1932 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001933 }
1934
Willy Tarreau26146192021-07-21 10:01:36 +02001935 if ((global.mode & (MODE_MWORKER | MODE_CHECK | MODE_CHECK_CONDITION)) == MODE_MWORKER &&
1936 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001937 atexit_flag = 1;
1938 atexit(reexec_on_failure);
1939 }
1940
Willy Tarreau576132e2011-09-10 19:26:56 +02001941 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001942 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001943 exit(1);
1944 }
1945
Amaury Denoyelle11124302021-06-04 18:22:08 +02001946 usermsgs_clr("config");
1947
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001948 if (global.mode & MODE_CHECK_CONDITION) {
1949 int result;
1950
1951 uint32_t err;
1952 const char *errptr;
1953 char *errmsg = NULL;
1954
1955 char *args[MAX_LINE_ARGS+1];
1956 int arg = sizeof(args) / sizeof(*args);
William Lallemand89e236f2022-05-06 17:22:36 +02001957 size_t outlen;
Willy Tarreauc8194c32021-07-16 16:38:58 +02001958 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001959
William Lallemand89e236f2022-05-06 17:22:36 +02001960 if (!check_condition)
1961 usage(progname);
1962
1963 outlen = strlen(check_condition) + 1;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001964 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02001965 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001966 &errptr);
1967
1968 if (err & PARSE_ERR_QUOTE) {
1969 ha_alert("Syntax Error in condition: Unmatched quote.\n");
1970 exit(2);
1971 }
1972
1973 if (err & PARSE_ERR_HEX) {
1974 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
1975 exit(2);
1976 }
1977
1978 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
1979 ha_alert("Error in condition: Line too long.\n");
1980 exit(2);
1981 }
1982
Willy Tarreauc8194c32021-07-16 16:38:58 +02001983 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001984 ha_alert("Error in condition: Too many words.\n");
1985 exit(2);
1986 }
1987
1988 if (err) {
1989 ha_alert("Unhandled error in condition, please report this to the developers.\n");
1990 exit(2);
1991 }
1992
Willy Tarreauc8194c32021-07-16 16:38:58 +02001993 /* remerge all words into a single expression */
1994 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
1995 ;
1996
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001997 result = cfg_eval_condition(args, &errmsg, &errptr);
1998
1999 if (result < 0) {
2000 if (errmsg)
2001 ha_alert("Failed to evaluate condition: %s\n", errmsg);
2002
2003 exit(2);
2004 }
2005
2006 exit(result ? 0 : 1);
2007 }
2008
William Lallemand944e6192018-11-21 15:48:31 +01002009 /* in wait mode, we don't try to read the configuration files */
2010 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01002011 char *env_cfgfiles = NULL;
2012 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01002013
William Lallemand944e6192018-11-21 15:48:31 +01002014 /* handle cfgfiles that are actually directories */
2015 cfgfiles_expand_directories();
2016
2017 if (LIST_ISEMPTY(&cfg_cfgfiles))
2018 usage(progname);
2019
2020
2021 list_for_each_entry(wl, &cfg_cfgfiles, list) {
2022 int ret;
2023
Christopher Faulet4e366822021-01-12 18:57:38 +01002024 if (env_err == 0) {
2025 if (!memprintf(&env_cfgfiles, "%s%s%s",
2026 (env_cfgfiles ? env_cfgfiles : ""),
2027 (env_cfgfiles ? ";" : ""), wl->s))
2028 env_err = 1;
2029 }
William Lallemand7b302d82019-05-20 11:15:37 +02002030
William Lallemand944e6192018-11-21 15:48:31 +01002031 ret = readcfgfile(wl->s);
2032 if (ret == -1) {
2033 ha_alert("Could not open configuration file %s : %s\n",
2034 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01002035 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002036 exit(1);
2037 }
2038 if (ret & (ERR_ABORT|ERR_FATAL))
2039 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
2040 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01002041 if (err_code & ERR_ABORT) {
2042 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002043 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01002044 }
Willy Tarreauc4382422009-12-06 13:10:44 +01002045 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02002046
William Lallemand944e6192018-11-21 15:48:31 +01002047 /* do not try to resolve arguments nor to spot inconsistencies when
2048 * the configuration contains fatal errors caused by files not found
2049 * or failed memory allocations.
2050 */
2051 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2052 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01002053 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002054 exit(1);
2055 }
Christopher Faulet4e366822021-01-12 18:57:38 +01002056 if (env_err) {
2057 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
2058 exit(1);
2059 }
2060 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
2061 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02002062
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02002063 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002064 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01002065 struct mworker_proc *tmproc;
2066
William Lallemand482f9a92019-04-12 16:15:00 +02002067 setenv("HAPROXY_MWORKER", "1", 1);
2068
William Lallemand16dd1b32018-11-19 18:46:18 +01002069 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
2070
William Lallemand56be0e02022-01-28 21:11:41 +01002071 tmproc = mworker_proc_new();
William Lallemand16dd1b32018-11-19 18:46:18 +01002072 if (!tmproc) {
2073 ha_alert("Cannot allocate process structures.\n");
2074 exit(EXIT_FAILURE);
2075 }
William Lallemand8f7069a2019-04-12 16:09:23 +02002076 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01002077 tmproc->pid = pid;
2078 tmproc->timestamp = start_date.tv_sec;
William Lallemandec059c22022-09-22 17:26:23 +02002079
2080 /* Creates the mcli_reload listener, which is the listener used
2081 * to retrieve the master CLI session which asked for the reload.
2082 *
2083 * ipc_fd[1] will be used as a listener, and ipc_fd[0]
2084 * will be used to send the FD of the session.
2085 *
2086 * Both FDs will be kept in the master.
2087 */
2088 if (socketpair(AF_UNIX, SOCK_STREAM, 0, tmproc->ipc_fd) < 0) {
2089 ha_alert("cannot create the mcli_reload socketpair.\n");
2090 exit(EXIT_FAILURE);
2091 }
William Lallemand16dd1b32018-11-19 18:46:18 +01002092 proc_self = tmproc;
2093
Willy Tarreau2b718102021-04-21 07:32:39 +02002094 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01002095 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002096
William Lallemand56be0e02022-01-28 21:11:41 +01002097 tmproc = mworker_proc_new();
Willy Tarreau6185a032021-06-15 08:02:06 +02002098 if (!tmproc) {
2099 ha_alert("Cannot allocate process structures.\n");
2100 exit(EXIT_FAILURE);
2101 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002102 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
William Lallemandce83b4a2018-10-26 14:47:30 +02002103
Willy Tarreau6185a032021-06-15 08:02:06 +02002104 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
2105 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02002106 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002107
2108 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01002109 }
Willy Tarreau53bfac82022-07-22 17:35:49 +02002110
2111 if (global.mode & MODE_MWORKER_WAIT) {
2112 /* in exec mode, there's always exactly one thread. Failure to
2113 * set these ones now will result in nbthread being detected
2114 * automatically.
2115 */
2116 global.nbtgroups = 1;
2117 global.nbthread = 1;
2118 }
2119
William Lallemand944e6192018-11-21 15:48:31 +01002120 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
2121 struct wordlist *it, *c;
2122
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02002123 /* get the info of the children in the env */
2124 if (mworker_env_to_proc_list() < 0) {
2125 exit(EXIT_FAILURE);
2126 }
William Lallemande7361152018-10-26 14:47:36 +02002127
William Lallemand550db6d2018-11-06 17:37:12 +01002128 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemandec059c22022-09-22 17:26:23 +02002129 char *path = NULL;
William Lallemande7361152018-10-26 14:47:36 +02002130
William Lallemand550db6d2018-11-06 17:37:12 +01002131 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02002132 ha_alert("Can't create the master's CLI.\n");
2133 exit(EXIT_FAILURE);
2134 }
William Lallemande7361152018-10-26 14:47:36 +02002135
William Lallemand550db6d2018-11-06 17:37:12 +01002136 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
2137
William Lallemand21623b52022-09-24 15:51:27 +02002138 if (mworker_cli_proxy_new_listener(c->s) == NULL) {
William Lallemand550db6d2018-11-06 17:37:12 +01002139 ha_alert("Can't create the master's CLI.\n");
2140 exit(EXIT_FAILURE);
2141 }
Willy Tarreau2b718102021-04-21 07:32:39 +02002142 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01002143 free(c->s);
2144 free(c);
2145 }
William Lallemandec059c22022-09-22 17:26:23 +02002146 /* Create the mcli_reload listener from the proc_self struct */
2147 memprintf(&path, "sockpair@%d", proc_self->ipc_fd[1]);
William Lallemand56f73b22022-09-24 15:56:25 +02002148 mcli_reload_bind_conf = mworker_cli_proxy_new_listener(path);
2149 if (mcli_reload_bind_conf == NULL) {
William Lallemandec059c22022-09-22 17:26:23 +02002150 ha_alert("Cannot create the mcli_reload listener.\n");
2151 exit(EXIT_FAILURE);
2152 }
2153 ha_free(&path);
William Lallemand550db6d2018-11-06 17:37:12 +01002154 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002155 }
2156
Eric Salama5ba83352021-03-16 15:11:17 +01002157 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
2158 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
2159 }
2160
Christopher Faulet27c8d202021-10-13 09:50:53 +02002161 /* destroy unreferenced defaults proxies */
2162 proxy_destroy_all_unref_defaults();
2163
William Lallemandb53eb872022-04-21 18:02:53 +02002164 list_for_each_entry(prcf, &pre_check_list, list)
2165 err_code |= prcf->fct();
Willy Tarreaue90904d2021-02-12 14:08:31 +01002166
William Lallemand8b9a2df2022-05-04 14:29:46 +02002167 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2168 ha_alert("Fatal errors found in configuration.\n");
2169 exit(1);
2170 }
2171
Willy Tarreaubb925012009-07-23 13:36:36 +02002172 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02002173 for (px = proxies_list; px; px = px->next) {
2174 struct server *srv;
2175 struct post_proxy_check_fct *ppcf;
2176 struct post_server_check_fct *pscf;
2177
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002178 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002179 continue;
2180
Christopher Fauletc1692962019-08-12 09:51:07 +02002181 list_for_each_entry(pscf, &post_server_check_list, list) {
2182 for (srv = px->srv; srv; srv = srv->next)
2183 err_code |= pscf->fct(srv);
2184 }
2185 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2186 err_code |= ppcf->fct(px);
2187 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002188 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002189 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002190 exit(1);
2191 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002193 err_code |= pattern_finalize_config();
2194 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2195 ha_alert("Failed to finalize pattern config.\n");
2196 exit(1);
2197 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002198
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002199 if (global.rlimit_memmax_all)
2200 global.rlimit_memmax = global.rlimit_memmax_all;
2201
Willy Tarreaue5733232019-05-22 19:24:06 +02002202#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002203 err_code |= netns_init();
2204 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002205 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002206 exit(1);
2207 }
2208#endif
2209
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002210 /* Apply server states */
2211 apply_server_state();
2212
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002213 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002214 srv_compute_all_admin_states(px);
2215
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002216 /* Apply servers' configured address */
2217 err_code |= srv_init_addr();
2218 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002219 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002220 exit(1);
2221 }
2222
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002223 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2224 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2225 exit(1);
2226 }
2227
Willy Tarreau654726d2021-12-28 15:43:11 +01002228#if defined(HA_HAVE_DUMP_LIBS)
2229 if (global.mode & MODE_DUMP_LIBS) {
2230 qfprintf(stdout, "List of loaded object files:\n");
2231 chunk_reset(&trash);
2232 if (dump_libs(&trash, 0))
2233 printf("%s", trash.area);
2234 }
2235#endif
2236
Willy Tarreau76871a42022-03-08 16:01:40 +01002237 if (global.mode & MODE_DUMP_KWD)
2238 dump_registered_keywords();
2239
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002241 struct peers *pr;
2242 struct proxy *px;
2243
Willy Tarreaubebd2122020-04-15 16:06:11 +02002244 if (warned & WARN_ANY)
2245 qfprintf(stdout, "Warnings were found.\n");
2246
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002247 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002248 if (pr->peers_fe)
2249 break;
2250
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002251 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002252 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002253 break;
2254
Emeric Brunbc5c8212021-08-13 09:32:50 +02002255 if (!px) {
2256 /* We may only have log-forward section */
2257 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002258 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002259 break;
2260 }
2261
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002262 if (pr || px) {
2263 /* At least one peer or one listener has been found */
2264 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002265 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002266 }
2267 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2268 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002269 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002270
Erwan Le Goasb0c05012022-09-14 17:51:55 +02002271 if (global.mode & MODE_DUMP_CFG)
2272 deinit_and_exit(0);
2273
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002274 if (global.mode & MODE_DIAG) {
2275 cfg_run_diagnostics();
2276 }
2277
Remi Tricot-Le Breton51944462022-05-16 16:24:31 +02002278#ifdef USE_OPENSSL
William Lallemand3b8bafd2022-07-19 18:13:29 +02002279 /* Initialize the error strings of OpenSSL */
2280 SSL_load_error_strings();
2281
Remi Tricot-Le Breton51944462022-05-16 16:24:31 +02002282 /* Initialize SSL random generator. Must be called before chroot for
2283 * access to /dev/urandom, and before ha_random_boot() which may use
2284 * RAND_bytes().
2285 */
2286 if (!ssl_initialize_random()) {
2287 ha_alert("OpenSSL random data generator initialization failed.\n");
2288 exit(EXIT_FAILURE);
2289 }
2290#endif
2291 ha_random_boot(argv); // the argv pointer brings some kernel-fed entropy
2292
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002293 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002294 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002295
Willy Tarreaue6945732016-12-21 19:57:00 +01002296 list_for_each_entry(pcf, &post_check_list, list) {
2297 err_code |= pcf->fct();
2298 if (err_code & (ERR_ABORT|ERR_FATAL))
2299 exit(1);
2300 }
2301
William Lallemand0a012aa2022-06-21 11:11:50 +02002302 /* set the default maxconn in the master, but let it be rewritable with -n */
2303 if (global.mode & MODE_MWORKER_WAIT)
2304 global.maxconn = DEFAULT_MAXCONN;
2305
Willy Tarreaubaaee002006-06-26 02:48:02 +02002306 if (cfg_maxconn > 0)
2307 global.maxconn = cfg_maxconn;
2308
Willy Tarreau4975d142021-03-13 11:00:33 +01002309 if (global.cli_fe)
2310 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002311
2312 if (cfg_peers) {
2313 /* peers also need to bypass global maxconn */
2314 struct peers *p = cfg_peers;
2315
2316 for (p = cfg_peers; p; p = p->next)
2317 if (p->peers_fe)
2318 global.maxsock += p->peers_fe->maxconn;
2319 }
2320
Willy Tarreaud0256482015-01-15 21:45:22 +01002321 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002322 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2323 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2324 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2325 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002326 *
2327 * If memmax is set, then it depends on which values are set. If
2328 * maxsslconn is set, we use memmax to determine how many cleartext
2329 * connections may be added, and set maxconn to the sum of the two.
2330 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2331 * the remaining amount of memory between memmax and the cleartext
2332 * connections. If neither are set, then it is considered that all
2333 * connections are SSL-capable, and maxconn is computed based on this,
2334 * then maxsslconn accordingly. We need to know if SSL is used on the
2335 * frontends, backends, or both, because when it's used on both sides,
2336 * we need twice the value for maxsslconn, but we only count the
2337 * handshake once since it is not performed on the two sides at the
2338 * same time (frontend-side is terminated before backend-side begins).
2339 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002340 * ssl_handshake_cost during its initialization. In any case, if
2341 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2342 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002343 */
Willy Tarreauac350932019-03-01 15:43:14 +01002344 ideal_maxconn = compute_ideal_maxconn();
2345
Willy Tarreaud0256482015-01-15 21:45:22 +01002346 if (!global.rlimit_memmax) {
2347 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002348 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002349 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2350 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2351 }
2352 }
2353#ifdef USE_OPENSSL
2354 else if (!global.maxconn && !global.maxsslconn &&
2355 (global.ssl_used_frontend || global.ssl_used_backend)) {
2356 /* memmax is set, compute everything automatically. Here we want
2357 * to ensure that all SSL connections will be served. We take
2358 * care of the number of sides where SSL is used, and consider
2359 * the worst case : SSL used on both sides and doing a handshake
2360 * simultaneously. Note that we can't have more than maxconn
2361 * handshakes at a time by definition, so for the worst case of
2362 * two SSL conns per connection, we count a single handshake.
2363 */
2364 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2365 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002366 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002367
Willy Tarreau2cb3be72022-05-24 07:43:57 +02002368 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002369 mem -= global.maxzlibmem;
2370 mem = mem * MEM_USABLE_RATIO;
2371
Willy Tarreau304e17e2020-03-10 17:54:54 +01002372 /* Principle: we test once to set maxconn according to the free
2373 * memory. If it results in values the system rejects, we try a
2374 * second time by respecting rlim_fd_max. If it fails again, we
2375 * go back to the initial value and will let the final code
2376 * dealing with rlimit report the error. That's up to 3 attempts.
2377 */
2378 do {
2379 global.maxconn = mem /
2380 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2381 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2382 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002383
Willy Tarreau304e17e2020-03-10 17:54:54 +01002384 if (retried == 1)
2385 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2386 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002387#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002388 if (global.maxconn > SYSTEM_MAXCONN)
2389 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002390#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002391 global.maxsslconn = sides * global.maxconn;
2392
2393 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2394 break;
2395 } while (retried++ < 2);
2396
Willy Tarreaud0256482015-01-15 21:45:22 +01002397 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2398 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2399 global.maxconn, global.maxsslconn);
2400 }
2401 else if (!global.maxsslconn &&
2402 (global.ssl_used_frontend || global.ssl_used_backend)) {
2403 /* memmax and maxconn are known, compute maxsslconn automatically.
2404 * maxsslconn being forced, we don't know how many of it will be
2405 * on each side if both sides are being used. The worst case is
2406 * when all connections use only one SSL instance because
2407 * handshakes may be on two sides at the same time.
2408 */
2409 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2410 int64_t mem = global.rlimit_memmax * 1048576ULL;
2411 int64_t sslmem;
2412
Willy Tarreau8e5b9582022-05-26 08:55:05 +02002413 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002414 mem -= global.maxzlibmem;
2415 mem = mem * MEM_USABLE_RATIO;
2416
Willy Tarreau87b09662015-04-03 00:22:06 +02002417 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002418 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2419 global.maxsslconn = round_2dig(global.maxsslconn);
2420
2421 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002422 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2423 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2424 "without SSL is %d, but %d was found and SSL is in use.\n",
2425 global.rlimit_memmax,
2426 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2427 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002428 exit(1);
2429 }
2430
2431 if (global.maxsslconn > sides * global.maxconn)
2432 global.maxsslconn = sides * global.maxconn;
2433
2434 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2435 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2436 }
2437#endif
2438 else if (!global.maxconn) {
2439 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2440 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2441 int64_t mem = global.rlimit_memmax * 1048576ULL;
2442 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002443 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002444
2445 if (global.ssl_used_frontend || global.ssl_used_backend)
Willy Tarreau8e5b9582022-05-26 08:55:05 +02002446 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002447
2448 mem -= global.maxzlibmem;
2449 mem = mem * MEM_USABLE_RATIO;
2450
2451 clearmem = mem;
2452 if (sides)
2453 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2454
Willy Tarreau304e17e2020-03-10 17:54:54 +01002455 /* Principle: we test once to set maxconn according to the free
2456 * memory. If it results in values the system rejects, we try a
2457 * second time by respecting rlim_fd_max. If it fails again, we
2458 * go back to the initial value and will let the final code
2459 * dealing with rlimit report the error. That's up to 3 attempts.
2460 */
2461 do {
2462 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2463 if (retried == 1)
2464 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2465 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002466#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002467 if (global.maxconn > SYSTEM_MAXCONN)
2468 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002469#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002470
Willy Tarreau304e17e2020-03-10 17:54:54 +01002471 if (clearmem <= 0 || !global.maxconn) {
2472 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2473 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2474 "is %d, but %d was found.\n",
2475 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002476 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002477 global.maxsslconn);
2478 exit(1);
2479 }
2480
2481 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2482 break;
2483 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002484
2485 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2486 if (sides && global.maxsslconn > sides * global.maxconn) {
2487 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2488 "to be limited to %d. Better reduce global.maxsslconn to get more "
2489 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2490 }
2491 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2492 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002493 }
2494
Willy Tarreaua409f302020-03-10 17:08:53 +01002495 global.maxsock = compute_ideal_maxsock(global.maxconn);
2496 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002497 if (!global.maxpipes)
2498 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499
Olivier Houchard88698d92019-04-16 19:07:22 +02002500 /* update connection pool thresholds */
2501 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2502 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2503
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002504 proxy_adjust_all_maxconn();
2505
Willy Tarreau1db37712007-06-03 17:16:49 +02002506 if (global.tune.maxpollevents <= 0)
2507 global.tune.maxpollevents = MAX_POLL_EVENTS;
2508
Willy Tarreau060a7612021-03-10 11:06:26 +01002509 if (global.tune.runqueue_depth <= 0) {
2510 /* tests on various thread counts from 1 to 64 have shown an
2511 * optimal queue depth following roughly 1/sqrt(threads).
2512 */
2513 int s = my_flsl(global.nbthread);
2514 s += (global.nbthread / s); // roughly twice the sqrt.
2515 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2516 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002517
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002518 if (global.tune.recv_enough == 0)
2519 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2520
Willy Tarreau27a674e2009-08-17 07:23:33 +02002521 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2522 global.tune.maxrewrite = global.tune.bufsize / 2;
2523
Amaury Denoyelle11124302021-06-04 18:22:08 +02002524 usermsgs_clr(NULL);
2525
Willy Tarreaubaaee002006-06-26 02:48:02 +02002526 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2527 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002528 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002529 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2530 }
2531
William Lallemand095ba4c2017-06-01 17:38:50 +02002532 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002533 /* command line daemon mode inhibits foreground and debug modes mode */
2534 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002535 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002536 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002537
2538 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002539
William Lallemand095ba4c2017-06-01 17:38:50 +02002540 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002541 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002542 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 }
2544
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002545 if (global.nbthread < 1)
2546 global.nbthread = 1;
2547
Christopher Faulet3ef26392017-08-29 16:46:57 +02002548 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002549 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002550 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002551 exit(1);
2552 }
2553
Christopher Faulet96d44832017-11-14 22:02:30 +01002554 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002555 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002556 exit(1);
2557 }
2558
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002559 /*
2560 * Note: we could register external pollers here.
2561 * Built-in pollers have been registered before main().
2562 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002563
Willy Tarreau43b78992009-01-25 15:42:27 +01002564 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002565 disable_poller("kqueue");
2566
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002567 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2568 disable_poller("evports");
2569
Willy Tarreau43b78992009-01-25 15:42:27 +01002570 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002571 disable_poller("epoll");
2572
Willy Tarreau43b78992009-01-25 15:42:27 +01002573 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002574 disable_poller("poll");
2575
Willy Tarreau43b78992009-01-25 15:42:27 +01002576 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002577 disable_poller("select");
2578
2579 /* Note: we could disable any poller by name here */
2580
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002581 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002582 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002583 fprintf(stderr, "\n");
2584 list_filters(stderr);
2585 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002586
Willy Tarreau4f60f162007-04-08 16:39:58 +02002587 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002588 ha_alert("No polling mechanism available.\n"
Willy Tarreaue5715bf2022-07-09 23:38:46 +02002589 " This may happen when using thread-groups with old pollers (poll/select), or\n"
2590 " it is possible that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
Christopher Faulet767a84b2017-11-24 16:50:31 +01002591 " is too low on this platform to support maxconn and the number of listeners\n"
2592 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2593 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2594 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2595 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2596 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2597 " check build settings using 'haproxy -vv'.\n\n",
2598 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002599 exit(1);
2600 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002601 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2602 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002603 }
2604
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002605 if (!global.node)
2606 global.node = strdup(hostname);
2607
Willy Tarreau02b092f2020-10-07 18:36:54 +02002608 /* stop disabled proxies */
2609 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002610 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002611 stop_proxy(px);
2612 }
2613
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002614 if (!hlua_post_init())
2615 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002616}
2617
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002618void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002619{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002620 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002621 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002622 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002623 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002624 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002625 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002626 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002627 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002628 struct per_thread_init_fct *tif, *tifb;
2629 struct per_thread_deinit_fct *tdf, *tdfb;
2630 struct per_thread_alloc_fct *taf, *tafb;
2631 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002632 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002633 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002634 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreau65009eb2022-04-27 18:02:54 +02002635 struct pre_check_fct *prcf, *prcfb;
Willy Tarreau226866e2022-04-27 18:07:24 +02002636 struct cfg_postparser *pprs, *pprsb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002637 int cur_fd;
2638
2639 /* At this point the listeners state is weird:
2640 * - most listeners are still bound and referenced in their protocol
2641 * - some might be zombies that are not in their proto anymore, but
2642 * still appear in their proxy's listeners with a valid FD.
2643 * - some might be stopped and still appear in their proxy as FD #-1
2644 * - among all of them, some might be inherited hence shared and we're
2645 * not allowed to pause them or whatever, we must just close them.
2646 * - finally some are not listeners (pipes, logs, stdout, etc) and
2647 * must be left intact.
2648 *
2649 * The safe way to proceed is to unbind (and close) whatever is not yet
2650 * unbound so that no more receiver/listener remains alive. Then close
2651 * remaining listener FDs, which correspond to zombie listeners (those
2652 * belonging to disabled proxies that were in another process).
2653 * objt_listener() would be cleaner here but not converted yet.
2654 */
2655 protocol_unbind_all();
2656
2657 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002658 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002659 continue;
2660
Willy Tarreaua74cb382020-10-15 21:29:49 +02002661 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002662 struct listener *l = fdtab[cur_fd].owner;
2663
2664 BUG_ON(l->state != LI_INIT);
2665 unbind_listener(l);
2666 }
2667 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002668
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002669 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002670 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002671 /* build a list of unique uri_auths */
2672 if (!ua)
2673 ua = p->uri_auth;
2674 else {
2675 /* check if p->uri_auth is unique */
2676 for (uap = ua; uap; uap=uap->next)
2677 if (uap == p->uri_auth)
2678 break;
2679
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002680 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002681 /* add it, if it is */
2682 p->uri_auth->next = ua;
2683 ua = p->uri_auth;
2684 }
William Lallemand0f99e342011-10-12 17:50:54 +02002685 }
2686
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002687 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002688 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002689 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002690 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002691
Christopher Faulet27c8d202021-10-13 09:50:53 +02002692 /* destroy all referenced defaults proxies */
2693 proxy_destroy_all_unref_defaults();
2694
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002695 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002696 struct stat_scope *scope, *scopep;
2697
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002698 uap = ua;
2699 ua = ua->next;
2700
Willy Tarreaua534fea2008-08-03 12:19:50 +02002701 free(uap->uri_prefix);
2702 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002703 free(uap->node);
2704 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002705
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002706 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002707 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002708
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002709 scope = uap->scope;
2710 while (scope) {
2711 scopep = scope;
2712 scope = scope->next;
2713
2714 free(scopep->px_id);
2715 free(scopep);
2716 }
2717
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002718 free(uap);
2719 }
2720
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002721 userlist_free(userlist);
2722
David Carlier834cb2e2015-09-25 12:02:25 +01002723 cfg_unregister_sections();
2724
Christopher Faulet0132d062017-07-26 15:33:35 +02002725 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002726
Willy Tarreau05554e62016-12-21 20:46:26 +01002727 list_for_each_entry(pdf, &post_deinit_list, list)
2728 pdf->fct();
2729
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002730 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002731 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002732 ha_free(&global.chroot);
Frédéric Lécaille372508c2022-05-06 08:53:16 +02002733 ha_free(&global.cluster_secret);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002734 ha_free(&global.pidfile);
2735 ha_free(&global.node);
2736 ha_free(&global.desc);
2737 ha_free(&oldpids);
2738 ha_free(&old_argv);
2739 ha_free(&localpeer);
2740 ha_free(&global.server_state_base);
2741 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002742 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002743 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002744
William Lallemand0f99e342011-10-12 17:50:54 +02002745 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002746 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002747 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002748 free(log);
2749 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002750 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002751 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002752 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002753 free(wl);
2754 }
2755
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002756 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2757 if (bol->must_free)
2758 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002759 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002760 free(bol);
2761 }
2762
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002763 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002764 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002765 free(pxdf);
2766 }
2767
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002768 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002769 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002770 free(pdf);
2771 }
2772
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002773 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002774 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002775 free(srvdf);
2776 }
2777
Tim Duesterhusfc854942020-09-10 19:46:42 +02002778 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002779 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002780 free(pcf);
2781 }
2782
Tim Duesterhus34bef072020-07-04 11:49:50 +02002783 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002784 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002785 free(pscf);
2786 }
2787
Tim Duesterhus53508d62020-09-10 19:46:40 +02002788 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002789 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002790 free(ppcf);
2791 }
2792
Willy Tarreau65009eb2022-04-27 18:02:54 +02002793 list_for_each_entry_safe(prcf, prcfb, &pre_check_list, list) {
2794 LIST_DELETE(&prcf->list);
2795 free(prcf);
2796 }
2797
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002798 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002799 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002800 free(tif);
2801 }
2802
2803 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002804 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002805 free(tdf);
2806 }
2807
2808 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002809 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002810 free(taf);
2811 }
2812
2813 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002814 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002815 free(tff);
2816 }
2817
Willy Tarreau226866e2022-04-27 18:07:24 +02002818 list_for_each_entry_safe(pprs, pprsb, &postparsers, list) {
2819 LIST_DELETE(&pprs->list);
2820 free(pprs);
2821 }
2822
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002823 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002824 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002825 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002826} /* end deinit() */
2827
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002828__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002829{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002830 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002831 deinit();
2832 exit(status);
2833}
William Lallemand72160322018-11-06 17:37:16 +01002834
Willy Tarreau918ff602011-07-25 16:33:49 +02002835/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002836void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002837{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002838 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002839
Willy Tarreau55542642021-10-08 09:33:24 +02002840 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002841 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002842 wake_expired_tasks();
2843
William Lallemand1aab50b2018-06-07 09:46:01 +02002844 /* check if we caught some signals and process them in the
2845 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002846 if (signal_queue_len && tid == 0) {
2847 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002848 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002849 }
2850
2851 /* Process a few tasks */
2852 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002853
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002854 /* also stop if we failed to cleanly stop all tasks */
2855 if (killed > 1)
2856 break;
2857
Matthias Wirtheea152e2022-09-09 10:21:00 +02002858 /* expire immediately if events or signals are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002859 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002860 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002861 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002862 else {
Willy Tarreaue7475c82022-06-20 09:23:24 +02002863 _HA_ATOMIC_OR(&th_ctx->flags, TH_FL_SLEEPING);
Willy Tarreaudce4ad72022-06-22 15:38:38 +02002864 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_NOTIFIED);
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002865 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002866 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002867 activity[tid].wake_tasks++;
Willy Tarreaue7475c82022-06-20 09:23:24 +02002868 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_SLEEPING);
Matthias Wirtheea152e2022-09-09 10:21:00 +02002869 } else if (signal_queue_len) {
2870 /* this check is required after setting TH_FL_SLEEPING to avoid
2871 * a race with wakeup on signals using wake_threads() */
2872 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_SLEEPING);
Olivier Houchard79321b92018-07-26 17:55:11 +02002873 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002874 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002875 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002876
Willy Tarreau4f46a352020-03-23 09:27:28 +01002877 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002878 int i;
2879
2880 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002881 /* stop muxes before acknowledging stopping */
Willy Tarreau24cfc9f2022-07-04 14:07:29 +02002882 if (!(tg_ctx->stopping_threads & ti->ltid_bit)) {
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002883 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2884 wake = 1;
2885 }
2886
Willy Tarreauef422ce2022-06-28 19:29:29 +02002887 if (_HA_ATOMIC_OR_FETCH(&tg_ctx->stopping_threads, ti->ltid_bit) == ti->ltid_bit &&
2888 _HA_ATOMIC_OR_FETCH(&stopping_tgroup_mask, tg->tgid_bit) == tg->tgid_bit) {
2889 /* first one to detect it, notify all threads that stopping was just set */
2890 for (i = 0; i < global.nbthread; i++) {
2891 if (ha_thread_info[i].tg->threads_enabled &
2892 ha_thread_info[i].ltid_bit &
2893 ~_HA_ATOMIC_LOAD(&ha_thread_info[i].tg_ctx->stopping_threads))
Willy Tarreaud6455742020-05-13 14:30:25 +02002894 wake_thread(i);
Willy Tarreauef422ce2022-06-28 19:29:29 +02002895 }
Willy Tarreaud6455742020-05-13 14:30:25 +02002896 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002897 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002898
2899 /* stop when there's nothing left to do */
2900 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreauef422ce2022-06-28 19:29:29 +02002901 (_HA_ATOMIC_LOAD(&stopping_tgroup_mask) & all_tgroups_mask) == all_tgroups_mask) {
2902 /* check that all threads are aware of the stopping status */
2903 for (i = 0; i < global.nbtgroups; i++)
Willy Tarreauf34a3fa2022-07-06 10:13:05 +02002904 if ((_HA_ATOMIC_LOAD(&ha_tgroup_ctx[i].stopping_threads) & ha_tgroup_info[i].threads_enabled) !=
2905 ha_tgroup_info[i].threads_enabled)
Willy Tarreauef422ce2022-06-28 19:29:29 +02002906 break;
2907#ifdef USE_THREAD
2908 if (i == global.nbtgroups) {
2909 /* all are OK, let's wake them all and stop */
2910 for (i = 0; i < global.nbthread; i++)
2911 if (i != tid && ha_thread_info[i].tg->threads_enabled & ha_thread_info[i].ltid_bit)
2912 wake_thread(i);
2913 break;
2914 }
2915#endif
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002916 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002917 }
2918
Willy Tarreauc49ba522019-12-11 08:12:23 +01002919 /* If we have to sleep, measure how long */
2920 next = wake ? TICK_ETERNITY : next_timer_expiry();
2921
Willy Tarreau58b458d2008-06-29 22:40:23 +02002922 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002923 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002924
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002925 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002926 }
2927}
2928
Christopher Faulet1d17c102017-08-29 15:38:48 +02002929static void *run_thread_poll_loop(void *data)
2930{
Willy Tarreau082b6282019-05-22 14:42:12 +02002931 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002932 struct per_thread_init_fct *ptif;
2933 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002934 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002935 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002936 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2937 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002938
Willy Tarreau43ab05b2021-09-28 09:43:11 +02002939 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02002940 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02002941 clock_set_local_source();
Willy Tarreau91e6df02019-05-03 17:21:18 +02002942
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002943 /* Now, initialize one thread init at a time. This is better since
2944 * some init code is a bit tricky and may release global resources
2945 * after reallocating them locally. This will also ensure there is
2946 * no race on file descriptors allocation.
2947 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002948#ifdef USE_THREAD
2949 pthread_mutex_lock(&init_mutex);
2950#endif
2951 /* The first thread must set the number of threads left */
2952 if (!init_left)
2953 init_left = global.nbthread;
2954 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002955
Willy Tarreau55542642021-10-08 09:33:24 +02002956 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002957
Willy Tarreau082b6282019-05-22 14:42:12 +02002958 /* per-thread alloc calls performed here are not allowed to snoop on
2959 * other threads, so they are free to initialize at their own rhythm
2960 * as long as they act as if they were alone. None of them may rely
2961 * on resources initialized by the other ones.
2962 */
2963 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2964 if (!ptaf->fct()) {
2965 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002966#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002967 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002968#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02002969 exit(1);
2970 }
2971 }
2972
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002973 /* per-thread init calls performed here are not allowed to snoop on
2974 * other threads, so they are free to initialize at their own rhythm
2975 * as long as they act as if they were alone.
2976 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002977 list_for_each_entry(ptif, &per_thread_init_list, list) {
2978 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002979 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002980#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002981 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002982#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002983 exit(1);
2984 }
2985 }
2986
Willy Tarreau71092822019-06-10 09:51:04 +02002987 /* enabling protocols will result in fd_insert() calls to be performed,
2988 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002989 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002990 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002991 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002992 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002993
Willy Tarreau34a150c2019-06-11 09:16:41 +02002994#ifdef USE_THREAD
2995 pthread_cond_broadcast(&init_cond);
2996 pthread_mutex_unlock(&init_mutex);
2997
2998 /* now wait for other threads to finish starting */
2999 pthread_mutex_lock(&init_mutex);
3000 while (init_left)
3001 pthread_cond_wait(&init_cond, &init_mutex);
3002 pthread_mutex_unlock(&init_mutex);
3003#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02003004
Willy Tarreaua45a8b52019-12-06 16:31:45 +01003005#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
3006 /* Let's refrain from using setuid executables. This way the impact of
3007 * an eventual vulnerability in a library remains limited. It may
3008 * impact external checks but who cares about them anyway ? In the
3009 * worst case it's possible to disable the option. Obviously we do this
3010 * in workers only. We can't hard-fail on this one as it really is
3011 * implementation dependent though we're interested in feedback, hence
3012 * the warning.
3013 */
3014 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
3015 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02003016 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 +01003017 ha_warning("Failed to disable setuid, please report to developers with detailed "
3018 "information about your operating system. You can silence this warning "
3019 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
3020 }
3021 }
3022#endif
3023
Willy Tarreaud96f1122019-12-03 07:07:36 +01003024#if defined(RLIMIT_NPROC)
3025 /* all threads have started, it's now time to prevent any new thread
3026 * or process from starting. Obviously we do this in workers only. We
3027 * can't hard-fail on this one as it really is implementation dependent
3028 * though we're interested in feedback, hence the warning.
3029 */
3030 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
3031 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
3032 static int warn_fail;
3033
Willy Tarreau18515722021-04-06 11:57:41 +02003034 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01003035 ha_warning("Failed to disable forks, please report to developers with detailed "
3036 "information about your operating system. You can silence this warning "
3037 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
3038 }
3039 }
3040#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003041 run_poll_loop();
3042
3043 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
3044 ptdf->fct();
3045
Willy Tarreau082b6282019-05-22 14:42:12 +02003046 list_for_each_entry(ptff, &per_thread_free_list, list)
3047 ptff->fct();
3048
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003049#ifdef USE_THREAD
Willy Tarreau291f6ff2022-07-04 13:36:16 +02003050 if (!_HA_ATOMIC_AND_FETCH(&ha_tgroup_info[ti->tgid-1].threads_enabled, ~ti->ltid_bit))
Willy Tarreaucce203a2022-06-24 15:55:11 +02003051 _HA_ATOMIC_AND(&all_tgroups_mask, ~tg->tgid_bit);
Willy Tarreauad92fdf2022-07-06 10:17:21 +02003052 if (!_HA_ATOMIC_AND_FETCH(&tg_ctx->stopping_threads, ~ti->ltid_bit))
3053 _HA_ATOMIC_AND(&stopping_tgroup_mask, ~tg->tgid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003054 if (tid > 0)
3055 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02003056#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003057 return NULL;
3058}
Christopher Faulet1d17c102017-08-29 15:38:48 +02003059
William Dauchyf9af9d72019-11-17 15:47:16 +01003060/* set uid/gid depending on global settings */
3061static void set_identity(const char *program_name)
3062{
3063 if (global.gid) {
3064 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
3065 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
3066 " without 'uid'/'user' is generally useless.\n", program_name);
3067
3068 if (setgid(global.gid) == -1) {
3069 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
3070 protocol_unbind_all();
3071 exit(1);
3072 }
3073 }
3074
3075 if (global.uid && setuid(global.uid) == -1) {
3076 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
3077 protocol_unbind_all();
3078 exit(1);
3079 }
3080}
3081
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082int main(int argc, char **argv)
3083{
3084 int err, retry;
3085 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02003086 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02003087 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
3088
Willy Tarreau41afd902022-07-21 09:55:22 +02003089 /* Catch broken toolchains */
3090 if (sizeof(long) != sizeof(void *) || (intovf + 0x7FFFFFFF >= intovf)) {
3091 const char *msg;
3092
3093 if (sizeof(long) != sizeof(void *))
3094 /* Apparently MingW64 was not made for us and can also break openssl */
3095 msg = "The compiler this program was built with uses unsupported integral type sizes.\n"
3096 "Most likely it follows the unsupported LLP64 model. Never try to link HAProxy\n"
3097 "against libraries built with that compiler either! Please only use a compiler\n"
3098 "producing ILP32 or LP64 programs for both programs and libraries.\n";
3099 else if (intovf + 0x7FFFFFFF >= intovf)
3100 /* Catch forced CFLAGS that miss 2-complement integer overflow */
3101 msg = "The source code was miscompiled by the compiler, which usually indicates that\n"
3102 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
3103 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
3104 "and INSTALL files to decide on the best way to pass your local build options.\n";
3105 else
3106 msg = "Bug in the compiler bug detection code, please report it to developers!\n";
3107
Willy Tarreau1335da32021-07-14 17:54:01 +02003108 fprintf(stderr,
3109 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
Willy Tarreau41afd902022-07-21 09:55:22 +02003110 "%s"
3111 "\nBuild options :"
Willy Tarreau1335da32021-07-14 17:54:01 +02003112#ifdef BUILD_TARGET
Willy Tarreau41afd902022-07-21 09:55:22 +02003113 "\n TARGET = " BUILD_TARGET
Willy Tarreau1335da32021-07-14 17:54:01 +02003114#endif
3115#ifdef BUILD_CPU
Willy Tarreau41afd902022-07-21 09:55:22 +02003116 "\n CPU = " BUILD_CPU
Willy Tarreau1335da32021-07-14 17:54:01 +02003117#endif
3118#ifdef BUILD_CC
Willy Tarreau41afd902022-07-21 09:55:22 +02003119 "\n CC = " BUILD_CC
Willy Tarreau1335da32021-07-14 17:54:01 +02003120#endif
3121#ifdef BUILD_CFLAGS
Willy Tarreau41afd902022-07-21 09:55:22 +02003122 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau1335da32021-07-14 17:54:01 +02003123#endif
3124#ifdef BUILD_OPTIONS
Willy Tarreau41afd902022-07-21 09:55:22 +02003125 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau1335da32021-07-14 17:54:01 +02003126#endif
3127#ifdef BUILD_DEBUG
Willy Tarreau41afd902022-07-21 09:55:22 +02003128 "\n DEBUG = " BUILD_DEBUG
Willy Tarreau1335da32021-07-14 17:54:01 +02003129#endif
Willy Tarreau41afd902022-07-21 09:55:22 +02003130 "\n\n", msg);
3131
Willy Tarreau1335da32021-07-14 17:54:01 +02003132 return 1;
3133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134
Olivier Houchard5fa300d2018-02-03 15:15:21 +01003135 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003136
Willy Tarreaubf696402019-03-01 10:09:28 +01003137 /* take a copy of initial limits before we possibly change them */
3138 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02003139
3140 if (limit.rlim_max == RLIM_INFINITY)
3141 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01003142 rlim_fd_cur_at_boot = limit.rlim_cur;
3143 rlim_fd_max_at_boot = limit.rlim_max;
3144
Willy Tarreau5794fb02018-11-25 18:43:29 +01003145 /* process all initcalls in order of potential dependency */
3146 RUN_INITCALLS(STG_PREPARE);
3147 RUN_INITCALLS(STG_LOCK);
Willy Tarreau3ebe4d92022-02-18 14:51:49 +01003148 RUN_INITCALLS(STG_REGISTER);
Willy Tarreau34527d52022-02-17 17:45:58 +01003149
3150 /* now's time to initialize early boot variables */
3151 init_early(argc, argv);
3152
Willy Tarreau18f96d02022-02-23 17:25:00 +01003153 /* handles argument parsing */
3154 init_args(argc, argv);
3155
Willy Tarreau5794fb02018-11-25 18:43:29 +01003156 RUN_INITCALLS(STG_ALLOC);
3157 RUN_INITCALLS(STG_POOL);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003158 RUN_INITCALLS(STG_INIT);
3159
Willy Tarreau34527d52022-02-17 17:45:58 +01003160 /* this is the late init where the config is parsed */
Emeric Bruncf20bf12010-10-22 16:06:11 +02003161 init(argc, argv);
Willy Tarreau34527d52022-02-17 17:45:58 +01003162
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003163 signal_register_fct(SIGQUIT, dump, SIGQUIT);
3164 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
3165 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02003166 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003167
Willy Tarreaue437c442010-03-17 18:02:46 +01003168 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
3169 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
3170 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003171 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003172 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173
Willy Tarreaudc23a922011-02-16 11:10:36 +01003174 /* ulimits */
3175 if (!global.rlimit_nofile)
3176 global.rlimit_nofile = global.maxsock;
3177
3178 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01003179 limit.rlim_cur = global.rlimit_nofile;
3180 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
3181
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003182 if ((global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit) ||
3183 setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02003184 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003185 if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
3186 limit.rlim_cur = global.fd_hard_limit;
3187
William Dauchy0fec3ab2019-10-27 20:08:11 +01003188 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3189 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
3190 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003191 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003192 }
3193 else {
3194 /* try to set it to the max possible at least */
3195 limit.rlim_cur = limit.rlim_max;
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003196 if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
3197 limit.rlim_cur = global.fd_hard_limit;
3198
William Dauchy0fec3ab2019-10-27 20:08:11 +01003199 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
3200 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02003201
William Dauchya5194602020-03-28 19:29:58 +01003202 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003203 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
3204 global.rlimit_nofile = limit.rlim_cur;
3205 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01003206 }
3207 }
3208
3209 if (global.rlimit_memmax) {
3210 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01003211 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01003212#ifdef RLIMIT_AS
3213 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003214 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3215 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3216 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003217 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003218 }
3219 else
William Dauchya5194602020-03-28 19:29:58 +01003220 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003221 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003222 }
3223#else
3224 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003225 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3226 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3227 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003228 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003229 }
3230 else
William Dauchya5194602020-03-28 19:29:58 +01003231 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003232 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003233 }
3234#endif
3235 }
3236
William Lallemandf82afbb2022-01-07 18:19:42 +01003237 /* Try to get the listeners FD from the previous process using
3238 * _getsocks on the stat socket, it must never been done in wait mode
3239 * and check mode
3240 */
3241 if (old_unixsocket &&
3242 !(global.mode & (MODE_MWORKER_WAIT|MODE_CHECK|MODE_CHECK_CONDITION))) {
William Lallemand85b0bd92017-06-01 17:38:53 +02003243 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02003244 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003245 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02003246 if (!(global.mode & MODE_MWORKER))
3247 exit(1);
3248 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02003249 }
3250 }
William Lallemand85b0bd92017-06-01 17:38:53 +02003251
Willy Tarreaubaaee002006-06-26 02:48:02 +02003252 /* We will loop at most 100 times with 10 ms delay each time.
3253 * That's at most 1 second. We only send a signal to old pids
3254 * if we cannot grab at least one port.
3255 */
3256 retry = MAX_START_RETRIES;
3257 err = ERR_NONE;
3258 while (retry >= 0) {
3259 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003260 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003261 /* exit the loop on no error or fatal error */
3262 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003264 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003265 break;
3266
3267 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3268 * listening sockets. So on those platforms, it would be wiser to
3269 * simply send SIGUSR1, which will not be undoable.
3270 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003271 if (tell_old_pids(SIGTTOU) == 0) {
3272 /* no need to wait if we can't contact old pids */
3273 retry = 0;
3274 continue;
3275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 /* give some time to old processes to stop listening */
3277 w.tv_sec = 0;
3278 w.tv_usec = 10*1000;
3279 select(0, NULL, NULL, NULL, &w);
3280 retry--;
3281 }
3282
Willy Tarreaue91bff22020-09-02 11:11:43 +02003283 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003284 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003285 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003286 if (retry != MAX_START_RETRIES && nb_oldpids) {
3287 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003289 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 exit(1);
3291 }
3292
William Lallemand944e6192018-11-21 15:48:31 +01003293 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003294 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003295 /* Note: we don't have to send anything to the old pids because we
3296 * never stopped them. */
3297 exit(1);
3298 }
3299
Willy Tarreaue91bff22020-09-02 11:11:43 +02003300 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003301 * the previous process gave us, we don't need them anymore
3302 */
Willy Tarreaub5101162022-01-28 18:28:18 +01003303 sock_drop_unused_old_sockets();
Willy Tarreaudd815982007-10-16 12:25:14 +02003304
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003306 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3307 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308
Willy Tarreaubaaee002006-06-26 02:48:02 +02003309 /* MODE_QUIET can inhibit alerts and warnings below this line */
3310
PiBa-NL149a81a2017-12-25 21:03:31 +01003311 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3312 /* either stdin/out/err are already closed or should stay as they are. */
3313 if ((global.mode & MODE_DAEMON)) {
3314 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3315 global.mode &= ~MODE_VERBOSE;
3316 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3317 }
3318 } else {
3319 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3320 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003321 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003322 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 }
3324
3325 /* open log & pid files before the chroot */
William Lallemand7b820a62022-02-14 09:02:14 +01003326 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) &&
3327 !(global.mode & MODE_MWORKER_WAIT) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003328 unlink(global.pidfile);
3329 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3330 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003331 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003332 if (nb_oldpids)
3333 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003334 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003335 exit(1);
3336 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 }
3338
Willy Tarreaub38651a2007-03-24 17:24:39 +01003339 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003340 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3341 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003342 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003343 exit(1);
3344 }
3345
Jackie Tapia749f74c2020-07-22 18:59:40 -05003346 /* If the user is not root, we'll still let them try the configuration
3347 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003348 */
3349 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003350 ha_warning("[%s.main()] Some options which require full privileges"
3351 " might not work well.\n"
3352 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003353
William Lallemand095ba4c2017-06-01 17:38:50 +02003354 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3355
3356 /* chroot if needed */
3357 if (global.chroot != NULL) {
3358 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003359 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003360 if (nb_oldpids)
3361 tell_old_pids(SIGTTIN);
3362 protocol_unbind_all();
3363 exit(1);
3364 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003365 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003366 }
3367
William Lallemand944e6192018-11-21 15:48:31 +01003368 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003369 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003370
William Lallemand27edc4b2019-05-07 17:49:33 +02003371 /* send a SIGTERM to workers who have a too high reloads number */
3372 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3373 mworker_kill_max_reloads(SIGTERM);
3374
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 /* Note that any error at this stage will be fatal because we will not
3376 * be able to restart the old pids.
3377 */
3378
William Dauchyf9af9d72019-11-17 15:47:16 +01003379 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3380 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003381
Willy Tarreaubaaee002006-06-26 02:48:02 +02003382 /* check ulimits */
3383 limit.rlim_cur = limit.rlim_max = 0;
3384 getrlimit(RLIMIT_NOFILE, &limit);
3385 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003386 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3387 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3388 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3389 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3390 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003391 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003392 }
3393 else
3394 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003395 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003396 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3397 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398 }
3399
William Lallemand944e6192018-11-21 15:48:31 +01003400 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003401 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003402 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003403 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003404
William Lallemand095ba4c2017-06-01 17:38:50 +02003405 /*
3406 * if daemon + mworker: must fork here to let a master
3407 * process live in background before forking children
3408 */
William Lallemand73b85e72017-06-01 17:38:51 +02003409
3410 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3411 && (global.mode & MODE_MWORKER)
3412 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003413 ret = fork();
3414 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003415 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003416 protocol_unbind_all();
3417 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003418 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003419 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003420 } else /* change the process group ID in the child (master process) */
3421 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003422 }
William Lallemande20b6a62017-06-01 17:38:55 +02003423
William Lallemande20b6a62017-06-01 17:38:55 +02003424
William Lallemanddeed7802017-11-06 11:00:04 +01003425 /* if in master-worker mode, write the PID of the father */
3426 if (global.mode & MODE_MWORKER) {
3427 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003428 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003429 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003430 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003431 }
3432
Willy Tarreaubaaee002006-06-26 02:48:02 +02003433 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003434 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003435 if (global.mode & MODE_MWORKER)
3436 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003437
3438 ret = fork();
3439 if (ret < 0) {
3440 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3441 protocol_unbind_all();
3442 exit(1); /* there has been an error */
3443 }
3444 else if (ret == 0) { /* child breaks here */
Willy Tarreau3c032f22021-07-21 10:17:02 +02003445 /* This one must not be exported, it's internal! */
3446 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003447 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003448 }
3449 else { /* parent here */
3450 in_parent = 1;
3451
William Lallemand944e6192018-11-21 15:48:31 +01003452 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3453 char pidstr[100];
3454 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003455 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003456 }
3457 if (global.mode & MODE_MWORKER) {
3458 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003459
William Lallemand5d71a6b2021-11-09 15:25:31 +01003460 ha_notice("New worker (%d) forked\n", ret);
William Lallemand944e6192018-11-21 15:48:31 +01003461 /* find the right mworker_proc */
3462 list_for_each_entry(child, &proc_list, list) {
William Lallemandd4835a92022-07-21 00:52:43 +02003463 if (child->reloads == 0 &&
3464 child->options & PROC_O_TYPE_WORKER &&
3465 child->pid == -1) {
William Lallemand944e6192018-11-21 15:48:31 +01003466 child->timestamp = now.tv_sec;
3467 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003468 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003469 break;
3470 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003471 }
3472 }
William Lallemand944e6192018-11-21 15:48:31 +01003473 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003474
William Lallemand944e6192018-11-21 15:48:31 +01003475 } else {
3476 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003477 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003478 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003479
3480#ifdef USE_CPU_AFFINITY
Willy Tarreau5b093412022-07-08 09:38:30 +02003481 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 +02003482
David CARLIERdf91cbd2022-01-06 18:53:50 +00003483#if defined(CPUSET_USE_CPUSET) || defined(__DragonFly__)
Willy Tarreau5b093412022-07-08 09:38:30 +02003484 struct hap_cpuset *set = &cpu_map[0].proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003485 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
David CARLIERdf91cbd2022-01-06 18:53:50 +00003486#elif defined(__FreeBSD__)
Willy Tarreau5b093412022-07-08 09:38:30 +02003487 struct hap_cpuset *set = &cpu_map[0].proc;
David CARLIERdf91cbd2022-01-06 18:53:50 +00003488 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003489#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003490 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003491#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003492 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003493 if (pidfd >= 0) {
3494 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3495 close(pidfd);
3496 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003497
3498 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003499 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003500
Willy Tarreaud67ff342021-06-15 07:58:09 +02003501 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003502 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
William Lallemandfab0fdc2021-11-09 18:01:22 +01003503 master = 1;
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003504
3505 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3506 (global.mode & MODE_DAEMON)) {
3507 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003508 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3509 stdio_quiet(-1);
3510
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003511 global.mode &= ~MODE_VERBOSE;
3512 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003513 }
3514
William Lallemandfab0fdc2021-11-09 18:01:22 +01003515 if (global.mode & MODE_MWORKER_WAIT) {
3516 /* only the wait mode handles the master CLI */
3517 mworker_loop();
3518 } else {
3519
William Lallemanda46a99e2022-07-07 14:00:36 +02003520#if defined(USE_SYSTEMD)
3521 if (global.tune.options & GTUNE_USE_SYSTEMD)
3522 sd_notifyf(0, "READY=1\nMAINPID=%lu\nSTATUS=Ready.\n", (unsigned long)getpid());
3523#endif
William Lallemandfab0fdc2021-11-09 18:01:22 +01003524 /* if not in wait mode, reload in wait mode to free the memory */
William Lallemand68192b22022-09-24 15:44:42 +02003525 setenv("HAPROXY_LOAD_SUCCESS", "1", 1);
William Lallemand836bda22021-11-09 18:16:47 +01003526 ha_notice("Loading success.\n");
William Lallemand68836742021-11-10 10:49:06 +01003527 proc_self->failedreloads = 0; /* reset the number of failure */
William Lallemandfab0fdc2021-11-09 18:01:22 +01003528 mworker_reexec_waitmode();
3529 }
William Lallemand1499b9b2017-06-07 15:04:47 +02003530 /* should never get there */
3531 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003532 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003533#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003534 ssl_free_dh();
3535#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003536 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003537 }
3538
William Lallemandcb11fd22017-06-01 17:38:52 +02003539 /* child must never use the atexit function */
3540 atexit_flag = 0;
3541
William Lallemandbc193052018-09-11 10:06:26 +02003542 /* close useless master sockets */
3543 if (global.mode & MODE_MWORKER) {
3544 struct mworker_proc *child, *it;
3545 master = 0;
3546
William Lallemand309dc9a2018-10-26 14:47:45 +02003547 mworker_cli_proxy_stop();
3548
William Lallemandbc193052018-09-11 10:06:26 +02003549 /* free proc struct of other processes */
3550 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003551 /* close the FD of the master side for all
3552 * workers, we don't need to close the worker
3553 * side of other workers since it's done with
3554 * the bind_proc */
William Lallemand7e018782022-01-28 21:56:24 +01003555 if (child->ipc_fd[0] >= 0) {
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003556 close(child->ipc_fd[0]);
William Lallemand7e018782022-01-28 21:56:24 +01003557 child->ipc_fd[0] = -1;
3558 }
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003559 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandd4835a92022-07-21 00:52:43 +02003560 child->reloads == 0 &&
3561 child->pid == -1) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003562 /* keep this struct if this is our pid */
3563 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003564 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003565 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003566 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003567 mworker_free_child(child);
3568 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003569 }
3570 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003571
William Lallemande1340412017-12-28 16:09:36 +01003572 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3573 devnullfd = open("/dev/null", O_RDWR, 0);
3574 if (devnullfd < 0) {
3575 ha_alert("Cannot open /dev/null\n");
3576 exit(EXIT_FAILURE);
3577 }
3578 }
3579
William Lallemand095ba4c2017-06-01 17:38:50 +02003580 /* Must chroot and setgid/setuid in the children */
3581 /* chroot if needed */
3582 if (global.chroot != NULL) {
3583 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003584 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003585 if (nb_oldpids)
3586 tell_old_pids(SIGTTIN);
3587 protocol_unbind_all();
3588 exit(1);
3589 }
3590 }
3591
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003592 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003593 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003594
William Lallemand7f80eb22017-05-26 18:19:55 +02003595 /* pass through every cli socket, and check if it's bound to
3596 * the current process and if it exposes listeners sockets.
3597 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3598 * */
3599
Willy Tarreau4975d142021-03-13 11:00:33 +01003600 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003601 struct bind_conf *bind_conf;
3602
Willy Tarreau4975d142021-03-13 11:00:33 +01003603 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003604 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003605 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3606 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003607 }
3608 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003609 }
3610
William Lallemand2e8fad92018-11-13 16:18:23 +01003611 /*
3612 * This is only done in daemon mode because we might want the
3613 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3614 * we should now close the 3 first FDs to ensure that we can
3615 * detach from the TTY. We MUST NOT do it in other cases since
3616 * it would have already be done, and 0-2 would have been
3617 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003618 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003619 if ((global.mode & MODE_DAEMON) &&
3620 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003621 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003622 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003623 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3625 }
3626 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003627 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3628 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003629 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003630 }
3631
William Dauchye039f262019-11-17 15:47:15 +01003632 /* try our best to re-enable core dumps depending on system capabilities.
3633 * What is addressed here :
3634 * - remove file size limits
3635 * - remove core size limits
3636 * - mark the process dumpable again if it lost it due to user/group
3637 */
3638 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3639 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3640
3641#if defined(RLIMIT_FSIZE)
3642 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3643 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3644 ha_alert("[%s.main()] Failed to set the raise the maximum "
3645 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003646 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003647 }
3648 else
3649 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003650 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003651 }
3652#endif
3653
3654#if defined(RLIMIT_CORE)
3655 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3656 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3657 ha_alert("[%s.main()] Failed to set the raise the core "
3658 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003659 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003660 }
3661 else
3662 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003663 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003664 }
3665#endif
3666
3667#if defined(USE_PRCTL)
3668 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3669 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3670 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003671#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003672 {
3673 int traceable = PROC_TRACE_CTL_ENABLE;
3674 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3675 ha_warning("[%s.main()] Failed to set the traceable flag, "
3676 "no core will be dumped.\n", argv[0]);
3677 }
William Dauchye039f262019-11-17 15:47:15 +01003678#endif
3679 }
3680
Christopher Faulete3a5e352017-10-24 13:53:54 +02003681 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003682 reset_usermsgs_ctx();
3683
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003684 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003685 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003686
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003687 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003688 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003689
3690 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003691 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003692
3693 /* wait for all threads to terminate */
3694 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003695
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003696 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697}
3698
Willy Tarreaubaaee002006-06-26 02:48:02 +02003699/*
3700 * Local variables:
3701 * c-indent-level: 8
3702 * c-basic-offset: 8
3703 * End:
3704 */