blob: 8d6f5876650746ccf060b36e33ff057aed379f81 [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"
Willy Tarreaue5733232019-05-22 19:24:06 +0200593#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200594 " -de disables epoll() usage even when available\n"
595#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200596#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200597 " -dk disables kqueue() usage even when available\n"
598#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200599#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000600 " -dv disables event ports usage even when available\n"
601#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200602#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200603 " -dp disables poll() usage even when available\n"
604#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200605#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100606 " -dS disables splice usage (broken on old kernels)\n"
607#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200608#if defined(USE_GETADDRINFO)
609 " -dG disables getaddrinfo() usage\n"
610#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000611#if defined(SO_REUSEPORT)
612 " -dR disables SO_REUSEPORT usage\n"
613#endif
Willy Tarreau654726d2021-12-28 15:43:11 +0100614#if defined(HA_HAVE_DUMP_LIBS)
615 " -dL dumps loaded object files after config checks\n"
616#endif
Willy Tarreau76871a42022-03-08 16:01:40 +0100617 " -dK{class[,...]} dump registered keywords (use 'help' for list)\n"
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100618 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100619 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200620 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200621 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200622 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200623 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200624 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200625 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100626 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200627 exit(1);
628}
629
630
631
632/*********************************************************************/
633/* more specific functions ***************************************/
634/*********************************************************************/
635
William Lallemand73b85e72017-06-01 17:38:51 +0200636/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
637 * pids the signal was correctly delivered to.
638 */
William Lallemande25473c2019-04-01 11:29:56 +0200639int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200640{
641 int p;
642 int ret = 0;
643 for (p = 0; p < nb_oldpids; p++)
644 if (kill(oldpids[p], sig) == 0)
645 ret++;
646 return ret;
647}
648
William Lallemand75ea0a02017-11-15 19:02:58 +0100649/*
William Lallemand73b85e72017-06-01 17:38:51 +0200650 * remove a pid forom the olpid array and decrease nb_oldpids
651 * return 1 pid was found otherwise return 0
652 */
653
654int delete_oldpid(int pid)
655{
656 int i;
657
658 for (i = 0; i < nb_oldpids; i++) {
659 if (oldpids[i] == pid) {
660 oldpids[i] = oldpids[nb_oldpids - 1];
661 oldpids[nb_oldpids - 1] = 0;
662 nb_oldpids--;
663 return 1;
664 }
665 }
666 return 0;
667}
668
William Lallemand85b0bd92017-06-01 17:38:53 +0200669
William Lallemand73b85e72017-06-01 17:38:51 +0200670/*
671 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800672 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200673 */
William Lallemandfab0fdc2021-11-09 18:01:22 +0100674static void mworker_reexec()
William Lallemand73b85e72017-06-01 17:38:51 +0200675{
William Lallemand00417412020-06-05 14:08:41 +0200676 char **next_argv = NULL;
677 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200678 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200679 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200680 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100681 struct rlimit limit;
William Lallemand2be557f2021-11-24 18:45:37 +0100682 struct mworker_proc *current_child = NULL;
William Lallemand73b85e72017-06-01 17:38:51 +0200683
684 mworker_block_signals();
William Lallemand73b85e72017-06-01 17:38:51 +0200685 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
686
William Lallemand55a921c2022-01-28 21:17:30 +0100687 mworker_cleanup_proc();
William Lallemandbc193052018-09-11 10:06:26 +0200688 mworker_proc_list_to_env(); /* put the children description in the env */
689
William Lallemandc4810b82021-11-18 10:51:30 +0100690 /* ensure that we close correctly every listeners before reexecuting */
691 mworker_cleanlisteners();
692
William Lallemand7c756a82018-11-26 11:53:40 +0100693 /* during the reload we must ensure that every FDs that can't be
694 * reuse (ie those that are not referenced in the proc_list)
695 * are closed or they will leak. */
696
697 /* close the listeners FD */
698 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200699
William Lallemand67e371e2021-11-25 10:03:44 +0100700 if (fdtab)
701 deinit_pollers();
William Lallemandefd95472021-11-26 14:43:57 +0100702
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500703#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200704 /* close random device FDs */
705 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100706#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100707
Willy Tarreau8dca1952019-03-01 10:21:55 +0100708 /* restore the initial FD limits */
709 limit.rlim_cur = rlim_fd_cur_at_boot;
710 limit.rlim_max = rlim_fd_max_at_boot;
711 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
712 getrlimit(RLIMIT_NOFILE, &limit);
713 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
714 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
715 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
716 }
717
William Lallemand73b85e72017-06-01 17:38:51 +0200718 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200719 while (old_argv[old_argc])
720 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200721
William Lallemand85b0bd92017-06-01 17:38:53 +0200722 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200723 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200724 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200725 if (next_argv == NULL)
726 goto alloc_error;
727
William Lallemand00417412020-06-05 14:08:41 +0200728 /* copy the program name */
729 next_argv[next_argc++] = old_argv[0];
730
731 /* insert the new options just after argv[0] in case we have a -- */
732
William Lallemandbefab9e2021-11-25 00:49:19 +0100733 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
734 /* add -sf <PID>* to argv */
735 if (mworker_child_nb() > 0) {
736 struct mworker_proc *child;
William Lallemand3f128872019-04-01 11:29:59 +0200737
William Lallemandbefab9e2021-11-25 00:49:19 +0100738 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200739
William Lallemandbefab9e2021-11-25 00:49:19 +0100740 list_for_each_entry(child, &proc_list, list) {
741 if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
742 current_child = child;
William Lallemand2be557f2021-11-24 18:45:37 +0100743
William Lallemandbefab9e2021-11-25 00:49:19 +0100744 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
745 continue;
746 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
747 goto alloc_error;
748 msg = NULL;
749 }
William Lallemand73b85e72017-06-01 17:38:51 +0200750 }
William Lallemand2be557f2021-11-24 18:45:37 +0100751
752 if (current_child) {
753 /* add the -x option with the socketpair of the current worker */
754 next_argv[next_argc++] = "-x";
755 if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
756 goto alloc_error;
757 msg = NULL;
758 }
William Lallemand85b0bd92017-06-01 17:38:53 +0200759 }
760
William Lallemand00417412020-06-05 14:08:41 +0200761 /* copy the previous options */
762 for (i = 1; i < old_argc; i++)
763 next_argv[next_argc++] = old_argv[i];
764
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200765 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100766 execvp(next_argv[0], next_argv);
Christopher Faulet767a84b2017-11-24 16:50:31 +0100767 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100768 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100769 return;
770
William Lallemand73b85e72017-06-01 17:38:51 +0200771alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100772 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800773 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200774 return;
775}
776
William Lallemandfab0fdc2021-11-09 18:01:22 +0100777/* reexec haproxy in waitmode */
778static void mworker_reexec_waitmode()
779{
780 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
781 mworker_reexec();
782}
783
784/* reload haproxy and emit a warning */
785void mworker_reload()
786{
William Lallemandad221f42021-11-09 18:43:59 +0100787 struct mworker_proc *child;
William Lallemandefd95472021-11-26 14:43:57 +0100788 struct per_thread_deinit_fct *ptdf;
William Lallemandad221f42021-11-09 18:43:59 +0100789
William Lallemand836bda22021-11-09 18:16:47 +0100790 ha_notice("Reloading HAProxy\n");
William Lallemandad221f42021-11-09 18:43:59 +0100791
William Lallemandefd95472021-11-26 14:43:57 +0100792 /* close the poller FD and the thread waker pipe FD */
793 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
794 ptdf->fct();
795
William Lallemandad221f42021-11-09 18:43:59 +0100796 /* increment the number of reloads */
797 list_for_each_entry(child, &proc_list, list) {
798 child->reloads++;
799 }
800
William Lallemanda46a99e2022-07-07 14:00:36 +0200801#if defined(USE_SYSTEMD)
802 if (global.tune.options & GTUNE_USE_SYSTEMD)
803 sd_notify(0, "RELOADING=1\nSTATUS=Reloading Configuration.\n");
804#endif
William Lallemandfab0fdc2021-11-09 18:01:22 +0100805 mworker_reexec();
806}
807
William Lallemandb3f2be32018-09-11 10:06:18 +0200808static void mworker_loop()
809{
810
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200811 /* Busy polling makes no sense in the master :-) */
812 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200813
William Lallemandbc193052018-09-11 10:06:26 +0200814
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100815 signal_unregister(SIGTTIN);
816 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100817 signal_unregister(SIGUSR1);
818 signal_unregister(SIGHUP);
819 signal_unregister(SIGQUIT);
820
William Lallemandb3f2be32018-09-11 10:06:18 +0200821 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
822 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100823 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
824 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200825 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
826 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
827 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
828 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
829
830 mworker_unblock_signals();
William Lallemand27f3fa52018-12-06 14:05:20 +0100831 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200832
William Lallemandbc193052018-09-11 10:06:26 +0200833 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
834 some SIGCHLD were lost */
835
William Lallemandb3f2be32018-09-11 10:06:18 +0200836 jobs++; /* this is the "master" job, we want to take care of the
837 signals even if there is no listener so the poll loop don't
838 leave */
839
840 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200841 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200842}
William Lallemandcb11fd22017-06-01 17:38:52 +0200843
844/*
845 * Reexec the process in failure mode, instead of exiting
846 */
847void reexec_on_failure()
848{
William Lallemand68836742021-11-10 10:49:06 +0100849 struct mworker_proc *child;
850
William Lallemandcb11fd22017-06-01 17:38:52 +0200851 if (!atexit_flag)
852 return;
William Lallemand68836742021-11-10 10:49:06 +0100853
854 /* get the info of the children in the env */
855 if (mworker_env_to_proc_list() < 0) {
856 exit(EXIT_FAILURE);
857 }
858
859 /* increment the number of failed reloads */
860 list_for_each_entry(child, &proc_list, list) {
861 child->failedreloads++;
862 }
863
Willy Tarreaue08acae2022-01-28 18:40:06 +0100864 /* do not keep unused FDs retrieved from the previous process */
865 sock_drop_unused_old_sockets();
866
William Lallemandfab0fdc2021-11-09 18:01:22 +0100867 usermsgs_clr(NULL);
William Lallemand836bda22021-11-09 18:16:47 +0100868 ha_warning("Loading failure!\n");
William Lallemanda46a99e2022-07-07 14:00:36 +0200869#if defined(USE_SYSTEMD)
870 /* the sd_notify API is not able to send a reload failure signal. So
871 * the READY=1 signal still need to be sent */
872 if (global.tune.options & GTUNE_USE_SYSTEMD)
873 sd_notify(0, "READY=1\nSTATUS=Reload failed!\n");
874#endif
875
William Lallemandfab0fdc2021-11-09 18:01:22 +0100876 mworker_reexec_waitmode();
William Lallemandcb11fd22017-06-01 17:38:52 +0200877}
William Lallemand73b85e72017-06-01 17:38:51 +0200878
879
880/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200881 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
882 * a signal zero to all subscribers. This means that it's as easy as
883 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200884 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100885static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886{
887 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200888 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100889 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200890}
891
892/*
893 * upon SIGTTOU, we pause everything
894 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100895static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200896{
Willy Tarreau775e0012020-09-24 16:36:26 +0200897 if (protocol_pause_all() & ERR_FATAL) {
898 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200899 ha_warning("%s", msg);
900 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200901 soft_stop();
902 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100903 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904}
905
906/*
907 * upon SIGTTIN, let's have a soft stop.
908 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100909static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910{
Willy Tarreau775e0012020-09-24 16:36:26 +0200911 if (protocol_resume_all() & ERR_FATAL) {
912 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 +0200913 ha_warning("%s", msg);
914 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200915 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916}
917
918/*
919 * this function dumps every server's state when the process receives SIGHUP.
920 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100921static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100923 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200924
Christopher Faulet767a84b2017-11-24 16:50:31 +0100925 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 while (p) {
927 struct server *s = p->srv;
928
929 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
930 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100931 chunk_printf(&trash,
932 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
933 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200934 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200935 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200936 ha_warning("%s\n", trash.area);
937 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938 s = s->next;
939 }
940
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200941 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
942 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100943 chunk_printf(&trash,
944 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
945 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200946 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 +0200947 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100948 chunk_printf(&trash,
949 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
950 p->id,
951 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200952 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 +0200953 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100954 chunk_printf(&trash,
955 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
956 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
957 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200958 p->feconn, p->beconn, p->totpend, p->queue.length, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200960 ha_warning("%s\n", trash.area);
961 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962
963 p = p->next;
964 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200965}
966
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100967static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200969 /* dump memory usage then free everything possible */
970 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100971 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200972}
973
William Lallemande1340412017-12-28 16:09:36 +0100974/*
975 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
976 * If <fd> < 0, it opens /dev/null and use it to dup
977 *
978 * In the case of chrooting, you have to open /dev/null before the chroot, and
979 * pass the <fd> to this function
980 */
981static void stdio_quiet(int fd)
982{
983 if (fd < 0)
984 fd = open("/dev/null", O_RDWR, 0);
985
986 if (fd > -1) {
987 fclose(stdin);
988 fclose(stdout);
989 fclose(stderr);
990
991 dup2(fd, 0);
992 dup2(fd, 1);
993 dup2(fd, 2);
994 if (fd > 2)
995 close(fd);
996 return;
997 }
998
999 ha_alert("Cannot open /dev/null\n");
1000 exit(EXIT_FAILURE);
1001}
1002
1003
Joseph Herlant03420902018-11-15 10:41:50 -08001004/* This function checks if cfg_cfgfiles contains directories.
1005 * If it finds one, it adds all the files (and only files) it contains
1006 * in cfg_cfgfiles in place of the directory (and removes the directory).
1007 * It adds the files in lexical order.
1008 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001009 * It doesn't add files with name starting with '.'
1010 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001011static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001012{
1013 struct wordlist *wl, *wlb;
1014 char *err = NULL;
1015
1016 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1017 struct stat file_stat;
1018 struct dirent **dir_entries = NULL;
1019 int dir_entries_nb;
1020 int dir_entries_it;
1021
1022 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001023 ha_alert("Cannot open configuration file/directory %s : %s\n",
1024 wl->s,
1025 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001026 exit(1);
1027 }
1028
1029 if (!S_ISDIR(file_stat.st_mode))
1030 continue;
1031
1032 /* from this point wl->s is a directory */
1033
1034 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1035 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001036 ha_alert("Cannot open configuration directory %s : %s\n",
1037 wl->s,
1038 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001039 exit(1);
1040 }
1041
1042 /* for each element in the directory wl->s */
1043 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1044 struct dirent *dir_entry = dir_entries[dir_entries_it];
1045 char *filename = NULL;
1046 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1047
1048 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001049 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001050 */
1051 if (dir_entry->d_name[0] == '.' ||
1052 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1053 goto next_dir_entry;
1054
1055 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001056 ha_alert("Cannot load configuration files %s : out of memory.\n",
1057 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001058 exit(1);
1059 }
1060
1061 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001062 ha_alert("Cannot open configuration file %s : %s\n",
1063 wl->s,
1064 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001065 exit(1);
1066 }
1067
1068 /* don't add anything else than regular file in cfg_cfgfiles
1069 * this way we avoid loops
1070 */
1071 if (!S_ISREG(file_stat.st_mode))
1072 goto next_dir_entry;
1073
1074 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001075 ha_alert("Cannot load configuration files %s : %s\n",
1076 filename,
1077 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001078 exit(1);
1079 }
1080
1081next_dir_entry:
1082 free(filename);
1083 free(dir_entry);
1084 }
1085
1086 free(dir_entries);
1087
1088 /* remove the current directory (wl) from cfg_cfgfiles */
1089 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001090 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001091 free(wl);
1092 }
1093
1094 free(err);
1095}
1096
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097/*
William Lallemand73b85e72017-06-01 17:38:51 +02001098 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001099 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001100 * Return an allocated copy of argv
1101 */
1102
1103static char **copy_argv(int argc, char **argv)
1104{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001105 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001106
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001107 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001108 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001109 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001110 return NULL;
1111 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001112 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001113
William Lallemanddf6c5a82020-06-04 17:40:23 +02001114 /* first copy argv[0] */
1115 *newargv++ = *argv++;
1116 argc--;
1117
1118 while (argc > 0) {
1119 if (**argv != '-') {
1120 /* non options are copied but will fail in the argument parser */
1121 *newargv++ = *argv++;
1122 argc--;
1123
1124 } else {
1125 char *flag;
1126
1127 flag = *argv + 1;
1128
1129 if (flag[0] == '-' && flag[1] == 0) {
1130 /* "--\0" copy every arguments till the end of argv */
1131 *newargv++ = *argv++;
1132 argc--;
1133
1134 while (argc > 0) {
1135 *newargv++ = *argv++;
1136 argc--;
1137 }
1138 } else {
1139 switch (*flag) {
1140 case 's':
1141 /* -sf / -st and their parameters are ignored */
1142 if (flag[1] == 'f' || flag[1] == 't') {
1143 argc--;
1144 argv++;
1145 /* The list can't contain a negative value since the only
1146 way to know the end of this list is by looking for the
1147 next option or the end of the options */
1148 while (argc > 0 && argv[0][0] != '-') {
1149 argc--;
1150 argv++;
1151 }
William Lallemand398da622020-09-02 16:12:23 +02001152 } else {
1153 argc--;
1154 argv++;
1155
William Lallemanddf6c5a82020-06-04 17:40:23 +02001156 }
1157 break;
1158
1159 case 'x':
1160 /* this option and its parameter are ignored */
1161 argc--;
1162 argv++;
1163 if (argc > 0) {
1164 argc--;
1165 argv++;
1166 }
1167 break;
1168
1169 case 'C':
1170 case 'n':
1171 case 'm':
1172 case 'N':
1173 case 'L':
1174 case 'f':
1175 case 'p':
1176 case 'S':
1177 /* these options have only 1 parameter which must be copied and can start with a '-' */
1178 *newargv++ = *argv++;
1179 argc--;
1180 if (argc == 0)
1181 goto error;
1182 *newargv++ = *argv++;
1183 argc--;
1184 break;
1185 default:
1186 /* for other options just copy them without parameters, this is also done
1187 * for options like "--foo", but this will fail in the argument parser.
1188 * */
1189 *newargv++ = *argv++;
1190 argc--;
1191 break;
1192 }
William Lallemand73b85e72017-06-01 17:38:51 +02001193 }
1194 }
William Lallemand73b85e72017-06-01 17:38:51 +02001195 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001196
William Lallemanddf6c5a82020-06-04 17:40:23 +02001197 return retargv;
1198
1199error:
1200 free(retargv);
1201 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001202}
1203
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001204
1205/* Performs basic random seed initialization. The main issue with this is that
1206 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1207 * which means that there will only be 4 billion possible random sequences once
1208 * srandom() is called, regardless of the internal state. Not calling it is
1209 * even worse as we'll always produce the same randoms sequences. What we do
1210 * here is to create an initial sequence from various entropy sources, hash it
1211 * using SHA1 and keep the resulting 160 bits available globally.
1212 *
1213 * We initialize the current process with the first 32 bits before starting the
1214 * polling loop, where all this will be changed to have process specific and
1215 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001216 *
1217 * Before starting threads, it's still possible to call random() as srandom()
1218 * is initialized from this, but after threads and/or processes are started,
1219 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001220 */
1221static void ha_random_boot(char *const *argv)
1222{
1223 unsigned char message[256];
1224 unsigned char *m = message;
1225 struct timeval tv;
1226 blk_SHA_CTX ctx;
1227 unsigned long l;
1228 int fd;
1229 int i;
1230
1231 /* start with current time as pseudo-random seed */
1232 gettimeofday(&tv, NULL);
1233 write_u32(m, tv.tv_sec); m += 4;
1234 write_u32(m, tv.tv_usec); m += 4;
1235
1236 /* PID and PPID add some OS-based randomness */
1237 write_u16(m, getpid()); m += 2;
1238 write_u16(m, getppid()); m += 2;
1239
1240 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1241 fd = open("/dev/urandom", O_RDONLY);
1242 if (fd >= 0) {
1243 i = read(fd, m, 20);
1244 if (i > 0)
1245 m += i;
1246 close(fd);
1247 }
1248
1249 /* take up to 160 bits bytes from openssl (non-blocking) */
1250#ifdef USE_OPENSSL
1251 if (RAND_bytes(m, 20) == 1)
1252 m += 20;
1253#endif
1254
1255 /* take 160 bits from existing random in case it was already initialized */
1256 for (i = 0; i < 5; i++) {
1257 write_u32(m, random());
1258 m += 4;
1259 }
1260
1261 /* stack address (benefit form operating system's ASLR) */
1262 l = (unsigned long)&m;
1263 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1264
1265 /* argv address (benefit form operating system's ASLR) */
1266 l = (unsigned long)&argv;
1267 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1268
1269 /* use tv_usec again after all the operations above */
1270 gettimeofday(&tv, NULL);
1271 write_u32(m, tv.tv_usec); m += 4;
1272
1273 /*
1274 * At this point, ~84-92 bytes have been used
1275 */
1276
1277 /* finish with the hostname */
1278 strncpy((char *)m, hostname, message + sizeof(message) - m);
1279 m += strlen(hostname);
1280
1281 /* total message length */
1282 l = m - message;
1283
1284 memset(&ctx, 0, sizeof(ctx));
1285 blk_SHA1_Init(&ctx);
1286 blk_SHA1_Update(&ctx, message, l);
1287 blk_SHA1_Final(boot_seed, &ctx);
1288
1289 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001290 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001291}
1292
Willy Tarreau5a023f02019-03-01 14:19:31 +01001293/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1294 * setting, and returns it. It may return -1 meaning "unlimited" if some
1295 * unlimited proxies have been found and the global.maxconn value is not yet
1296 * set. It may also return a value greater than maxconn if it's not yet set.
1297 * Note that a value of zero means there is no need for pipes. -1 is never
1298 * returned if global.maxconn is valid.
1299 */
1300static int compute_ideal_maxpipes()
1301{
1302 struct proxy *cur;
1303 int nbfe = 0, nbbe = 0;
1304 int unlimited = 0;
1305 int pipes;
1306 int max;
1307
1308 for (cur = proxies_list; cur; cur = cur->next) {
1309 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1310 if (cur->cap & PR_CAP_FE) {
1311 max = cur->maxconn;
1312 nbfe += max;
1313 if (!max) {
1314 unlimited = 1;
1315 break;
1316 }
1317 }
1318 if (cur->cap & PR_CAP_BE) {
1319 max = cur->fullconn ? cur->fullconn : global.maxconn;
1320 nbbe += max;
1321 if (!max) {
1322 unlimited = 1;
1323 break;
1324 }
1325 }
1326 }
1327 }
1328
1329 pipes = MAX(nbfe, nbbe);
1330 if (global.maxconn) {
1331 if (pipes > global.maxconn || unlimited)
1332 pipes = global.maxconn;
1333 } else if (unlimited) {
1334 pipes = -1;
1335 }
1336
1337 return pipes >= 4 ? pipes / 4 : pipes;
1338}
1339
Willy Tarreauac350932019-03-01 15:43:14 +01001340/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1341 * rlimits and computes an ideal maxconn. It's meant to be called only when
1342 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001343 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1344 * default 100) is returned as it is expected that it will even run on tight
1345 * environments, and will maintain compatibility with previous packages that
1346 * used to rely on this value as the default one. The system will emit a
1347 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001348 */
1349static int compute_ideal_maxconn()
1350{
1351 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1352 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1353 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001354 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001355 int maxconn;
1356
1357 /* we have to take into account these elements :
1358 * - number of engine_fds, which inflates the number of FD needed per
1359 * connection by this number.
1360 * - number of pipes per connection on average : for the unlimited
1361 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1362 * fixed value of 2*pipes.
1363 * - two FDs per connection
1364 */
1365
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02001366 if (global.fd_hard_limit && remain > global.fd_hard_limit)
1367 remain = global.fd_hard_limit;
1368
Willy Tarreauac350932019-03-01 15:43:14 +01001369 /* subtract listeners and checks */
1370 remain -= global.maxsock;
1371
Willy Tarreau3f200852019-03-14 19:13:17 +01001372 /* one epoll_fd/kqueue_fd per thread */
1373 remain -= global.nbthread;
1374
1375 /* one wake-up pipe (2 fd) per thread */
1376 remain -= 2 * global.nbthread;
1377
Willy Tarreauac350932019-03-01 15:43:14 +01001378 /* Fixed pipes values : we only subtract them if they're not larger
1379 * than the remaining FDs because pipes are optional.
1380 */
1381 if (pipes >= 0 && pipes * 2 < remain)
1382 remain -= pipes * 2;
1383
1384 if (pipes < 0) {
1385 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1386 * = maxconn * (2 + 0.5 + engine_fds)
1387 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1388 */
1389 maxconn = 2 * remain / (5 + 2 * engine_fds);
1390 } else {
1391 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1392 * = maxconn * (2 + engine_fds)
1393 */
1394 maxconn = remain / (2 + engine_fds);
1395 }
1396
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001397 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001398}
1399
Willy Tarreaua409f302020-03-10 17:08:53 +01001400/* computes the estimated maxsock value for the given maxconn based on the
1401 * possibly set global.maxpipes and existing partial global.maxsock. It may
1402 * temporarily change global.maxconn for the time needed to propagate the
1403 * computations, and will reset it.
1404 */
1405static int compute_ideal_maxsock(int maxconn)
1406{
1407 int maxpipes = global.maxpipes;
1408 int maxsock = global.maxsock;
1409
1410
1411 if (!maxpipes) {
1412 int old_maxconn = global.maxconn;
1413
1414 global.maxconn = maxconn;
1415 maxpipes = compute_ideal_maxpipes();
1416 global.maxconn = old_maxconn;
1417 }
1418
1419 maxsock += maxconn * 2; /* each connection needs two sockets */
1420 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1421 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1422 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1423
1424 /* compute fd used by async engines */
1425 if (global.ssl_used_async_engines) {
1426 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1427
1428 maxsock += maxconn * sides * global.ssl_used_async_engines;
1429 }
1430 return maxsock;
1431}
1432
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001433/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001434 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1435 * value is accepted, non-zero otherwise. This is used to determine if an
1436 * automatic limit may be applied or not. When it is not, the caller knows that
1437 * the highest we can do is the rlim_max at boot. In case of error, we return
1438 * that the setting is possible, so that we defer the error processing to the
1439 * final stage in charge of enforcing this.
1440 */
1441static int check_if_maxsock_permitted(int maxsock)
1442{
1443 struct rlimit orig_limit, test_limit;
1444 int ret;
1445
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02001446 if (global.fd_hard_limit && maxsock > global.fd_hard_limit)
1447 return 0;
1448
Willy Tarreau304e17e2020-03-10 17:54:54 +01001449 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1450 return 1;
1451
1452 /* don't go further if we can't even set to what we have */
1453 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1454 return 1;
1455
1456 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1457 test_limit.rlim_cur = test_limit.rlim_max;
1458 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1459
1460 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1461 return 1;
1462
1463 return ret == 0;
1464}
1465
Willy Tarreau34527d52022-02-17 17:45:58 +01001466/* This performs th every basic early initialization at the end of the PREPARE
1467 * init stage. It may only assume that list heads are initialized, but not that
1468 * anything else is correct. It will initialize a number of variables that
1469 * depend on command line and will pre-parse the command line. If it fails, it
1470 * directly exits.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001471 */
Willy Tarreau34527d52022-02-17 17:45:58 +01001472static void init_early(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001473{
Kevinm48936af2010-12-22 16:08:21 +00001474 char *progname;
Willy Tarreau34527d52022-02-17 17:45:58 +01001475 char *tmp;
1476 int len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001477
Willy Tarreau34527d52022-02-17 17:45:58 +01001478 /* First, let's initialize most global variables */
1479 totalconn = actconn = listeners = stopping = 0;
1480 killed = pid = 0;
1481
1482 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
1483 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Christopher Faulete3a5e352017-10-24 13:53:54 +02001484 global.mode = MODE_STARTING;
William Lallemand73b85e72017-06-01 17:38:51 +02001485
Willy Tarreau34527d52022-02-17 17:45:58 +01001486 /* if we were in mworker mode, we should restart in mworker mode */
1487 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1488 global.mode |= MODE_MWORKER;
David du Colombier7af46052012-05-16 14:16:48 +02001489
Willy Tarreau34527d52022-02-17 17:45:58 +01001490 /* initialize date, time, and pid */
1491 tzset();
1492 clock_init_process_date();
1493 start_date = now;
1494 pid = getpid();
1495
1496 /* Set local host name and adjust some environment variables.
1497 * NB: POSIX does not make it mandatory for gethostname() to
1498 * NULL-terminate the string in case of truncation, and at least
1499 * FreeBSD appears not to do it.
Emeric Brun2b920a12010-09-23 18:30:22 +02001500 */
1501 memset(hostname, 0, sizeof(hostname));
1502 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001503
Willy Tarreau34527d52022-02-17 17:45:58 +01001504 /* preset some environment variables */
1505 localpeer = strdup(hostname);
1506 if (!localpeer || setenv("HAPROXY_LOCALPEER", localpeer, 1) < 0) {
Dragan Dosen4f014152020-06-18 16:56:47 +02001507 ha_alert("Cannot allocate memory for local peer.\n");
1508 exit(EXIT_FAILURE);
1509 }
Emeric Brun2b920a12010-09-23 18:30:22 +02001510
Willy Tarreau34527d52022-02-17 17:45:58 +01001511 /* Some CPU affinity stuff may have to be initialized */
1512#ifdef USE_CPU_AFFINITY
1513 {
Willy Tarreau5b093412022-07-08 09:38:30 +02001514 int g, i;
1515
1516 for (g = 0; g < MAX_TGROUPS; g++) {
1517 ha_cpuset_zero(&cpu_map[g].proc);
1518 ha_cpuset_zero(&cpu_map[g].proc_t1);
1519 for (i = 0; i < MAX_THREADS_PER_GROUP; ++i) {
1520 ha_cpuset_zero(&cpu_map[g].thread[i]);
1521 }
Willy Tarreau34527d52022-02-17 17:45:58 +01001522 }
1523 }
1524#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001525
Willy Tarreau34527d52022-02-17 17:45:58 +01001526 /* extract the program name from argv[0], it will be used for the logs
1527 * and error messages.
1528 */
1529 progname = *argv;
1530 while ((tmp = strchr(progname, '/')) != NULL)
1531 progname = tmp + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001532
Willy Tarreau34527d52022-02-17 17:45:58 +01001533 len = strlen(progname);
1534 progname = strdup(progname);
1535 if (!progname) {
1536 ha_alert("Cannot allocate memory for log_tag.\n");
1537 exit(EXIT_FAILURE);
1538 }
Willy Tarreau84310e22014-02-14 11:59:04 +01001539
Willy Tarreau34527d52022-02-17 17:45:58 +01001540 chunk_initlen(&global.log_tag, progname, len, len);
1541}
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001542
Willy Tarreau392524d2022-02-17 18:10:36 +01001543/* handles program arguments. Very minimal parsing is performed, variables are
1544 * fed with some values, and lists are completed with other ones. In case of
1545 * error, it will exit.
Willy Tarreau34527d52022-02-17 17:45:58 +01001546 */
Willy Tarreau392524d2022-02-17 18:10:36 +01001547static void init_args(int argc, char **argv)
Willy Tarreau34527d52022-02-17 17:45:58 +01001548{
Willy Tarreau34527d52022-02-17 17:45:58 +01001549 char *progname = global.log_tag.area;
Willy Tarreau392524d2022-02-17 18:10:36 +01001550 char *err_msg = NULL;
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001551
Willy Tarreau34527d52022-02-17 17:45:58 +01001552 /* pre-fill in the global tuning options before we let the cmdline
1553 * change them.
1554 */
Willy Tarreau43b78992009-01-25 15:42:27 +01001555 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001556#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001557 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001559#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001560 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001562#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001563 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001564#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001565#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001566 global.tune.options |= GTUNE_USE_EVPORTS;
1567#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001568#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001569 global.tune.options |= GTUNE_USE_SPLICE;
1570#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001571#if defined(USE_GETADDRINFO)
1572 global.tune.options |= GTUNE_USE_GAI;
1573#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001574#if defined(SO_REUSEPORT)
1575 global.tune.options |= GTUNE_USE_REUSEPORT;
1576#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001577#ifdef USE_THREAD
1578 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1579#endif
William Dauchya5194602020-03-28 19:29:58 +01001580 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581
Willy Tarreau392524d2022-02-17 18:10:36 +01001582 /* keep a copy of original arguments for the master process */
1583 old_argv = copy_argv(argc, argv);
1584 if (!old_argv) {
1585 ha_alert("failed to copy argv.\n");
1586 exit(EXIT_FAILURE);
1587 }
1588
1589 /* skip program name and start */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590 argc--; argv++;
1591 while (argc > 0) {
1592 char *flag;
1593
1594 if (**argv == '-') {
1595 flag = *argv+1;
1596
1597 /* 1 arg */
1598 if (*flag == 'v') {
1599 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001600 if (flag[1] == 'v') /* -vv */
1601 display_build_opts();
Tim Duesterhus77b3db02022-04-27 00:08:11 +02001602 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001604#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001606 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001608#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001610 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001611#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001612#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001613 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001614 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001615#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001616#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001617 else if (*flag == 'd' && flag[1] == 'v')
1618 global.tune.options &= ~GTUNE_USE_EVPORTS;
1619#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001620#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001621 else if (*flag == 'd' && flag[1] == 'S')
1622 global.tune.options &= ~GTUNE_USE_SPLICE;
1623#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001624#if defined(USE_GETADDRINFO)
1625 else if (*flag == 'd' && flag[1] == 'G')
1626 global.tune.options &= ~GTUNE_USE_GAI;
1627#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001628#if defined(SO_REUSEPORT)
1629 else if (*flag == 'd' && flag[1] == 'R')
1630 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1631#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001632 else if (*flag == 'd' && flag[1] == 'V')
1633 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001634 else if (*flag == 'V')
1635 arg_mode |= MODE_VERBOSE;
1636 else if (*flag == 'd' && flag[1] == 'b')
1637 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001638 else if (*flag == 'd' && flag[1] == 'D')
1639 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001640 else if (*flag == 'd' && flag[1] == 'W')
1641 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreauef301b72022-02-23 14:15:18 +01001642 else if (*flag == 'd' && flag[1] == 'M') {
Willy Tarreau1408b1f2022-02-18 18:54:40 +01001643 int ret = pool_parse_debugging(flag + 2, &err_msg);
1644
1645 if (ret <= -1) {
1646 if (ret < -1)
1647 ha_alert("-dM: %s\n", err_msg);
1648 else
1649 printf("%s\n", err_msg);
1650 ha_free(&err_msg);
1651 exit(ret < -1 ? EXIT_FAILURE : 0);
1652 } else if (ret == 0) {
1653 ha_warning("-dM: %s\n", err_msg);
1654 ha_free(&err_msg);
1655 }
Willy Tarreauef301b72022-02-23 14:15:18 +01001656 }
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001657 else if (*flag == 'd' && flag[1] == 'r')
1658 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreau654726d2021-12-28 15:43:11 +01001659#if defined(HA_HAVE_DUMP_LIBS)
1660 else if (*flag == 'd' && flag[1] == 'L')
1661 arg_mode |= MODE_DUMP_LIBS;
1662#endif
Willy Tarreau76871a42022-03-08 16:01:40 +01001663 else if (*flag == 'd' && flag[1] == 'K') {
1664 arg_mode |= MODE_DUMP_KWD;
1665 kwd_dump = flag + 2;
1666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667 else if (*flag == 'd')
1668 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001669 else if (*flag == 'c' && flag[1] == 'c') {
1670 arg_mode |= MODE_CHECK_CONDITION;
1671 argv++;
1672 argc--;
1673 check_condition = *argv;
1674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001675 else if (*flag == 'c')
1676 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001677 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001678 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001679 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001680 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001681#if defined(USE_SYSTEMD)
1682 global.tune.options |= GTUNE_USE_SYSTEMD;
1683#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001684 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 +01001685 usage(progname);
1686#endif
1687 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001688 else if (*flag == 'W')
1689 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001690 else if (*flag == 'q')
1691 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001692 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001693 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001694 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001695 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001696 }
William Lallemand4fc09692017-06-19 16:37:19 +02001697 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001698 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001699 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001700
Olivier Houchardf73629d2017-04-05 22:33:04 +02001701 argv++;
1702 argc--;
1703 }
William Lallemande7361152018-10-26 14:47:36 +02001704 else if (*flag == 'S') {
1705 struct wordlist *c;
1706
William Lallemanda6b32492020-06-04 23:49:20 +02001707 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001708 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1709 usage(progname);
1710 }
1711 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1712 ha_alert("Cannot allocate memory\n");
1713 exit(EXIT_FAILURE);
1714 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001715 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001716
1717 argv++;
1718 argc--;
1719 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1721 /* list of pids to finish ('f') or terminate ('t') */
1722
1723 if (flag[1] == 'f')
1724 oldpids_sig = SIGUSR1; /* finish then exit */
1725 else
1726 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001727 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001728 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001729 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1730 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001731 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001732 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001733 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001734 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001735 errno = 0;
1736 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1737 if (errno) {
1738 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1739 flag,
1740 *argv, strerror(errno));
1741 exit(1);
1742 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001743 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001744 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001745 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1746 flag, endptr);
1747 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001748 }
Chris Lane236062f2018-02-05 23:15:44 +00001749 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001750 if (oldpids[nb_oldpids] <= 0)
1751 usage(progname);
1752 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001753 }
1754 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001755 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1756 /* now that's a cfgfile list */
1757 argv++; argc--;
1758 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001759 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001760 ha_alert("Cannot load configuration file/directory %s : %s\n",
1761 *argv,
1762 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001763 exit(1);
1764 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001765 argv++; argc--;
1766 }
1767 break;
1768 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001769 else { /* >=2 args */
1770 argv++; argc--;
1771 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001772 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773
1774 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001775 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001777 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001779 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001780 free(localpeer);
1781 if ((localpeer = strdup(*argv)) == NULL) {
1782 ha_alert("Cannot allocate memory for local peer.\n");
1783 exit(EXIT_FAILURE);
1784 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001785 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001786 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001787 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001788 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001789 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001790 ha_alert("Cannot load configuration file/directory %s : %s\n",
1791 *argv,
1792 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001793 exit(1);
1794 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001795 break;
Willy Tarreau392524d2022-02-17 18:10:36 +01001796 case 'p' :
1797 free(global.pidfile);
1798 if ((global.pidfile = strdup(*argv)) == NULL) {
1799 ha_alert("Cannot allocate memory for pidfile.\n");
1800 exit(EXIT_FAILURE);
1801 }
1802 break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001803 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001804 }
1805 }
1806 }
1807 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001808 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001809 argv++; argc--;
1810 }
Willy Tarreau392524d2022-02-17 18:10:36 +01001811 free(err_msg);
1812}
1813
Willy Tarreau76871a42022-03-08 16:01:40 +01001814/* call the various keyword dump functions based on the comma-delimited list of
1815 * classes in kwd_dump.
1816 */
1817static void dump_registered_keywords(void)
1818{
1819 char *end;
1820 int all __maybe_unused = 0;
1821
1822 for (; kwd_dump && *kwd_dump; kwd_dump = end) {
1823 end = strchr(kwd_dump, ',');
1824 if (end)
1825 *(end++) = 0;
1826
1827 if (strcmp(kwd_dump, "help") == 0) {
1828 printf("# List of supported keyword classes:\n");
1829 printf("all: list all keywords\n");
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001830 printf("acl: ACL keywords\n");
Willy Tarreauca1acd62022-03-29 15:02:44 +02001831 printf("cfg: configuration keywords\n");
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001832 printf("cli: CLI keywords\n");
Willy Tarreau29d799d2022-03-29 16:59:49 +02001833 printf("cnv: sample converter keywords\n");
Willy Tarreau3b65e142022-03-29 15:03:09 +02001834 printf("flt: filter names\n");
Willy Tarreauf78813f2022-03-29 16:51:29 +02001835 printf("smp: sample fetch functions\n");
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001836 printf("svc: service names\n");
Willy Tarreau76871a42022-03-08 16:01:40 +01001837 continue;
1838 }
1839 else if (strcmp(kwd_dump, "all") == 0) {
1840 all = 1;
1841 }
Willy Tarreauca1acd62022-03-29 15:02:44 +02001842
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001843 if (all || strcmp(kwd_dump, "acl") == 0) {
1844 printf("# List of registered ACL keywords:\n");
1845 acl_dump_kwd();
1846 }
1847
Willy Tarreauca1acd62022-03-29 15:02:44 +02001848 if (all || strcmp(kwd_dump, "cfg") == 0) {
1849 printf("# List of registered configuration keywords:\n");
1850 cfg_dump_registered_keywords();
1851 }
Willy Tarreau3b65e142022-03-29 15:03:09 +02001852
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001853 if (all || strcmp(kwd_dump, "cli") == 0) {
1854 printf("# List of registered CLI keywords:\n");
1855 cli_list_keywords();
1856 }
1857
Willy Tarreau29d799d2022-03-29 16:59:49 +02001858 if (all || strcmp(kwd_dump, "cnv") == 0) {
1859 printf("# List of registered sample converter functions:\n");
1860 smp_dump_conv_kw();
1861 }
1862
Willy Tarreau3b65e142022-03-29 15:03:09 +02001863 if (all || strcmp(kwd_dump, "flt") == 0) {
1864 printf("# List of registered filter names:\n");
1865 flt_dump_kws(NULL);
1866 }
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001867
Willy Tarreauf78813f2022-03-29 16:51:29 +02001868 if (all || strcmp(kwd_dump, "smp") == 0) {
1869 printf("# List of registered sample fetch functions:\n");
1870 smp_dump_fetch_kw();
1871 }
1872
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001873 if (all || strcmp(kwd_dump, "svc") == 0) {
1874 printf("# List of registered service names:\n");
1875 list_services(NULL);
1876 }
Willy Tarreau76871a42022-03-08 16:01:40 +01001877 }
1878}
1879
Willy Tarreau392524d2022-02-17 18:10:36 +01001880/*
1881 * This function initializes all the necessary variables. It only returns
1882 * if everything is OK. If something fails, it exits.
1883 */
1884static void init(int argc, char **argv)
1885{
1886 char *progname = global.log_tag.area;
1887 int err_code = 0;
1888 struct wordlist *wl;
1889 struct proxy *px;
1890 struct post_check_fct *pcf;
William Lallemandb53eb872022-04-21 18:02:53 +02001891 struct pre_check_fct *prcf;
Willy Tarreau392524d2022-02-17 18:10:36 +01001892 int ideal_maxconn;
1893
1894 if (!init_trash_buffers(1)) {
1895 ha_alert("failed to initialize trash buffers.\n");
1896 exit(1);
1897 }
1898
1899 if (init_acl() != 0)
1900 exit(1);
1901
1902 /* Initialise lua. */
1903 hlua_init();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904
Christopher Faulete3a5e352017-10-24 13:53:54 +02001905 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001906 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Willy Tarreau76871a42022-03-08 16:01:40 +01001907 | MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS | MODE_DUMP_KWD));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001908
William Lallemand944e6192018-11-21 15:48:31 +01001909 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001910 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001911 global.mode |= MODE_MWORKER_WAIT;
1912 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001913 }
1914
Willy Tarreau26146192021-07-21 10:01:36 +02001915 if ((global.mode & (MODE_MWORKER | MODE_CHECK | MODE_CHECK_CONDITION)) == MODE_MWORKER &&
1916 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001917 atexit_flag = 1;
1918 atexit(reexec_on_failure);
1919 }
1920
Willy Tarreau576132e2011-09-10 19:26:56 +02001921 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001922 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001923 exit(1);
1924 }
1925
Amaury Denoyelle11124302021-06-04 18:22:08 +02001926 usermsgs_clr("config");
1927
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001928 if (global.mode & MODE_CHECK_CONDITION) {
1929 int result;
1930
1931 uint32_t err;
1932 const char *errptr;
1933 char *errmsg = NULL;
1934
1935 char *args[MAX_LINE_ARGS+1];
1936 int arg = sizeof(args) / sizeof(*args);
William Lallemand89e236f2022-05-06 17:22:36 +02001937 size_t outlen;
Willy Tarreauc8194c32021-07-16 16:38:58 +02001938 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001939
William Lallemand89e236f2022-05-06 17:22:36 +02001940 if (!check_condition)
1941 usage(progname);
1942
1943 outlen = strlen(check_condition) + 1;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001944 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02001945 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001946 &errptr);
1947
1948 if (err & PARSE_ERR_QUOTE) {
1949 ha_alert("Syntax Error in condition: Unmatched quote.\n");
1950 exit(2);
1951 }
1952
1953 if (err & PARSE_ERR_HEX) {
1954 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
1955 exit(2);
1956 }
1957
1958 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
1959 ha_alert("Error in condition: Line too long.\n");
1960 exit(2);
1961 }
1962
Willy Tarreauc8194c32021-07-16 16:38:58 +02001963 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001964 ha_alert("Error in condition: Too many words.\n");
1965 exit(2);
1966 }
1967
1968 if (err) {
1969 ha_alert("Unhandled error in condition, please report this to the developers.\n");
1970 exit(2);
1971 }
1972
Willy Tarreauc8194c32021-07-16 16:38:58 +02001973 /* remerge all words into a single expression */
1974 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
1975 ;
1976
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001977 result = cfg_eval_condition(args, &errmsg, &errptr);
1978
1979 if (result < 0) {
1980 if (errmsg)
1981 ha_alert("Failed to evaluate condition: %s\n", errmsg);
1982
1983 exit(2);
1984 }
1985
1986 exit(result ? 0 : 1);
1987 }
1988
William Lallemand944e6192018-11-21 15:48:31 +01001989 /* in wait mode, we don't try to read the configuration files */
1990 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001991 char *env_cfgfiles = NULL;
1992 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001993
William Lallemand944e6192018-11-21 15:48:31 +01001994 /* handle cfgfiles that are actually directories */
1995 cfgfiles_expand_directories();
1996
1997 if (LIST_ISEMPTY(&cfg_cfgfiles))
1998 usage(progname);
1999
2000
2001 list_for_each_entry(wl, &cfg_cfgfiles, list) {
2002 int ret;
2003
Christopher Faulet4e366822021-01-12 18:57:38 +01002004 if (env_err == 0) {
2005 if (!memprintf(&env_cfgfiles, "%s%s%s",
2006 (env_cfgfiles ? env_cfgfiles : ""),
2007 (env_cfgfiles ? ";" : ""), wl->s))
2008 env_err = 1;
2009 }
William Lallemand7b302d82019-05-20 11:15:37 +02002010
William Lallemand944e6192018-11-21 15:48:31 +01002011 ret = readcfgfile(wl->s);
2012 if (ret == -1) {
2013 ha_alert("Could not open configuration file %s : %s\n",
2014 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01002015 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002016 exit(1);
2017 }
2018 if (ret & (ERR_ABORT|ERR_FATAL))
2019 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
2020 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01002021 if (err_code & ERR_ABORT) {
2022 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002023 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01002024 }
Willy Tarreauc4382422009-12-06 13:10:44 +01002025 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02002026
William Lallemand944e6192018-11-21 15:48:31 +01002027 /* do not try to resolve arguments nor to spot inconsistencies when
2028 * the configuration contains fatal errors caused by files not found
2029 * or failed memory allocations.
2030 */
2031 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2032 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01002033 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002034 exit(1);
2035 }
Christopher Faulet4e366822021-01-12 18:57:38 +01002036 if (env_err) {
2037 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
2038 exit(1);
2039 }
2040 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
2041 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02002042
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02002043 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002044 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01002045 struct mworker_proc *tmproc;
2046
William Lallemand482f9a92019-04-12 16:15:00 +02002047 setenv("HAPROXY_MWORKER", "1", 1);
2048
William Lallemand16dd1b32018-11-19 18:46:18 +01002049 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
2050
William Lallemand56be0e02022-01-28 21:11:41 +01002051 tmproc = mworker_proc_new();
William Lallemand16dd1b32018-11-19 18:46:18 +01002052 if (!tmproc) {
2053 ha_alert("Cannot allocate process structures.\n");
2054 exit(EXIT_FAILURE);
2055 }
William Lallemand8f7069a2019-04-12 16:09:23 +02002056 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01002057 tmproc->pid = pid;
2058 tmproc->timestamp = start_date.tv_sec;
William Lallemand16dd1b32018-11-19 18:46:18 +01002059 proc_self = tmproc;
2060
Willy Tarreau2b718102021-04-21 07:32:39 +02002061 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01002062 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002063
William Lallemand56be0e02022-01-28 21:11:41 +01002064 tmproc = mworker_proc_new();
Willy Tarreau6185a032021-06-15 08:02:06 +02002065 if (!tmproc) {
2066 ha_alert("Cannot allocate process structures.\n");
2067 exit(EXIT_FAILURE);
2068 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002069 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
William Lallemandce83b4a2018-10-26 14:47:30 +02002070
Willy Tarreau6185a032021-06-15 08:02:06 +02002071 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
2072 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02002073 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002074
2075 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01002076 }
Willy Tarreau53bfac82022-07-22 17:35:49 +02002077
2078 if (global.mode & MODE_MWORKER_WAIT) {
2079 /* in exec mode, there's always exactly one thread. Failure to
2080 * set these ones now will result in nbthread being detected
2081 * automatically.
2082 */
2083 global.nbtgroups = 1;
2084 global.nbthread = 1;
2085 }
2086
William Lallemand944e6192018-11-21 15:48:31 +01002087 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
2088 struct wordlist *it, *c;
2089
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02002090 /* get the info of the children in the env */
2091 if (mworker_env_to_proc_list() < 0) {
2092 exit(EXIT_FAILURE);
2093 }
William Lallemande7361152018-10-26 14:47:36 +02002094
William Lallemand550db6d2018-11-06 17:37:12 +01002095 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02002096
William Lallemand550db6d2018-11-06 17:37:12 +01002097 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02002098 ha_alert("Can't create the master's CLI.\n");
2099 exit(EXIT_FAILURE);
2100 }
William Lallemande7361152018-10-26 14:47:36 +02002101
William Lallemand550db6d2018-11-06 17:37:12 +01002102 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
2103
2104 if (mworker_cli_proxy_new_listener(c->s) < 0) {
2105 ha_alert("Can't create the master's CLI.\n");
2106 exit(EXIT_FAILURE);
2107 }
Willy Tarreau2b718102021-04-21 07:32:39 +02002108 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01002109 free(c->s);
2110 free(c);
2111 }
2112 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002113 }
2114
Eric Salama5ba83352021-03-16 15:11:17 +01002115 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
2116 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
2117 }
2118
Christopher Faulet27c8d202021-10-13 09:50:53 +02002119 /* destroy unreferenced defaults proxies */
2120 proxy_destroy_all_unref_defaults();
2121
William Lallemandb53eb872022-04-21 18:02:53 +02002122 list_for_each_entry(prcf, &pre_check_list, list)
2123 err_code |= prcf->fct();
Willy Tarreaue90904d2021-02-12 14:08:31 +01002124
William Lallemand8b9a2df2022-05-04 14:29:46 +02002125 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2126 ha_alert("Fatal errors found in configuration.\n");
2127 exit(1);
2128 }
2129
Willy Tarreaubb925012009-07-23 13:36:36 +02002130 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02002131 for (px = proxies_list; px; px = px->next) {
2132 struct server *srv;
2133 struct post_proxy_check_fct *ppcf;
2134 struct post_server_check_fct *pscf;
2135
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002136 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002137 continue;
2138
Christopher Fauletc1692962019-08-12 09:51:07 +02002139 list_for_each_entry(pscf, &post_server_check_list, list) {
2140 for (srv = px->srv; srv; srv = srv->next)
2141 err_code |= pscf->fct(srv);
2142 }
2143 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2144 err_code |= ppcf->fct(px);
2145 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002146 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002147 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002148 exit(1);
2149 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002150
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002151 err_code |= pattern_finalize_config();
2152 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2153 ha_alert("Failed to finalize pattern config.\n");
2154 exit(1);
2155 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002156
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002157 if (global.rlimit_memmax_all)
2158 global.rlimit_memmax = global.rlimit_memmax_all;
2159
Willy Tarreaue5733232019-05-22 19:24:06 +02002160#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002161 err_code |= netns_init();
2162 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002163 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002164 exit(1);
2165 }
2166#endif
2167
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002168 /* Apply server states */
2169 apply_server_state();
2170
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002171 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002172 srv_compute_all_admin_states(px);
2173
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002174 /* Apply servers' configured address */
2175 err_code |= srv_init_addr();
2176 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002177 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002178 exit(1);
2179 }
2180
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002181 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2182 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2183 exit(1);
2184 }
2185
Willy Tarreau654726d2021-12-28 15:43:11 +01002186#if defined(HA_HAVE_DUMP_LIBS)
2187 if (global.mode & MODE_DUMP_LIBS) {
2188 qfprintf(stdout, "List of loaded object files:\n");
2189 chunk_reset(&trash);
2190 if (dump_libs(&trash, 0))
2191 printf("%s", trash.area);
2192 }
2193#endif
2194
Willy Tarreau76871a42022-03-08 16:01:40 +01002195 if (global.mode & MODE_DUMP_KWD)
2196 dump_registered_keywords();
2197
Willy Tarreaubaaee002006-06-26 02:48:02 +02002198 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002199 struct peers *pr;
2200 struct proxy *px;
2201
Willy Tarreaubebd2122020-04-15 16:06:11 +02002202 if (warned & WARN_ANY)
2203 qfprintf(stdout, "Warnings were found.\n");
2204
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002205 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002206 if (pr->peers_fe)
2207 break;
2208
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002209 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002210 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002211 break;
2212
Emeric Brunbc5c8212021-08-13 09:32:50 +02002213 if (!px) {
2214 /* We may only have log-forward section */
2215 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002216 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002217 break;
2218 }
2219
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002220 if (pr || px) {
2221 /* At least one peer or one listener has been found */
2222 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002223 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002224 }
2225 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2226 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002227 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002228
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002229 if (global.mode & MODE_DIAG) {
2230 cfg_run_diagnostics();
2231 }
2232
Remi Tricot-Le Breton51944462022-05-16 16:24:31 +02002233#ifdef USE_OPENSSL
William Lallemand3b8bafd2022-07-19 18:13:29 +02002234 /* Initialize the error strings of OpenSSL */
2235 SSL_load_error_strings();
2236
Remi Tricot-Le Breton51944462022-05-16 16:24:31 +02002237 /* Initialize SSL random generator. Must be called before chroot for
2238 * access to /dev/urandom, and before ha_random_boot() which may use
2239 * RAND_bytes().
2240 */
2241 if (!ssl_initialize_random()) {
2242 ha_alert("OpenSSL random data generator initialization failed.\n");
2243 exit(EXIT_FAILURE);
2244 }
2245#endif
2246 ha_random_boot(argv); // the argv pointer brings some kernel-fed entropy
2247
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002248 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002249 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002250
Willy Tarreaue6945732016-12-21 19:57:00 +01002251 list_for_each_entry(pcf, &post_check_list, list) {
2252 err_code |= pcf->fct();
2253 if (err_code & (ERR_ABORT|ERR_FATAL))
2254 exit(1);
2255 }
2256
William Lallemand0a012aa2022-06-21 11:11:50 +02002257 /* set the default maxconn in the master, but let it be rewritable with -n */
2258 if (global.mode & MODE_MWORKER_WAIT)
2259 global.maxconn = DEFAULT_MAXCONN;
2260
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 if (cfg_maxconn > 0)
2262 global.maxconn = cfg_maxconn;
2263
Willy Tarreau4975d142021-03-13 11:00:33 +01002264 if (global.cli_fe)
2265 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002266
2267 if (cfg_peers) {
2268 /* peers also need to bypass global maxconn */
2269 struct peers *p = cfg_peers;
2270
2271 for (p = cfg_peers; p; p = p->next)
2272 if (p->peers_fe)
2273 global.maxsock += p->peers_fe->maxconn;
2274 }
2275
Willy Tarreaud0256482015-01-15 21:45:22 +01002276 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002277 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2278 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2279 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2280 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002281 *
2282 * If memmax is set, then it depends on which values are set. If
2283 * maxsslconn is set, we use memmax to determine how many cleartext
2284 * connections may be added, and set maxconn to the sum of the two.
2285 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2286 * the remaining amount of memory between memmax and the cleartext
2287 * connections. If neither are set, then it is considered that all
2288 * connections are SSL-capable, and maxconn is computed based on this,
2289 * then maxsslconn accordingly. We need to know if SSL is used on the
2290 * frontends, backends, or both, because when it's used on both sides,
2291 * we need twice the value for maxsslconn, but we only count the
2292 * handshake once since it is not performed on the two sides at the
2293 * same time (frontend-side is terminated before backend-side begins).
2294 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002295 * ssl_handshake_cost during its initialization. In any case, if
2296 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2297 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002298 */
Willy Tarreauac350932019-03-01 15:43:14 +01002299 ideal_maxconn = compute_ideal_maxconn();
2300
Willy Tarreaud0256482015-01-15 21:45:22 +01002301 if (!global.rlimit_memmax) {
2302 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002303 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002304 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2305 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2306 }
2307 }
2308#ifdef USE_OPENSSL
2309 else if (!global.maxconn && !global.maxsslconn &&
2310 (global.ssl_used_frontend || global.ssl_used_backend)) {
2311 /* memmax is set, compute everything automatically. Here we want
2312 * to ensure that all SSL connections will be served. We take
2313 * care of the number of sides where SSL is used, and consider
2314 * the worst case : SSL used on both sides and doing a handshake
2315 * simultaneously. Note that we can't have more than maxconn
2316 * handshakes at a time by definition, so for the worst case of
2317 * two SSL conns per connection, we count a single handshake.
2318 */
2319 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2320 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002321 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002322
Willy Tarreau2cb3be72022-05-24 07:43:57 +02002323 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002324 mem -= global.maxzlibmem;
2325 mem = mem * MEM_USABLE_RATIO;
2326
Willy Tarreau304e17e2020-03-10 17:54:54 +01002327 /* Principle: we test once to set maxconn according to the free
2328 * memory. If it results in values the system rejects, we try a
2329 * second time by respecting rlim_fd_max. If it fails again, we
2330 * go back to the initial value and will let the final code
2331 * dealing with rlimit report the error. That's up to 3 attempts.
2332 */
2333 do {
2334 global.maxconn = mem /
2335 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2336 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2337 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002338
Willy Tarreau304e17e2020-03-10 17:54:54 +01002339 if (retried == 1)
2340 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2341 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002342#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002343 if (global.maxconn > SYSTEM_MAXCONN)
2344 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002345#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002346 global.maxsslconn = sides * global.maxconn;
2347
2348 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2349 break;
2350 } while (retried++ < 2);
2351
Willy Tarreaud0256482015-01-15 21:45:22 +01002352 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2353 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2354 global.maxconn, global.maxsslconn);
2355 }
2356 else if (!global.maxsslconn &&
2357 (global.ssl_used_frontend || global.ssl_used_backend)) {
2358 /* memmax and maxconn are known, compute maxsslconn automatically.
2359 * maxsslconn being forced, we don't know how many of it will be
2360 * on each side if both sides are being used. The worst case is
2361 * when all connections use only one SSL instance because
2362 * handshakes may be on two sides at the same time.
2363 */
2364 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2365 int64_t mem = global.rlimit_memmax * 1048576ULL;
2366 int64_t sslmem;
2367
Willy Tarreau8e5b9582022-05-26 08:55:05 +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 Tarreau87b09662015-04-03 00:22:06 +02002372 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002373 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2374 global.maxsslconn = round_2dig(global.maxsslconn);
2375
2376 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002377 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2378 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2379 "without SSL is %d, but %d was found and SSL is in use.\n",
2380 global.rlimit_memmax,
2381 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2382 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002383 exit(1);
2384 }
2385
2386 if (global.maxsslconn > sides * global.maxconn)
2387 global.maxsslconn = sides * global.maxconn;
2388
2389 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2390 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2391 }
2392#endif
2393 else if (!global.maxconn) {
2394 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2395 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2396 int64_t mem = global.rlimit_memmax * 1048576ULL;
2397 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002398 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002399
2400 if (global.ssl_used_frontend || global.ssl_used_backend)
Willy Tarreau8e5b9582022-05-26 08:55:05 +02002401 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002402
2403 mem -= global.maxzlibmem;
2404 mem = mem * MEM_USABLE_RATIO;
2405
2406 clearmem = mem;
2407 if (sides)
2408 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2409
Willy Tarreau304e17e2020-03-10 17:54:54 +01002410 /* Principle: we test once to set maxconn according to the free
2411 * memory. If it results in values the system rejects, we try a
2412 * second time by respecting rlim_fd_max. If it fails again, we
2413 * go back to the initial value and will let the final code
2414 * dealing with rlimit report the error. That's up to 3 attempts.
2415 */
2416 do {
2417 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2418 if (retried == 1)
2419 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2420 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002421#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002422 if (global.maxconn > SYSTEM_MAXCONN)
2423 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002424#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002425
Willy Tarreau304e17e2020-03-10 17:54:54 +01002426 if (clearmem <= 0 || !global.maxconn) {
2427 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2428 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2429 "is %d, but %d was found.\n",
2430 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002431 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002432 global.maxsslconn);
2433 exit(1);
2434 }
2435
2436 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2437 break;
2438 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002439
2440 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2441 if (sides && global.maxsslconn > sides * global.maxconn) {
2442 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2443 "to be limited to %d. Better reduce global.maxsslconn to get more "
2444 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2445 }
2446 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2447 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002448 }
2449
Willy Tarreaua409f302020-03-10 17:08:53 +01002450 global.maxsock = compute_ideal_maxsock(global.maxconn);
2451 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002452 if (!global.maxpipes)
2453 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002454
Olivier Houchard88698d92019-04-16 19:07:22 +02002455 /* update connection pool thresholds */
2456 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2457 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2458
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002459 proxy_adjust_all_maxconn();
2460
Willy Tarreau1db37712007-06-03 17:16:49 +02002461 if (global.tune.maxpollevents <= 0)
2462 global.tune.maxpollevents = MAX_POLL_EVENTS;
2463
Willy Tarreau060a7612021-03-10 11:06:26 +01002464 if (global.tune.runqueue_depth <= 0) {
2465 /* tests on various thread counts from 1 to 64 have shown an
2466 * optimal queue depth following roughly 1/sqrt(threads).
2467 */
2468 int s = my_flsl(global.nbthread);
2469 s += (global.nbthread / s); // roughly twice the sqrt.
2470 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2471 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002472
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002473 if (global.tune.recv_enough == 0)
2474 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2475
Willy Tarreau27a674e2009-08-17 07:23:33 +02002476 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2477 global.tune.maxrewrite = global.tune.bufsize / 2;
2478
Amaury Denoyelle11124302021-06-04 18:22:08 +02002479 usermsgs_clr(NULL);
2480
Willy Tarreaubaaee002006-06-26 02:48:02 +02002481 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2482 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002483 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002484 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2485 }
2486
William Lallemand095ba4c2017-06-01 17:38:50 +02002487 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002488 /* command line daemon mode inhibits foreground and debug modes mode */
2489 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002490 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002491 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002492
2493 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002494
William Lallemand095ba4c2017-06-01 17:38:50 +02002495 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002496 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002497 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002498 }
2499
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002500 if (global.nbthread < 1)
2501 global.nbthread = 1;
2502
Christopher Faulet3ef26392017-08-29 16:46:57 +02002503 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002504 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002505 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002506 exit(1);
2507 }
2508
Christopher Faulet96d44832017-11-14 22:02:30 +01002509 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002510 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002511 exit(1);
2512 }
2513
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002514 /*
2515 * Note: we could register external pollers here.
2516 * Built-in pollers have been registered before main().
2517 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002518
Willy Tarreau43b78992009-01-25 15:42:27 +01002519 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002520 disable_poller("kqueue");
2521
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002522 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2523 disable_poller("evports");
2524
Willy Tarreau43b78992009-01-25 15:42:27 +01002525 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002526 disable_poller("epoll");
2527
Willy Tarreau43b78992009-01-25 15:42:27 +01002528 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002529 disable_poller("poll");
2530
Willy Tarreau43b78992009-01-25 15:42:27 +01002531 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002532 disable_poller("select");
2533
2534 /* Note: we could disable any poller by name here */
2535
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002536 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002537 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002538 fprintf(stderr, "\n");
2539 list_filters(stderr);
2540 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002541
Willy Tarreau4f60f162007-04-08 16:39:58 +02002542 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002543 ha_alert("No polling mechanism available.\n"
Willy Tarreaue5715bf2022-07-09 23:38:46 +02002544 " This may happen when using thread-groups with old pollers (poll/select), or\n"
2545 " it is possible that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
Christopher Faulet767a84b2017-11-24 16:50:31 +01002546 " is too low on this platform to support maxconn and the number of listeners\n"
2547 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2548 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2549 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2550 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2551 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2552 " check build settings using 'haproxy -vv'.\n\n",
2553 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002554 exit(1);
2555 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002556 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2557 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002558 }
2559
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002560 if (!global.node)
2561 global.node = strdup(hostname);
2562
Willy Tarreau02b092f2020-10-07 18:36:54 +02002563 /* stop disabled proxies */
2564 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002565 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002566 stop_proxy(px);
2567 }
2568
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002569 if (!hlua_post_init())
2570 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571}
2572
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002573void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002575 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002576 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002577 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002578 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002579 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002580 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002581 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002582 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002583 struct per_thread_init_fct *tif, *tifb;
2584 struct per_thread_deinit_fct *tdf, *tdfb;
2585 struct per_thread_alloc_fct *taf, *tafb;
2586 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002587 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002588 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002589 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreau65009eb2022-04-27 18:02:54 +02002590 struct pre_check_fct *prcf, *prcfb;
Willy Tarreau226866e2022-04-27 18:07:24 +02002591 struct cfg_postparser *pprs, *pprsb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002592 int cur_fd;
2593
2594 /* At this point the listeners state is weird:
2595 * - most listeners are still bound and referenced in their protocol
2596 * - some might be zombies that are not in their proto anymore, but
2597 * still appear in their proxy's listeners with a valid FD.
2598 * - some might be stopped and still appear in their proxy as FD #-1
2599 * - among all of them, some might be inherited hence shared and we're
2600 * not allowed to pause them or whatever, we must just close them.
2601 * - finally some are not listeners (pipes, logs, stdout, etc) and
2602 * must be left intact.
2603 *
2604 * The safe way to proceed is to unbind (and close) whatever is not yet
2605 * unbound so that no more receiver/listener remains alive. Then close
2606 * remaining listener FDs, which correspond to zombie listeners (those
2607 * belonging to disabled proxies that were in another process).
2608 * objt_listener() would be cleaner here but not converted yet.
2609 */
2610 protocol_unbind_all();
2611
2612 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002613 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002614 continue;
2615
Willy Tarreaua74cb382020-10-15 21:29:49 +02002616 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002617 struct listener *l = fdtab[cur_fd].owner;
2618
2619 BUG_ON(l->state != LI_INIT);
2620 unbind_listener(l);
2621 }
2622 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002623
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002624 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002625 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002626 /* build a list of unique uri_auths */
2627 if (!ua)
2628 ua = p->uri_auth;
2629 else {
2630 /* check if p->uri_auth is unique */
2631 for (uap = ua; uap; uap=uap->next)
2632 if (uap == p->uri_auth)
2633 break;
2634
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002635 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002636 /* add it, if it is */
2637 p->uri_auth->next = ua;
2638 ua = p->uri_auth;
2639 }
William Lallemand0f99e342011-10-12 17:50:54 +02002640 }
2641
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002642 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002644 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002645 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002646
Christopher Faulet27c8d202021-10-13 09:50:53 +02002647 /* destroy all referenced defaults proxies */
2648 proxy_destroy_all_unref_defaults();
2649
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002650 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002651 struct stat_scope *scope, *scopep;
2652
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002653 uap = ua;
2654 ua = ua->next;
2655
Willy Tarreaua534fea2008-08-03 12:19:50 +02002656 free(uap->uri_prefix);
2657 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002658 free(uap->node);
2659 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002660
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002661 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002662 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002663
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002664 scope = uap->scope;
2665 while (scope) {
2666 scopep = scope;
2667 scope = scope->next;
2668
2669 free(scopep->px_id);
2670 free(scopep);
2671 }
2672
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002673 free(uap);
2674 }
2675
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002676 userlist_free(userlist);
2677
David Carlier834cb2e2015-09-25 12:02:25 +01002678 cfg_unregister_sections();
2679
Christopher Faulet0132d062017-07-26 15:33:35 +02002680 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002681
Willy Tarreau05554e62016-12-21 20:46:26 +01002682 list_for_each_entry(pdf, &post_deinit_list, list)
2683 pdf->fct();
2684
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002685 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002686 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002687 ha_free(&global.chroot);
Frédéric Lécaille372508c2022-05-06 08:53:16 +02002688 ha_free(&global.cluster_secret);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002689 ha_free(&global.pidfile);
2690 ha_free(&global.node);
2691 ha_free(&global.desc);
2692 ha_free(&oldpids);
2693 ha_free(&old_argv);
2694 ha_free(&localpeer);
2695 ha_free(&global.server_state_base);
2696 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002697 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002698 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002699
William Lallemand0f99e342011-10-12 17:50:54 +02002700 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002701 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002702 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002703 free(log);
2704 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002705 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002706 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002707 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002708 free(wl);
2709 }
2710
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002711 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2712 if (bol->must_free)
2713 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002714 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002715 free(bol);
2716 }
2717
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002718 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002719 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002720 free(pxdf);
2721 }
2722
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002723 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002724 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002725 free(pdf);
2726 }
2727
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002728 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002729 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002730 free(srvdf);
2731 }
2732
Tim Duesterhusfc854942020-09-10 19:46:42 +02002733 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002734 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002735 free(pcf);
2736 }
2737
Tim Duesterhus34bef072020-07-04 11:49:50 +02002738 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002739 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002740 free(pscf);
2741 }
2742
Tim Duesterhus53508d62020-09-10 19:46:40 +02002743 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002744 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002745 free(ppcf);
2746 }
2747
Willy Tarreau65009eb2022-04-27 18:02:54 +02002748 list_for_each_entry_safe(prcf, prcfb, &pre_check_list, list) {
2749 LIST_DELETE(&prcf->list);
2750 free(prcf);
2751 }
2752
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002753 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002754 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002755 free(tif);
2756 }
2757
2758 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002759 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002760 free(tdf);
2761 }
2762
2763 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002764 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002765 free(taf);
2766 }
2767
2768 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002769 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002770 free(tff);
2771 }
2772
Willy Tarreau226866e2022-04-27 18:07:24 +02002773 list_for_each_entry_safe(pprs, pprsb, &postparsers, list) {
2774 LIST_DELETE(&pprs->list);
2775 free(pprs);
2776 }
2777
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002778 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002779 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002780 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002781} /* end deinit() */
2782
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002783__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002784{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002785 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002786 deinit();
2787 exit(status);
2788}
William Lallemand72160322018-11-06 17:37:16 +01002789
Willy Tarreau918ff602011-07-25 16:33:49 +02002790/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002791void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002792{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002793 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002794
Willy Tarreau55542642021-10-08 09:33:24 +02002795 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002796 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002797 wake_expired_tasks();
2798
William Lallemand1aab50b2018-06-07 09:46:01 +02002799 /* check if we caught some signals and process them in the
2800 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002801 if (signal_queue_len && tid == 0) {
2802 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002803 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002804 }
2805
2806 /* Process a few tasks */
2807 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002808
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002809 /* also stop if we failed to cleanly stop all tasks */
2810 if (killed > 1)
2811 break;
2812
Matthias Wirtheea152e2022-09-09 10:21:00 +02002813 /* expire immediately if events or signals are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002814 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002815 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002816 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002817 else {
Willy Tarreaue7475c82022-06-20 09:23:24 +02002818 _HA_ATOMIC_OR(&th_ctx->flags, TH_FL_SLEEPING);
Willy Tarreaudce4ad72022-06-22 15:38:38 +02002819 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_NOTIFIED);
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002820 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002821 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002822 activity[tid].wake_tasks++;
Willy Tarreaue7475c82022-06-20 09:23:24 +02002823 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_SLEEPING);
Matthias Wirtheea152e2022-09-09 10:21:00 +02002824 } else if (signal_queue_len) {
2825 /* this check is required after setting TH_FL_SLEEPING to avoid
2826 * a race with wakeup on signals using wake_threads() */
2827 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_SLEEPING);
Olivier Houchard79321b92018-07-26 17:55:11 +02002828 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002829 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002830 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002831
Willy Tarreau4f46a352020-03-23 09:27:28 +01002832 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002833 int i;
2834
2835 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002836 /* stop muxes before acknowledging stopping */
Willy Tarreau24cfc9f2022-07-04 14:07:29 +02002837 if (!(tg_ctx->stopping_threads & ti->ltid_bit)) {
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002838 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2839 wake = 1;
2840 }
2841
Willy Tarreauef422ce2022-06-28 19:29:29 +02002842 if (_HA_ATOMIC_OR_FETCH(&tg_ctx->stopping_threads, ti->ltid_bit) == ti->ltid_bit &&
2843 _HA_ATOMIC_OR_FETCH(&stopping_tgroup_mask, tg->tgid_bit) == tg->tgid_bit) {
2844 /* first one to detect it, notify all threads that stopping was just set */
2845 for (i = 0; i < global.nbthread; i++) {
2846 if (ha_thread_info[i].tg->threads_enabled &
2847 ha_thread_info[i].ltid_bit &
2848 ~_HA_ATOMIC_LOAD(&ha_thread_info[i].tg_ctx->stopping_threads))
Willy Tarreaud6455742020-05-13 14:30:25 +02002849 wake_thread(i);
Willy Tarreauef422ce2022-06-28 19:29:29 +02002850 }
Willy Tarreaud6455742020-05-13 14:30:25 +02002851 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002852 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002853
2854 /* stop when there's nothing left to do */
2855 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreauef422ce2022-06-28 19:29:29 +02002856 (_HA_ATOMIC_LOAD(&stopping_tgroup_mask) & all_tgroups_mask) == all_tgroups_mask) {
2857 /* check that all threads are aware of the stopping status */
2858 for (i = 0; i < global.nbtgroups; i++)
Willy Tarreauf34a3fa2022-07-06 10:13:05 +02002859 if ((_HA_ATOMIC_LOAD(&ha_tgroup_ctx[i].stopping_threads) & ha_tgroup_info[i].threads_enabled) !=
2860 ha_tgroup_info[i].threads_enabled)
Willy Tarreauef422ce2022-06-28 19:29:29 +02002861 break;
2862#ifdef USE_THREAD
2863 if (i == global.nbtgroups) {
2864 /* all are OK, let's wake them all and stop */
2865 for (i = 0; i < global.nbthread; i++)
2866 if (i != tid && ha_thread_info[i].tg->threads_enabled & ha_thread_info[i].ltid_bit)
2867 wake_thread(i);
2868 break;
2869 }
2870#endif
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002871 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002872 }
2873
Willy Tarreauc49ba522019-12-11 08:12:23 +01002874 /* If we have to sleep, measure how long */
2875 next = wake ? TICK_ETERNITY : next_timer_expiry();
2876
Willy Tarreau58b458d2008-06-29 22:40:23 +02002877 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002878 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002879
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002880 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002881 }
2882}
2883
Christopher Faulet1d17c102017-08-29 15:38:48 +02002884static void *run_thread_poll_loop(void *data)
2885{
Willy Tarreau082b6282019-05-22 14:42:12 +02002886 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002887 struct per_thread_init_fct *ptif;
2888 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002889 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002890 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002891 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2892 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002893
Willy Tarreau43ab05b2021-09-28 09:43:11 +02002894 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02002895 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02002896 clock_set_local_source();
Willy Tarreau91e6df02019-05-03 17:21:18 +02002897
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002898 /* Now, initialize one thread init at a time. This is better since
2899 * some init code is a bit tricky and may release global resources
2900 * after reallocating them locally. This will also ensure there is
2901 * no race on file descriptors allocation.
2902 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002903#ifdef USE_THREAD
2904 pthread_mutex_lock(&init_mutex);
2905#endif
2906 /* The first thread must set the number of threads left */
2907 if (!init_left)
2908 init_left = global.nbthread;
2909 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002910
Willy Tarreau55542642021-10-08 09:33:24 +02002911 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002912
Willy Tarreau082b6282019-05-22 14:42:12 +02002913 /* per-thread alloc calls performed here are not allowed to snoop on
2914 * other threads, so they are free to initialize at their own rhythm
2915 * as long as they act as if they were alone. None of them may rely
2916 * on resources initialized by the other ones.
2917 */
2918 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2919 if (!ptaf->fct()) {
2920 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002921#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002922 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002923#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02002924 exit(1);
2925 }
2926 }
2927
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002928 /* per-thread init calls performed here are not allowed to snoop on
2929 * other threads, so they are free to initialize at their own rhythm
2930 * as long as they act as if they were alone.
2931 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002932 list_for_each_entry(ptif, &per_thread_init_list, list) {
2933 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002934 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002935#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002936 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002937#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002938 exit(1);
2939 }
2940 }
2941
Willy Tarreau71092822019-06-10 09:51:04 +02002942 /* enabling protocols will result in fd_insert() calls to be performed,
2943 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002944 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002945 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002946 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002947 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002948
Willy Tarreau34a150c2019-06-11 09:16:41 +02002949#ifdef USE_THREAD
2950 pthread_cond_broadcast(&init_cond);
2951 pthread_mutex_unlock(&init_mutex);
2952
2953 /* now wait for other threads to finish starting */
2954 pthread_mutex_lock(&init_mutex);
2955 while (init_left)
2956 pthread_cond_wait(&init_cond, &init_mutex);
2957 pthread_mutex_unlock(&init_mutex);
2958#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002959
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002960#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2961 /* Let's refrain from using setuid executables. This way the impact of
2962 * an eventual vulnerability in a library remains limited. It may
2963 * impact external checks but who cares about them anyway ? In the
2964 * worst case it's possible to disable the option. Obviously we do this
2965 * in workers only. We can't hard-fail on this one as it really is
2966 * implementation dependent though we're interested in feedback, hence
2967 * the warning.
2968 */
2969 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2970 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002971 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 +01002972 ha_warning("Failed to disable setuid, please report to developers with detailed "
2973 "information about your operating system. You can silence this warning "
2974 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2975 }
2976 }
2977#endif
2978
Willy Tarreaud96f1122019-12-03 07:07:36 +01002979#if defined(RLIMIT_NPROC)
2980 /* all threads have started, it's now time to prevent any new thread
2981 * or process from starting. Obviously we do this in workers only. We
2982 * can't hard-fail on this one as it really is implementation dependent
2983 * though we're interested in feedback, hence the warning.
2984 */
2985 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2986 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2987 static int warn_fail;
2988
Willy Tarreau18515722021-04-06 11:57:41 +02002989 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002990 ha_warning("Failed to disable forks, please report to developers with detailed "
2991 "information about your operating system. You can silence this warning "
2992 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2993 }
2994 }
2995#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002996 run_poll_loop();
2997
2998 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2999 ptdf->fct();
3000
Willy Tarreau082b6282019-05-22 14:42:12 +02003001 list_for_each_entry(ptff, &per_thread_free_list, list)
3002 ptff->fct();
3003
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003004#ifdef USE_THREAD
Willy Tarreau291f6ff2022-07-04 13:36:16 +02003005 if (!_HA_ATOMIC_AND_FETCH(&ha_tgroup_info[ti->tgid-1].threads_enabled, ~ti->ltid_bit))
Willy Tarreaucce203a2022-06-24 15:55:11 +02003006 _HA_ATOMIC_AND(&all_tgroups_mask, ~tg->tgid_bit);
Willy Tarreauad92fdf2022-07-06 10:17:21 +02003007 if (!_HA_ATOMIC_AND_FETCH(&tg_ctx->stopping_threads, ~ti->ltid_bit))
3008 _HA_ATOMIC_AND(&stopping_tgroup_mask, ~tg->tgid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003009 if (tid > 0)
3010 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02003011#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003012 return NULL;
3013}
Christopher Faulet1d17c102017-08-29 15:38:48 +02003014
William Dauchyf9af9d72019-11-17 15:47:16 +01003015/* set uid/gid depending on global settings */
3016static void set_identity(const char *program_name)
3017{
3018 if (global.gid) {
3019 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
3020 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
3021 " without 'uid'/'user' is generally useless.\n", program_name);
3022
3023 if (setgid(global.gid) == -1) {
3024 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
3025 protocol_unbind_all();
3026 exit(1);
3027 }
3028 }
3029
3030 if (global.uid && setuid(global.uid) == -1) {
3031 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
3032 protocol_unbind_all();
3033 exit(1);
3034 }
3035}
3036
Willy Tarreaubaaee002006-06-26 02:48:02 +02003037int main(int argc, char **argv)
3038{
3039 int err, retry;
3040 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02003041 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02003042 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
3043
Willy Tarreau41afd902022-07-21 09:55:22 +02003044 /* Catch broken toolchains */
3045 if (sizeof(long) != sizeof(void *) || (intovf + 0x7FFFFFFF >= intovf)) {
3046 const char *msg;
3047
3048 if (sizeof(long) != sizeof(void *))
3049 /* Apparently MingW64 was not made for us and can also break openssl */
3050 msg = "The compiler this program was built with uses unsupported integral type sizes.\n"
3051 "Most likely it follows the unsupported LLP64 model. Never try to link HAProxy\n"
3052 "against libraries built with that compiler either! Please only use a compiler\n"
3053 "producing ILP32 or LP64 programs for both programs and libraries.\n";
3054 else if (intovf + 0x7FFFFFFF >= intovf)
3055 /* Catch forced CFLAGS that miss 2-complement integer overflow */
3056 msg = "The source code was miscompiled by the compiler, which usually indicates that\n"
3057 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
3058 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
3059 "and INSTALL files to decide on the best way to pass your local build options.\n";
3060 else
3061 msg = "Bug in the compiler bug detection code, please report it to developers!\n";
3062
Willy Tarreau1335da32021-07-14 17:54:01 +02003063 fprintf(stderr,
3064 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
Willy Tarreau41afd902022-07-21 09:55:22 +02003065 "%s"
3066 "\nBuild options :"
Willy Tarreau1335da32021-07-14 17:54:01 +02003067#ifdef BUILD_TARGET
Willy Tarreau41afd902022-07-21 09:55:22 +02003068 "\n TARGET = " BUILD_TARGET
Willy Tarreau1335da32021-07-14 17:54:01 +02003069#endif
3070#ifdef BUILD_CPU
Willy Tarreau41afd902022-07-21 09:55:22 +02003071 "\n CPU = " BUILD_CPU
Willy Tarreau1335da32021-07-14 17:54:01 +02003072#endif
3073#ifdef BUILD_CC
Willy Tarreau41afd902022-07-21 09:55:22 +02003074 "\n CC = " BUILD_CC
Willy Tarreau1335da32021-07-14 17:54:01 +02003075#endif
3076#ifdef BUILD_CFLAGS
Willy Tarreau41afd902022-07-21 09:55:22 +02003077 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau1335da32021-07-14 17:54:01 +02003078#endif
3079#ifdef BUILD_OPTIONS
Willy Tarreau41afd902022-07-21 09:55:22 +02003080 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau1335da32021-07-14 17:54:01 +02003081#endif
3082#ifdef BUILD_DEBUG
Willy Tarreau41afd902022-07-21 09:55:22 +02003083 "\n DEBUG = " BUILD_DEBUG
Willy Tarreau1335da32021-07-14 17:54:01 +02003084#endif
Willy Tarreau41afd902022-07-21 09:55:22 +02003085 "\n\n", msg);
3086
Willy Tarreau1335da32021-07-14 17:54:01 +02003087 return 1;
3088 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089
Olivier Houchard5fa300d2018-02-03 15:15:21 +01003090 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003091
Willy Tarreaubf696402019-03-01 10:09:28 +01003092 /* take a copy of initial limits before we possibly change them */
3093 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02003094
3095 if (limit.rlim_max == RLIM_INFINITY)
3096 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01003097 rlim_fd_cur_at_boot = limit.rlim_cur;
3098 rlim_fd_max_at_boot = limit.rlim_max;
3099
Willy Tarreau5794fb02018-11-25 18:43:29 +01003100 /* process all initcalls in order of potential dependency */
3101 RUN_INITCALLS(STG_PREPARE);
3102 RUN_INITCALLS(STG_LOCK);
Willy Tarreau3ebe4d92022-02-18 14:51:49 +01003103 RUN_INITCALLS(STG_REGISTER);
Willy Tarreau34527d52022-02-17 17:45:58 +01003104
3105 /* now's time to initialize early boot variables */
3106 init_early(argc, argv);
3107
Willy Tarreau18f96d02022-02-23 17:25:00 +01003108 /* handles argument parsing */
3109 init_args(argc, argv);
3110
Willy Tarreau5794fb02018-11-25 18:43:29 +01003111 RUN_INITCALLS(STG_ALLOC);
3112 RUN_INITCALLS(STG_POOL);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003113 RUN_INITCALLS(STG_INIT);
3114
Willy Tarreau34527d52022-02-17 17:45:58 +01003115 /* this is the late init where the config is parsed */
Emeric Bruncf20bf12010-10-22 16:06:11 +02003116 init(argc, argv);
Willy Tarreau34527d52022-02-17 17:45:58 +01003117
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003118 signal_register_fct(SIGQUIT, dump, SIGQUIT);
3119 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
3120 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02003121 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122
Willy Tarreaue437c442010-03-17 18:02:46 +01003123 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
3124 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
3125 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003127 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003128
Willy Tarreaudc23a922011-02-16 11:10:36 +01003129 /* ulimits */
3130 if (!global.rlimit_nofile)
3131 global.rlimit_nofile = global.maxsock;
3132
3133 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01003134 limit.rlim_cur = global.rlimit_nofile;
3135 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
3136
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003137 if ((global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit) ||
3138 setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02003139 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003140 if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
3141 limit.rlim_cur = global.fd_hard_limit;
3142
William Dauchy0fec3ab2019-10-27 20:08:11 +01003143 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3144 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
3145 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003146 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003147 }
3148 else {
3149 /* try to set it to the max possible at least */
3150 limit.rlim_cur = limit.rlim_max;
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003151 if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
3152 limit.rlim_cur = global.fd_hard_limit;
3153
William Dauchy0fec3ab2019-10-27 20:08:11 +01003154 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
3155 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02003156
William Dauchya5194602020-03-28 19:29:58 +01003157 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003158 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
3159 global.rlimit_nofile = limit.rlim_cur;
3160 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01003161 }
3162 }
3163
3164 if (global.rlimit_memmax) {
3165 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01003166 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01003167#ifdef RLIMIT_AS
3168 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003169 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3170 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3171 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003172 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003173 }
3174 else
William Dauchya5194602020-03-28 19:29:58 +01003175 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003176 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003177 }
3178#else
3179 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003180 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3181 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3182 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003183 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003184 }
3185 else
William Dauchya5194602020-03-28 19:29:58 +01003186 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003187 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003188 }
3189#endif
3190 }
3191
William Lallemandf82afbb2022-01-07 18:19:42 +01003192 /* Try to get the listeners FD from the previous process using
3193 * _getsocks on the stat socket, it must never been done in wait mode
3194 * and check mode
3195 */
3196 if (old_unixsocket &&
3197 !(global.mode & (MODE_MWORKER_WAIT|MODE_CHECK|MODE_CHECK_CONDITION))) {
William Lallemand85b0bd92017-06-01 17:38:53 +02003198 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02003199 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003200 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02003201 if (!(global.mode & MODE_MWORKER))
3202 exit(1);
3203 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02003204 }
3205 }
William Lallemand85b0bd92017-06-01 17:38:53 +02003206
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 /* We will loop at most 100 times with 10 ms delay each time.
3208 * That's at most 1 second. We only send a signal to old pids
3209 * if we cannot grab at least one port.
3210 */
3211 retry = MAX_START_RETRIES;
3212 err = ERR_NONE;
3213 while (retry >= 0) {
3214 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003215 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003216 /* exit the loop on no error or fatal error */
3217 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003219 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003220 break;
3221
3222 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3223 * listening sockets. So on those platforms, it would be wiser to
3224 * simply send SIGUSR1, which will not be undoable.
3225 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003226 if (tell_old_pids(SIGTTOU) == 0) {
3227 /* no need to wait if we can't contact old pids */
3228 retry = 0;
3229 continue;
3230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003231 /* give some time to old processes to stop listening */
3232 w.tv_sec = 0;
3233 w.tv_usec = 10*1000;
3234 select(0, NULL, NULL, NULL, &w);
3235 retry--;
3236 }
3237
Willy Tarreaue91bff22020-09-02 11:11:43 +02003238 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003239 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003240 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003241 if (retry != MAX_START_RETRIES && nb_oldpids) {
3242 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003244 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003245 exit(1);
3246 }
3247
William Lallemand944e6192018-11-21 15:48:31 +01003248 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003249 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003250 /* Note: we don't have to send anything to the old pids because we
3251 * never stopped them. */
3252 exit(1);
3253 }
3254
Willy Tarreaue91bff22020-09-02 11:11:43 +02003255 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003256 * the previous process gave us, we don't need them anymore
3257 */
Willy Tarreaub5101162022-01-28 18:28:18 +01003258 sock_drop_unused_old_sockets();
Willy Tarreaudd815982007-10-16 12:25:14 +02003259
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003261 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3262 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263
Willy Tarreaubaaee002006-06-26 02:48:02 +02003264 /* MODE_QUIET can inhibit alerts and warnings below this line */
3265
PiBa-NL149a81a2017-12-25 21:03:31 +01003266 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3267 /* either stdin/out/err are already closed or should stay as they are. */
3268 if ((global.mode & MODE_DAEMON)) {
3269 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3270 global.mode &= ~MODE_VERBOSE;
3271 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3272 }
3273 } else {
3274 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3275 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003276 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003277 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278 }
3279
3280 /* open log & pid files before the chroot */
William Lallemand7b820a62022-02-14 09:02:14 +01003281 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) &&
3282 !(global.mode & MODE_MWORKER_WAIT) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 unlink(global.pidfile);
3284 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3285 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003286 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003287 if (nb_oldpids)
3288 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003289 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 exit(1);
3291 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003292 }
3293
Willy Tarreaub38651a2007-03-24 17:24:39 +01003294 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003295 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3296 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003297 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003298 exit(1);
3299 }
3300
Jackie Tapia749f74c2020-07-22 18:59:40 -05003301 /* If the user is not root, we'll still let them try the configuration
3302 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003303 */
3304 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003305 ha_warning("[%s.main()] Some options which require full privileges"
3306 " might not work well.\n"
3307 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003308
William Lallemand095ba4c2017-06-01 17:38:50 +02003309 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3310
3311 /* chroot if needed */
3312 if (global.chroot != NULL) {
3313 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003314 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003315 if (nb_oldpids)
3316 tell_old_pids(SIGTTIN);
3317 protocol_unbind_all();
3318 exit(1);
3319 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003320 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003321 }
3322
William Lallemand944e6192018-11-21 15:48:31 +01003323 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003324 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003325
William Lallemand27edc4b2019-05-07 17:49:33 +02003326 /* send a SIGTERM to workers who have a too high reloads number */
3327 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3328 mworker_kill_max_reloads(SIGTERM);
3329
Willy Tarreaubaaee002006-06-26 02:48:02 +02003330 /* Note that any error at this stage will be fatal because we will not
3331 * be able to restart the old pids.
3332 */
3333
William Dauchyf9af9d72019-11-17 15:47:16 +01003334 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3335 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003336
Willy Tarreaubaaee002006-06-26 02:48:02 +02003337 /* check ulimits */
3338 limit.rlim_cur = limit.rlim_max = 0;
3339 getrlimit(RLIMIT_NOFILE, &limit);
3340 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003341 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3342 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3343 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3344 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3345 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003346 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003347 }
3348 else
3349 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003350 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003351 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3352 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353 }
3354
William Lallemand944e6192018-11-21 15:48:31 +01003355 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003357 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003358 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359
William Lallemand095ba4c2017-06-01 17:38:50 +02003360 /*
3361 * if daemon + mworker: must fork here to let a master
3362 * process live in background before forking children
3363 */
William Lallemand73b85e72017-06-01 17:38:51 +02003364
3365 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3366 && (global.mode & MODE_MWORKER)
3367 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003368 ret = fork();
3369 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003370 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003371 protocol_unbind_all();
3372 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003373 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003374 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003375 } else /* change the process group ID in the child (master process) */
3376 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003377 }
William Lallemande20b6a62017-06-01 17:38:55 +02003378
William Lallemande20b6a62017-06-01 17:38:55 +02003379
William Lallemanddeed7802017-11-06 11:00:04 +01003380 /* if in master-worker mode, write the PID of the father */
3381 if (global.mode & MODE_MWORKER) {
3382 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003383 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003384 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003385 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003386 }
3387
Willy Tarreaubaaee002006-06-26 02:48:02 +02003388 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003389 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003390 if (global.mode & MODE_MWORKER)
3391 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003392
3393 ret = fork();
3394 if (ret < 0) {
3395 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3396 protocol_unbind_all();
3397 exit(1); /* there has been an error */
3398 }
3399 else if (ret == 0) { /* child breaks here */
Willy Tarreau3c032f22021-07-21 10:17:02 +02003400 /* This one must not be exported, it's internal! */
3401 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003402 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003403 }
3404 else { /* parent here */
3405 in_parent = 1;
3406
William Lallemand944e6192018-11-21 15:48:31 +01003407 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3408 char pidstr[100];
3409 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003410 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003411 }
3412 if (global.mode & MODE_MWORKER) {
3413 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003414
William Lallemand5d71a6b2021-11-09 15:25:31 +01003415 ha_notice("New worker (%d) forked\n", ret);
William Lallemand944e6192018-11-21 15:48:31 +01003416 /* find the right mworker_proc */
3417 list_for_each_entry(child, &proc_list, list) {
William Lallemandd4835a92022-07-21 00:52:43 +02003418 if (child->reloads == 0 &&
3419 child->options & PROC_O_TYPE_WORKER &&
3420 child->pid == -1) {
William Lallemand944e6192018-11-21 15:48:31 +01003421 child->timestamp = now.tv_sec;
3422 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003423 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003424 break;
3425 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003426 }
3427 }
William Lallemand944e6192018-11-21 15:48:31 +01003428 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003429
William Lallemand944e6192018-11-21 15:48:31 +01003430 } else {
3431 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003432 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003433 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003434
3435#ifdef USE_CPU_AFFINITY
Willy Tarreau5b093412022-07-08 09:38:30 +02003436 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 +02003437
David CARLIERdf91cbd2022-01-06 18:53:50 +00003438#if defined(CPUSET_USE_CPUSET) || defined(__DragonFly__)
Willy Tarreau5b093412022-07-08 09:38:30 +02003439 struct hap_cpuset *set = &cpu_map[0].proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003440 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
David CARLIERdf91cbd2022-01-06 18:53:50 +00003441#elif defined(__FreeBSD__)
Willy Tarreau5b093412022-07-08 09:38:30 +02003442 struct hap_cpuset *set = &cpu_map[0].proc;
David CARLIERdf91cbd2022-01-06 18:53:50 +00003443 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003444#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003445 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003446#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003447 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003448 if (pidfd >= 0) {
3449 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3450 close(pidfd);
3451 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003452
3453 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003454 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003455
Willy Tarreaud67ff342021-06-15 07:58:09 +02003456 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003457 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
William Lallemandfab0fdc2021-11-09 18:01:22 +01003458 master = 1;
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003459
3460 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3461 (global.mode & MODE_DAEMON)) {
3462 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003463 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3464 stdio_quiet(-1);
3465
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003466 global.mode &= ~MODE_VERBOSE;
3467 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003468 }
3469
William Lallemandfab0fdc2021-11-09 18:01:22 +01003470 if (global.mode & MODE_MWORKER_WAIT) {
3471 /* only the wait mode handles the master CLI */
3472 mworker_loop();
3473 } else {
3474
William Lallemanda46a99e2022-07-07 14:00:36 +02003475#if defined(USE_SYSTEMD)
3476 if (global.tune.options & GTUNE_USE_SYSTEMD)
3477 sd_notifyf(0, "READY=1\nMAINPID=%lu\nSTATUS=Ready.\n", (unsigned long)getpid());
3478#endif
William Lallemandfab0fdc2021-11-09 18:01:22 +01003479 /* if not in wait mode, reload in wait mode to free the memory */
William Lallemand836bda22021-11-09 18:16:47 +01003480 ha_notice("Loading success.\n");
William Lallemand68836742021-11-10 10:49:06 +01003481 proc_self->failedreloads = 0; /* reset the number of failure */
William Lallemandfab0fdc2021-11-09 18:01:22 +01003482 mworker_reexec_waitmode();
3483 }
William Lallemand1499b9b2017-06-07 15:04:47 +02003484 /* should never get there */
3485 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003486 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003487#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003488 ssl_free_dh();
3489#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003490 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003491 }
3492
William Lallemandcb11fd22017-06-01 17:38:52 +02003493 /* child must never use the atexit function */
3494 atexit_flag = 0;
3495
William Lallemandbc193052018-09-11 10:06:26 +02003496 /* close useless master sockets */
3497 if (global.mode & MODE_MWORKER) {
3498 struct mworker_proc *child, *it;
3499 master = 0;
3500
William Lallemand309dc9a2018-10-26 14:47:45 +02003501 mworker_cli_proxy_stop();
3502
William Lallemandbc193052018-09-11 10:06:26 +02003503 /* free proc struct of other processes */
3504 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003505 /* close the FD of the master side for all
3506 * workers, we don't need to close the worker
3507 * side of other workers since it's done with
3508 * the bind_proc */
William Lallemand7e018782022-01-28 21:56:24 +01003509 if (child->ipc_fd[0] >= 0) {
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003510 close(child->ipc_fd[0]);
William Lallemand7e018782022-01-28 21:56:24 +01003511 child->ipc_fd[0] = -1;
3512 }
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003513 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandd4835a92022-07-21 00:52:43 +02003514 child->reloads == 0 &&
3515 child->pid == -1) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003516 /* keep this struct if this is our pid */
3517 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003518 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003519 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003520 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003521 mworker_free_child(child);
3522 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003523 }
3524 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003525
William Lallemande1340412017-12-28 16:09:36 +01003526 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3527 devnullfd = open("/dev/null", O_RDWR, 0);
3528 if (devnullfd < 0) {
3529 ha_alert("Cannot open /dev/null\n");
3530 exit(EXIT_FAILURE);
3531 }
3532 }
3533
William Lallemand095ba4c2017-06-01 17:38:50 +02003534 /* Must chroot and setgid/setuid in the children */
3535 /* chroot if needed */
3536 if (global.chroot != NULL) {
3537 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003538 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003539 if (nb_oldpids)
3540 tell_old_pids(SIGTTIN);
3541 protocol_unbind_all();
3542 exit(1);
3543 }
3544 }
3545
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003546 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003547 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003548
William Lallemand7f80eb22017-05-26 18:19:55 +02003549 /* pass through every cli socket, and check if it's bound to
3550 * the current process and if it exposes listeners sockets.
3551 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3552 * */
3553
Willy Tarreau4975d142021-03-13 11:00:33 +01003554 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003555 struct bind_conf *bind_conf;
3556
Willy Tarreau4975d142021-03-13 11:00:33 +01003557 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003558 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003559 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3560 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003561 }
3562 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003563 }
3564
William Lallemand2e8fad92018-11-13 16:18:23 +01003565 /*
3566 * This is only done in daemon mode because we might want the
3567 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3568 * we should now close the 3 first FDs to ensure that we can
3569 * detach from the TTY. We MUST NOT do it in other cases since
3570 * it would have already be done, and 0-2 would have been
3571 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003573 if ((global.mode & MODE_DAEMON) &&
3574 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003576 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003577 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3579 }
3580 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003581 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3582 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003583 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003584 }
3585
William Dauchye039f262019-11-17 15:47:15 +01003586 /* try our best to re-enable core dumps depending on system capabilities.
3587 * What is addressed here :
3588 * - remove file size limits
3589 * - remove core size limits
3590 * - mark the process dumpable again if it lost it due to user/group
3591 */
3592 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3593 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3594
3595#if defined(RLIMIT_FSIZE)
3596 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3597 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3598 ha_alert("[%s.main()] Failed to set the raise the maximum "
3599 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003600 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003601 }
3602 else
3603 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003604 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003605 }
3606#endif
3607
3608#if defined(RLIMIT_CORE)
3609 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3610 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3611 ha_alert("[%s.main()] Failed to set the raise the core "
3612 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003613 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003614 }
3615 else
3616 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003617 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003618 }
3619#endif
3620
3621#if defined(USE_PRCTL)
3622 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3623 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3624 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003625#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003626 {
3627 int traceable = PROC_TRACE_CTL_ENABLE;
3628 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3629 ha_warning("[%s.main()] Failed to set the traceable flag, "
3630 "no core will be dumped.\n", argv[0]);
3631 }
William Dauchye039f262019-11-17 15:47:15 +01003632#endif
3633 }
3634
Christopher Faulete3a5e352017-10-24 13:53:54 +02003635 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003636 reset_usermsgs_ctx();
3637
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003638 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003639 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003640
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003641 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003642 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003643
3644 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003645 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003646
3647 /* wait for all threads to terminate */
3648 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003649
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003650 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651}
3652
Willy Tarreaubaaee002006-06-26 02:48:02 +02003653/*
3654 * Local variables:
3655 * c-indent-level: 8
3656 * c-basic-offset: 8
3657 * End:
3658 */