blob: f86e3b5739a38a0b8fac81de2ebaf4c4a4455cee [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();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100685#if defined(USE_SYSTEMD)
686 if (global.tune.options & GTUNE_USE_SYSTEMD)
687 sd_notify(0, "RELOADING=1");
688#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200689 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
690
William Lallemand55a921c2022-01-28 21:17:30 +0100691 mworker_cleanup_proc();
William Lallemandbc193052018-09-11 10:06:26 +0200692 mworker_proc_list_to_env(); /* put the children description in the env */
693
William Lallemandc4810b82021-11-18 10:51:30 +0100694 /* ensure that we close correctly every listeners before reexecuting */
695 mworker_cleanlisteners();
696
William Lallemand7c756a82018-11-26 11:53:40 +0100697 /* during the reload we must ensure that every FDs that can't be
698 * reuse (ie those that are not referenced in the proc_list)
699 * are closed or they will leak. */
700
701 /* close the listeners FD */
702 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200703
William Lallemand67e371e2021-11-25 10:03:44 +0100704 if (fdtab)
705 deinit_pollers();
William Lallemandefd95472021-11-26 14:43:57 +0100706
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500707#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200708 /* close random device FDs */
709 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100710#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100711
Willy Tarreau8dca1952019-03-01 10:21:55 +0100712 /* restore the initial FD limits */
713 limit.rlim_cur = rlim_fd_cur_at_boot;
714 limit.rlim_max = rlim_fd_max_at_boot;
715 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
716 getrlimit(RLIMIT_NOFILE, &limit);
717 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
718 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
719 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
720 }
721
William Lallemand73b85e72017-06-01 17:38:51 +0200722 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200723 while (old_argv[old_argc])
724 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200725
William Lallemand85b0bd92017-06-01 17:38:53 +0200726 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200727 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200728 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200729 if (next_argv == NULL)
730 goto alloc_error;
731
William Lallemand00417412020-06-05 14:08:41 +0200732 /* copy the program name */
733 next_argv[next_argc++] = old_argv[0];
734
735 /* insert the new options just after argv[0] in case we have a -- */
736
William Lallemandbefab9e2021-11-25 00:49:19 +0100737 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
738 /* add -sf <PID>* to argv */
739 if (mworker_child_nb() > 0) {
740 struct mworker_proc *child;
William Lallemand3f128872019-04-01 11:29:59 +0200741
William Lallemandbefab9e2021-11-25 00:49:19 +0100742 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200743
William Lallemandbefab9e2021-11-25 00:49:19 +0100744 list_for_each_entry(child, &proc_list, list) {
745 if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
746 current_child = child;
William Lallemand2be557f2021-11-24 18:45:37 +0100747
William Lallemandbefab9e2021-11-25 00:49:19 +0100748 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
749 continue;
750 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
751 goto alloc_error;
752 msg = NULL;
753 }
William Lallemand73b85e72017-06-01 17:38:51 +0200754 }
William Lallemand2be557f2021-11-24 18:45:37 +0100755
756 if (current_child) {
757 /* add the -x option with the socketpair of the current worker */
758 next_argv[next_argc++] = "-x";
759 if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
760 goto alloc_error;
761 msg = NULL;
762 }
William Lallemand85b0bd92017-06-01 17:38:53 +0200763 }
764
William Lallemand00417412020-06-05 14:08:41 +0200765 /* copy the previous options */
766 for (i = 1; i < old_argc; i++)
767 next_argv[next_argc++] = old_argv[i];
768
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200769 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100770 execvp(next_argv[0], next_argv);
Christopher Faulet767a84b2017-11-24 16:50:31 +0100771 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100772 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100773 return;
774
William Lallemand73b85e72017-06-01 17:38:51 +0200775alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100776 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800777 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200778 return;
779}
780
William Lallemandfab0fdc2021-11-09 18:01:22 +0100781/* reexec haproxy in waitmode */
782static void mworker_reexec_waitmode()
783{
784 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
785 mworker_reexec();
786}
787
788/* reload haproxy and emit a warning */
789void mworker_reload()
790{
William Lallemandad221f42021-11-09 18:43:59 +0100791 struct mworker_proc *child;
William Lallemandefd95472021-11-26 14:43:57 +0100792 struct per_thread_deinit_fct *ptdf;
William Lallemandad221f42021-11-09 18:43:59 +0100793
William Lallemand836bda22021-11-09 18:16:47 +0100794 ha_notice("Reloading HAProxy\n");
William Lallemandad221f42021-11-09 18:43:59 +0100795
William Lallemandefd95472021-11-26 14:43:57 +0100796 /* close the poller FD and the thread waker pipe FD */
797 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
798 ptdf->fct();
799
William Lallemandad221f42021-11-09 18:43:59 +0100800 /* increment the number of reloads */
801 list_for_each_entry(child, &proc_list, list) {
802 child->reloads++;
803 }
804
William Lallemandfab0fdc2021-11-09 18:01:22 +0100805 mworker_reexec();
806}
807
William Lallemandb3f2be32018-09-11 10:06:18 +0200808static void mworker_loop()
809{
810
811#if defined(USE_SYSTEMD)
812 if (global.tune.options & GTUNE_USE_SYSTEMD)
813 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
814#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200815 /* Busy polling makes no sense in the master :-) */
816 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200817
William Lallemandbc193052018-09-11 10:06:26 +0200818
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100819 signal_unregister(SIGTTIN);
820 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100821 signal_unregister(SIGUSR1);
822 signal_unregister(SIGHUP);
823 signal_unregister(SIGQUIT);
824
William Lallemandb3f2be32018-09-11 10:06:18 +0200825 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
826 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100827 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
828 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200829 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
830 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
831 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
832 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
833
834 mworker_unblock_signals();
William Lallemand27f3fa52018-12-06 14:05:20 +0100835 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200836
William Lallemandbc193052018-09-11 10:06:26 +0200837 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
838 some SIGCHLD were lost */
839
William Lallemandb3f2be32018-09-11 10:06:18 +0200840 global.nbthread = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200841
William Lallemand2672eb92018-12-14 15:52:39 +0100842#ifdef USE_THREAD
843 tid_bit = 1;
844 all_threads_mask = 1;
845#endif
846
William Lallemandb3f2be32018-09-11 10:06:18 +0200847 jobs++; /* this is the "master" job, we want to take care of the
848 signals even if there is no listener so the poll loop don't
849 leave */
850
851 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200852 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200853}
William Lallemandcb11fd22017-06-01 17:38:52 +0200854
855/*
856 * Reexec the process in failure mode, instead of exiting
857 */
858void reexec_on_failure()
859{
William Lallemand68836742021-11-10 10:49:06 +0100860 struct mworker_proc *child;
861
William Lallemandcb11fd22017-06-01 17:38:52 +0200862 if (!atexit_flag)
863 return;
William Lallemand68836742021-11-10 10:49:06 +0100864
865 /* get the info of the children in the env */
866 if (mworker_env_to_proc_list() < 0) {
867 exit(EXIT_FAILURE);
868 }
869
870 /* increment the number of failed reloads */
871 list_for_each_entry(child, &proc_list, list) {
872 child->failedreloads++;
873 }
874
Willy Tarreaue08acae2022-01-28 18:40:06 +0100875 /* do not keep unused FDs retrieved from the previous process */
876 sock_drop_unused_old_sockets();
877
William Lallemandfab0fdc2021-11-09 18:01:22 +0100878 usermsgs_clr(NULL);
William Lallemand836bda22021-11-09 18:16:47 +0100879 ha_warning("Loading failure!\n");
William Lallemandfab0fdc2021-11-09 18:01:22 +0100880 mworker_reexec_waitmode();
William Lallemandcb11fd22017-06-01 17:38:52 +0200881}
William Lallemand73b85e72017-06-01 17:38:51 +0200882
883
884/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200885 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
886 * a signal zero to all subscribers. This means that it's as easy as
887 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100889static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200890{
891 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200892 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100893 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200894}
895
896/*
897 * upon SIGTTOU, we pause everything
898 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100899static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900{
Willy Tarreau775e0012020-09-24 16:36:26 +0200901 if (protocol_pause_all() & ERR_FATAL) {
902 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200903 ha_warning("%s", msg);
904 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200905 soft_stop();
906 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100907 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908}
909
910/*
911 * upon SIGTTIN, let's have a soft stop.
912 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100913static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914{
Willy Tarreau775e0012020-09-24 16:36:26 +0200915 if (protocol_resume_all() & ERR_FATAL) {
916 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 +0200917 ha_warning("%s", msg);
918 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200919 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920}
921
922/*
923 * this function dumps every server's state when the process receives SIGHUP.
924 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100925static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100927 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200928
Christopher Faulet767a84b2017-11-24 16:50:31 +0100929 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 while (p) {
931 struct server *s = p->srv;
932
933 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
934 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100935 chunk_printf(&trash,
936 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
937 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200938 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200939 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200940 ha_warning("%s\n", trash.area);
941 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942 s = s->next;
943 }
944
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200945 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
946 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100947 chunk_printf(&trash,
948 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
949 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200950 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 +0200951 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100952 chunk_printf(&trash,
953 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
954 p->id,
955 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200956 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 +0200957 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100958 chunk_printf(&trash,
959 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
960 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
961 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200962 p->feconn, p->beconn, p->totpend, p->queue.length, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200964 ha_warning("%s\n", trash.area);
965 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200966
967 p = p->next;
968 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200969}
970
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100971static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200972{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200973 /* dump memory usage then free everything possible */
974 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100975 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200976}
977
William Lallemande1340412017-12-28 16:09:36 +0100978/*
979 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
980 * If <fd> < 0, it opens /dev/null and use it to dup
981 *
982 * In the case of chrooting, you have to open /dev/null before the chroot, and
983 * pass the <fd> to this function
984 */
985static void stdio_quiet(int fd)
986{
987 if (fd < 0)
988 fd = open("/dev/null", O_RDWR, 0);
989
990 if (fd > -1) {
991 fclose(stdin);
992 fclose(stdout);
993 fclose(stderr);
994
995 dup2(fd, 0);
996 dup2(fd, 1);
997 dup2(fd, 2);
998 if (fd > 2)
999 close(fd);
1000 return;
1001 }
1002
1003 ha_alert("Cannot open /dev/null\n");
1004 exit(EXIT_FAILURE);
1005}
1006
1007
Joseph Herlant03420902018-11-15 10:41:50 -08001008/* This function checks if cfg_cfgfiles contains directories.
1009 * If it finds one, it adds all the files (and only files) it contains
1010 * in cfg_cfgfiles in place of the directory (and removes the directory).
1011 * It adds the files in lexical order.
1012 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001013 * It doesn't add files with name starting with '.'
1014 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001015static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001016{
1017 struct wordlist *wl, *wlb;
1018 char *err = NULL;
1019
1020 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1021 struct stat file_stat;
1022 struct dirent **dir_entries = NULL;
1023 int dir_entries_nb;
1024 int dir_entries_it;
1025
1026 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001027 ha_alert("Cannot open configuration file/directory %s : %s\n",
1028 wl->s,
1029 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001030 exit(1);
1031 }
1032
1033 if (!S_ISDIR(file_stat.st_mode))
1034 continue;
1035
1036 /* from this point wl->s is a directory */
1037
1038 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1039 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001040 ha_alert("Cannot open configuration directory %s : %s\n",
1041 wl->s,
1042 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001043 exit(1);
1044 }
1045
1046 /* for each element in the directory wl->s */
1047 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1048 struct dirent *dir_entry = dir_entries[dir_entries_it];
1049 char *filename = NULL;
1050 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1051
1052 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001053 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001054 */
1055 if (dir_entry->d_name[0] == '.' ||
1056 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1057 goto next_dir_entry;
1058
1059 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001060 ha_alert("Cannot load configuration files %s : out of memory.\n",
1061 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001062 exit(1);
1063 }
1064
1065 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001066 ha_alert("Cannot open configuration file %s : %s\n",
1067 wl->s,
1068 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001069 exit(1);
1070 }
1071
1072 /* don't add anything else than regular file in cfg_cfgfiles
1073 * this way we avoid loops
1074 */
1075 if (!S_ISREG(file_stat.st_mode))
1076 goto next_dir_entry;
1077
1078 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001079 ha_alert("Cannot load configuration files %s : %s\n",
1080 filename,
1081 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001082 exit(1);
1083 }
1084
1085next_dir_entry:
1086 free(filename);
1087 free(dir_entry);
1088 }
1089
1090 free(dir_entries);
1091
1092 /* remove the current directory (wl) from cfg_cfgfiles */
1093 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001094 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001095 free(wl);
1096 }
1097
1098 free(err);
1099}
1100
Willy Tarreaubaaee002006-06-26 02:48:02 +02001101/*
William Lallemand73b85e72017-06-01 17:38:51 +02001102 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001103 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001104 * Return an allocated copy of argv
1105 */
1106
1107static char **copy_argv(int argc, char **argv)
1108{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001109 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001110
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001111 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001112 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001113 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001114 return NULL;
1115 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001116 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001117
William Lallemanddf6c5a82020-06-04 17:40:23 +02001118 /* first copy argv[0] */
1119 *newargv++ = *argv++;
1120 argc--;
1121
1122 while (argc > 0) {
1123 if (**argv != '-') {
1124 /* non options are copied but will fail in the argument parser */
1125 *newargv++ = *argv++;
1126 argc--;
1127
1128 } else {
1129 char *flag;
1130
1131 flag = *argv + 1;
1132
1133 if (flag[0] == '-' && flag[1] == 0) {
1134 /* "--\0" copy every arguments till the end of argv */
1135 *newargv++ = *argv++;
1136 argc--;
1137
1138 while (argc > 0) {
1139 *newargv++ = *argv++;
1140 argc--;
1141 }
1142 } else {
1143 switch (*flag) {
1144 case 's':
1145 /* -sf / -st and their parameters are ignored */
1146 if (flag[1] == 'f' || flag[1] == 't') {
1147 argc--;
1148 argv++;
1149 /* The list can't contain a negative value since the only
1150 way to know the end of this list is by looking for the
1151 next option or the end of the options */
1152 while (argc > 0 && argv[0][0] != '-') {
1153 argc--;
1154 argv++;
1155 }
William Lallemand398da622020-09-02 16:12:23 +02001156 } else {
1157 argc--;
1158 argv++;
1159
William Lallemanddf6c5a82020-06-04 17:40:23 +02001160 }
1161 break;
1162
1163 case 'x':
1164 /* this option and its parameter are ignored */
1165 argc--;
1166 argv++;
1167 if (argc > 0) {
1168 argc--;
1169 argv++;
1170 }
1171 break;
1172
1173 case 'C':
1174 case 'n':
1175 case 'm':
1176 case 'N':
1177 case 'L':
1178 case 'f':
1179 case 'p':
1180 case 'S':
1181 /* these options have only 1 parameter which must be copied and can start with a '-' */
1182 *newargv++ = *argv++;
1183 argc--;
1184 if (argc == 0)
1185 goto error;
1186 *newargv++ = *argv++;
1187 argc--;
1188 break;
1189 default:
1190 /* for other options just copy them without parameters, this is also done
1191 * for options like "--foo", but this will fail in the argument parser.
1192 * */
1193 *newargv++ = *argv++;
1194 argc--;
1195 break;
1196 }
William Lallemand73b85e72017-06-01 17:38:51 +02001197 }
1198 }
William Lallemand73b85e72017-06-01 17:38:51 +02001199 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001200
William Lallemanddf6c5a82020-06-04 17:40:23 +02001201 return retargv;
1202
1203error:
1204 free(retargv);
1205 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001206}
1207
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001208
1209/* Performs basic random seed initialization. The main issue with this is that
1210 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1211 * which means that there will only be 4 billion possible random sequences once
1212 * srandom() is called, regardless of the internal state. Not calling it is
1213 * even worse as we'll always produce the same randoms sequences. What we do
1214 * here is to create an initial sequence from various entropy sources, hash it
1215 * using SHA1 and keep the resulting 160 bits available globally.
1216 *
1217 * We initialize the current process with the first 32 bits before starting the
1218 * polling loop, where all this will be changed to have process specific and
1219 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001220 *
1221 * Before starting threads, it's still possible to call random() as srandom()
1222 * is initialized from this, but after threads and/or processes are started,
1223 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001224 */
1225static void ha_random_boot(char *const *argv)
1226{
1227 unsigned char message[256];
1228 unsigned char *m = message;
1229 struct timeval tv;
1230 blk_SHA_CTX ctx;
1231 unsigned long l;
1232 int fd;
1233 int i;
1234
1235 /* start with current time as pseudo-random seed */
1236 gettimeofday(&tv, NULL);
1237 write_u32(m, tv.tv_sec); m += 4;
1238 write_u32(m, tv.tv_usec); m += 4;
1239
1240 /* PID and PPID add some OS-based randomness */
1241 write_u16(m, getpid()); m += 2;
1242 write_u16(m, getppid()); m += 2;
1243
1244 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1245 fd = open("/dev/urandom", O_RDONLY);
1246 if (fd >= 0) {
1247 i = read(fd, m, 20);
1248 if (i > 0)
1249 m += i;
1250 close(fd);
1251 }
1252
1253 /* take up to 160 bits bytes from openssl (non-blocking) */
1254#ifdef USE_OPENSSL
1255 if (RAND_bytes(m, 20) == 1)
1256 m += 20;
1257#endif
1258
1259 /* take 160 bits from existing random in case it was already initialized */
1260 for (i = 0; i < 5; i++) {
1261 write_u32(m, random());
1262 m += 4;
1263 }
1264
1265 /* stack address (benefit form operating system's ASLR) */
1266 l = (unsigned long)&m;
1267 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1268
1269 /* argv address (benefit form operating system's ASLR) */
1270 l = (unsigned long)&argv;
1271 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1272
1273 /* use tv_usec again after all the operations above */
1274 gettimeofday(&tv, NULL);
1275 write_u32(m, tv.tv_usec); m += 4;
1276
1277 /*
1278 * At this point, ~84-92 bytes have been used
1279 */
1280
1281 /* finish with the hostname */
1282 strncpy((char *)m, hostname, message + sizeof(message) - m);
1283 m += strlen(hostname);
1284
1285 /* total message length */
1286 l = m - message;
1287
1288 memset(&ctx, 0, sizeof(ctx));
1289 blk_SHA1_Init(&ctx);
1290 blk_SHA1_Update(&ctx, message, l);
1291 blk_SHA1_Final(boot_seed, &ctx);
1292
1293 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001294 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001295}
1296
Willy Tarreau5a023f02019-03-01 14:19:31 +01001297/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1298 * setting, and returns it. It may return -1 meaning "unlimited" if some
1299 * unlimited proxies have been found and the global.maxconn value is not yet
1300 * set. It may also return a value greater than maxconn if it's not yet set.
1301 * Note that a value of zero means there is no need for pipes. -1 is never
1302 * returned if global.maxconn is valid.
1303 */
1304static int compute_ideal_maxpipes()
1305{
1306 struct proxy *cur;
1307 int nbfe = 0, nbbe = 0;
1308 int unlimited = 0;
1309 int pipes;
1310 int max;
1311
1312 for (cur = proxies_list; cur; cur = cur->next) {
1313 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1314 if (cur->cap & PR_CAP_FE) {
1315 max = cur->maxconn;
1316 nbfe += max;
1317 if (!max) {
1318 unlimited = 1;
1319 break;
1320 }
1321 }
1322 if (cur->cap & PR_CAP_BE) {
1323 max = cur->fullconn ? cur->fullconn : global.maxconn;
1324 nbbe += max;
1325 if (!max) {
1326 unlimited = 1;
1327 break;
1328 }
1329 }
1330 }
1331 }
1332
1333 pipes = MAX(nbfe, nbbe);
1334 if (global.maxconn) {
1335 if (pipes > global.maxconn || unlimited)
1336 pipes = global.maxconn;
1337 } else if (unlimited) {
1338 pipes = -1;
1339 }
1340
1341 return pipes >= 4 ? pipes / 4 : pipes;
1342}
1343
Willy Tarreauac350932019-03-01 15:43:14 +01001344/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1345 * rlimits and computes an ideal maxconn. It's meant to be called only when
1346 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001347 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1348 * default 100) is returned as it is expected that it will even run on tight
1349 * environments, and will maintain compatibility with previous packages that
1350 * used to rely on this value as the default one. The system will emit a
1351 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001352 */
1353static int compute_ideal_maxconn()
1354{
1355 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1356 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1357 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001358 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001359 int maxconn;
1360
1361 /* we have to take into account these elements :
1362 * - number of engine_fds, which inflates the number of FD needed per
1363 * connection by this number.
1364 * - number of pipes per connection on average : for the unlimited
1365 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1366 * fixed value of 2*pipes.
1367 * - two FDs per connection
1368 */
1369
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02001370 if (global.fd_hard_limit && remain > global.fd_hard_limit)
1371 remain = global.fd_hard_limit;
1372
Willy Tarreauac350932019-03-01 15:43:14 +01001373 /* subtract listeners and checks */
1374 remain -= global.maxsock;
1375
Willy Tarreau3f200852019-03-14 19:13:17 +01001376 /* one epoll_fd/kqueue_fd per thread */
1377 remain -= global.nbthread;
1378
1379 /* one wake-up pipe (2 fd) per thread */
1380 remain -= 2 * global.nbthread;
1381
Willy Tarreauac350932019-03-01 15:43:14 +01001382 /* Fixed pipes values : we only subtract them if they're not larger
1383 * than the remaining FDs because pipes are optional.
1384 */
1385 if (pipes >= 0 && pipes * 2 < remain)
1386 remain -= pipes * 2;
1387
1388 if (pipes < 0) {
1389 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1390 * = maxconn * (2 + 0.5 + engine_fds)
1391 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1392 */
1393 maxconn = 2 * remain / (5 + 2 * engine_fds);
1394 } else {
1395 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1396 * = maxconn * (2 + engine_fds)
1397 */
1398 maxconn = remain / (2 + engine_fds);
1399 }
1400
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001401 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001402}
1403
Willy Tarreaua409f302020-03-10 17:08:53 +01001404/* computes the estimated maxsock value for the given maxconn based on the
1405 * possibly set global.maxpipes and existing partial global.maxsock. It may
1406 * temporarily change global.maxconn for the time needed to propagate the
1407 * computations, and will reset it.
1408 */
1409static int compute_ideal_maxsock(int maxconn)
1410{
1411 int maxpipes = global.maxpipes;
1412 int maxsock = global.maxsock;
1413
1414
1415 if (!maxpipes) {
1416 int old_maxconn = global.maxconn;
1417
1418 global.maxconn = maxconn;
1419 maxpipes = compute_ideal_maxpipes();
1420 global.maxconn = old_maxconn;
1421 }
1422
1423 maxsock += maxconn * 2; /* each connection needs two sockets */
1424 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1425 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1426 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1427
1428 /* compute fd used by async engines */
1429 if (global.ssl_used_async_engines) {
1430 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1431
1432 maxsock += maxconn * sides * global.ssl_used_async_engines;
1433 }
1434 return maxsock;
1435}
1436
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001437/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001438 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1439 * value is accepted, non-zero otherwise. This is used to determine if an
1440 * automatic limit may be applied or not. When it is not, the caller knows that
1441 * the highest we can do is the rlim_max at boot. In case of error, we return
1442 * that the setting is possible, so that we defer the error processing to the
1443 * final stage in charge of enforcing this.
1444 */
1445static int check_if_maxsock_permitted(int maxsock)
1446{
1447 struct rlimit orig_limit, test_limit;
1448 int ret;
1449
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02001450 if (global.fd_hard_limit && maxsock > global.fd_hard_limit)
1451 return 0;
1452
Willy Tarreau304e17e2020-03-10 17:54:54 +01001453 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1454 return 1;
1455
1456 /* don't go further if we can't even set to what we have */
1457 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1458 return 1;
1459
1460 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1461 test_limit.rlim_cur = test_limit.rlim_max;
1462 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1463
1464 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1465 return 1;
1466
1467 return ret == 0;
1468}
1469
Willy Tarreau34527d52022-02-17 17:45:58 +01001470/* This performs th every basic early initialization at the end of the PREPARE
1471 * init stage. It may only assume that list heads are initialized, but not that
1472 * anything else is correct. It will initialize a number of variables that
1473 * depend on command line and will pre-parse the command line. If it fails, it
1474 * directly exits.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001475 */
Willy Tarreau34527d52022-02-17 17:45:58 +01001476static void init_early(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001477{
Kevinm48936af2010-12-22 16:08:21 +00001478 char *progname;
Willy Tarreau34527d52022-02-17 17:45:58 +01001479 char *tmp;
1480 int len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481
Willy Tarreau34527d52022-02-17 17:45:58 +01001482 /* First, let's initialize most global variables */
1483 totalconn = actconn = listeners = stopping = 0;
1484 killed = pid = 0;
1485
1486 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
1487 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Christopher Faulete3a5e352017-10-24 13:53:54 +02001488 global.mode = MODE_STARTING;
William Lallemand73b85e72017-06-01 17:38:51 +02001489
Willy Tarreau34527d52022-02-17 17:45:58 +01001490 /* if we were in mworker mode, we should restart in mworker mode */
1491 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1492 global.mode |= MODE_MWORKER;
David du Colombier7af46052012-05-16 14:16:48 +02001493
Willy Tarreau34527d52022-02-17 17:45:58 +01001494 /* initialize date, time, and pid */
1495 tzset();
1496 clock_init_process_date();
1497 start_date = now;
1498 pid = getpid();
1499
1500 /* Set local host name and adjust some environment variables.
1501 * NB: POSIX does not make it mandatory for gethostname() to
1502 * NULL-terminate the string in case of truncation, and at least
1503 * FreeBSD appears not to do it.
Emeric Brun2b920a12010-09-23 18:30:22 +02001504 */
1505 memset(hostname, 0, sizeof(hostname));
1506 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001507
Willy Tarreau34527d52022-02-17 17:45:58 +01001508 /* preset some environment variables */
1509 localpeer = strdup(hostname);
1510 if (!localpeer || setenv("HAPROXY_LOCALPEER", localpeer, 1) < 0) {
Dragan Dosen4f014152020-06-18 16:56:47 +02001511 ha_alert("Cannot allocate memory for local peer.\n");
1512 exit(EXIT_FAILURE);
1513 }
Emeric Brun2b920a12010-09-23 18:30:22 +02001514
Willy Tarreau34527d52022-02-17 17:45:58 +01001515 /* Some CPU affinity stuff may have to be initialized */
1516#ifdef USE_CPU_AFFINITY
1517 {
1518 int i;
1519 ha_cpuset_zero(&cpu_map.proc);
1520 ha_cpuset_zero(&cpu_map.proc_t1);
1521 for (i = 0; i < MAX_THREADS; ++i) {
1522 ha_cpuset_zero(&cpu_map.thread[i]);
1523 }
1524 }
1525#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001526
Willy Tarreau34527d52022-02-17 17:45:58 +01001527 /* extract the program name from argv[0], it will be used for the logs
1528 * and error messages.
1529 */
1530 progname = *argv;
1531 while ((tmp = strchr(progname, '/')) != NULL)
1532 progname = tmp + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001533
Willy Tarreau34527d52022-02-17 17:45:58 +01001534 len = strlen(progname);
1535 progname = strdup(progname);
1536 if (!progname) {
1537 ha_alert("Cannot allocate memory for log_tag.\n");
1538 exit(EXIT_FAILURE);
1539 }
Willy Tarreau84310e22014-02-14 11:59:04 +01001540
Willy Tarreau34527d52022-02-17 17:45:58 +01001541 chunk_initlen(&global.log_tag, progname, len, len);
1542}
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001543
Willy Tarreau392524d2022-02-17 18:10:36 +01001544/* handles program arguments. Very minimal parsing is performed, variables are
1545 * fed with some values, and lists are completed with other ones. In case of
1546 * error, it will exit.
Willy Tarreau34527d52022-02-17 17:45:58 +01001547 */
Willy Tarreau392524d2022-02-17 18:10:36 +01001548static void init_args(int argc, char **argv)
Willy Tarreau34527d52022-02-17 17:45:58 +01001549{
Willy Tarreau34527d52022-02-17 17:45:58 +01001550 char *progname = global.log_tag.area;
Willy Tarreau392524d2022-02-17 18:10:36 +01001551 char *err_msg = NULL;
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001552
Willy Tarreau34527d52022-02-17 17:45:58 +01001553 /* pre-fill in the global tuning options before we let the cmdline
1554 * change them.
1555 */
Willy Tarreau43b78992009-01-25 15:42:27 +01001556 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001557#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001558 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001560#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001561 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001563#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001564 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001565#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001566#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001567 global.tune.options |= GTUNE_USE_EVPORTS;
1568#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001569#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001570 global.tune.options |= GTUNE_USE_SPLICE;
1571#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001572#if defined(USE_GETADDRINFO)
1573 global.tune.options |= GTUNE_USE_GAI;
1574#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001575#if defined(SO_REUSEPORT)
1576 global.tune.options |= GTUNE_USE_REUSEPORT;
1577#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001578#ifdef USE_THREAD
1579 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1580#endif
William Dauchya5194602020-03-28 19:29:58 +01001581 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001582
Willy Tarreau392524d2022-02-17 18:10:36 +01001583 /* keep a copy of original arguments for the master process */
1584 old_argv = copy_argv(argc, argv);
1585 if (!old_argv) {
1586 ha_alert("failed to copy argv.\n");
1587 exit(EXIT_FAILURE);
1588 }
1589
1590 /* skip program name and start */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591 argc--; argv++;
1592 while (argc > 0) {
1593 char *flag;
1594
1595 if (**argv == '-') {
1596 flag = *argv+1;
1597
1598 /* 1 arg */
1599 if (*flag == 'v') {
1600 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001601 if (flag[1] == 'v') /* -vv */
1602 display_build_opts();
Tim Duesterhus77b3db02022-04-27 00:08:11 +02001603 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001604 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001605#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001606 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001607 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001608#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001609#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001610 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001611 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001612#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001613#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001614 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001615 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001616#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001617#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001618 else if (*flag == 'd' && flag[1] == 'v')
1619 global.tune.options &= ~GTUNE_USE_EVPORTS;
1620#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001621#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001622 else if (*flag == 'd' && flag[1] == 'S')
1623 global.tune.options &= ~GTUNE_USE_SPLICE;
1624#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001625#if defined(USE_GETADDRINFO)
1626 else if (*flag == 'd' && flag[1] == 'G')
1627 global.tune.options &= ~GTUNE_USE_GAI;
1628#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001629#if defined(SO_REUSEPORT)
1630 else if (*flag == 'd' && flag[1] == 'R')
1631 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1632#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001633 else if (*flag == 'd' && flag[1] == 'V')
1634 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635 else if (*flag == 'V')
1636 arg_mode |= MODE_VERBOSE;
1637 else if (*flag == 'd' && flag[1] == 'b')
1638 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001639 else if (*flag == 'd' && flag[1] == 'D')
1640 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001641 else if (*flag == 'd' && flag[1] == 'W')
1642 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreauef301b72022-02-23 14:15:18 +01001643 else if (*flag == 'd' && flag[1] == 'M') {
Willy Tarreau1408b1f2022-02-18 18:54:40 +01001644 int ret = pool_parse_debugging(flag + 2, &err_msg);
1645
1646 if (ret <= -1) {
1647 if (ret < -1)
1648 ha_alert("-dM: %s\n", err_msg);
1649 else
1650 printf("%s\n", err_msg);
1651 ha_free(&err_msg);
1652 exit(ret < -1 ? EXIT_FAILURE : 0);
1653 } else if (ret == 0) {
1654 ha_warning("-dM: %s\n", err_msg);
1655 ha_free(&err_msg);
1656 }
Willy Tarreauef301b72022-02-23 14:15:18 +01001657 }
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001658 else if (*flag == 'd' && flag[1] == 'r')
1659 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreau654726d2021-12-28 15:43:11 +01001660#if defined(HA_HAVE_DUMP_LIBS)
1661 else if (*flag == 'd' && flag[1] == 'L')
1662 arg_mode |= MODE_DUMP_LIBS;
1663#endif
Willy Tarreau76871a42022-03-08 16:01:40 +01001664 else if (*flag == 'd' && flag[1] == 'K') {
1665 arg_mode |= MODE_DUMP_KWD;
1666 kwd_dump = flag + 2;
1667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001668 else if (*flag == 'd')
1669 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001670 else if (*flag == 'c' && flag[1] == 'c') {
1671 arg_mode |= MODE_CHECK_CONDITION;
1672 argv++;
1673 argc--;
1674 check_condition = *argv;
1675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676 else if (*flag == 'c')
1677 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001678 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001679 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001680 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001681 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001682#if defined(USE_SYSTEMD)
1683 global.tune.options |= GTUNE_USE_SYSTEMD;
1684#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001685 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 +01001686 usage(progname);
1687#endif
1688 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001689 else if (*flag == 'W')
1690 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001691 else if (*flag == 'q')
1692 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001693 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001694 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001695 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001696 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001697 }
William Lallemand4fc09692017-06-19 16:37:19 +02001698 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001699 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001700 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001701
Olivier Houchardf73629d2017-04-05 22:33:04 +02001702 argv++;
1703 argc--;
1704 }
William Lallemande7361152018-10-26 14:47:36 +02001705 else if (*flag == 'S') {
1706 struct wordlist *c;
1707
William Lallemanda6b32492020-06-04 23:49:20 +02001708 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001709 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1710 usage(progname);
1711 }
1712 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1713 ha_alert("Cannot allocate memory\n");
1714 exit(EXIT_FAILURE);
1715 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001716 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001717
1718 argv++;
1719 argc--;
1720 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001721 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1722 /* list of pids to finish ('f') or terminate ('t') */
1723
1724 if (flag[1] == 'f')
1725 oldpids_sig = SIGUSR1; /* finish then exit */
1726 else
1727 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001728 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001729 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001730 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1731 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001732 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001733 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001734 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001735 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001736 errno = 0;
1737 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1738 if (errno) {
1739 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1740 flag,
1741 *argv, strerror(errno));
1742 exit(1);
1743 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001744 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001745 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001746 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1747 flag, endptr);
1748 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001749 }
Chris Lane236062f2018-02-05 23:15:44 +00001750 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001751 if (oldpids[nb_oldpids] <= 0)
1752 usage(progname);
1753 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754 }
1755 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001756 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1757 /* now that's a cfgfile list */
1758 argv++; argc--;
1759 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001760 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001761 ha_alert("Cannot load configuration file/directory %s : %s\n",
1762 *argv,
1763 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001764 exit(1);
1765 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001766 argv++; argc--;
1767 }
1768 break;
1769 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770 else { /* >=2 args */
1771 argv++; argc--;
1772 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001773 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001774
1775 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001776 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001777 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001778 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001779 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001780 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001781 free(localpeer);
1782 if ((localpeer = strdup(*argv)) == NULL) {
1783 ha_alert("Cannot allocate memory for local peer.\n");
1784 exit(EXIT_FAILURE);
1785 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001786 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001787 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001788 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001789 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001790 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001791 ha_alert("Cannot load configuration file/directory %s : %s\n",
1792 *argv,
1793 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001794 exit(1);
1795 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001796 break;
Willy Tarreau392524d2022-02-17 18:10:36 +01001797 case 'p' :
1798 free(global.pidfile);
1799 if ((global.pidfile = strdup(*argv)) == NULL) {
1800 ha_alert("Cannot allocate memory for pidfile.\n");
1801 exit(EXIT_FAILURE);
1802 }
1803 break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001804 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001805 }
1806 }
1807 }
1808 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001809 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001810 argv++; argc--;
1811 }
Willy Tarreau392524d2022-02-17 18:10:36 +01001812 free(err_msg);
1813}
1814
Willy Tarreau76871a42022-03-08 16:01:40 +01001815/* call the various keyword dump functions based on the comma-delimited list of
1816 * classes in kwd_dump.
1817 */
1818static void dump_registered_keywords(void)
1819{
1820 char *end;
1821 int all __maybe_unused = 0;
1822
1823 for (; kwd_dump && *kwd_dump; kwd_dump = end) {
1824 end = strchr(kwd_dump, ',');
1825 if (end)
1826 *(end++) = 0;
1827
1828 if (strcmp(kwd_dump, "help") == 0) {
1829 printf("# List of supported keyword classes:\n");
1830 printf("all: list all keywords\n");
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001831 printf("acl: ACL keywords\n");
Willy Tarreauca1acd62022-03-29 15:02:44 +02001832 printf("cfg: configuration keywords\n");
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001833 printf("cli: CLI keywords\n");
Willy Tarreau29d799d2022-03-29 16:59:49 +02001834 printf("cnv: sample converter keywords\n");
Willy Tarreau3b65e142022-03-29 15:03:09 +02001835 printf("flt: filter names\n");
Willy Tarreauf78813f2022-03-29 16:51:29 +02001836 printf("smp: sample fetch functions\n");
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001837 printf("svc: service names\n");
Willy Tarreau76871a42022-03-08 16:01:40 +01001838 continue;
1839 }
1840 else if (strcmp(kwd_dump, "all") == 0) {
1841 all = 1;
1842 }
Willy Tarreauca1acd62022-03-29 15:02:44 +02001843
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001844 if (all || strcmp(kwd_dump, "acl") == 0) {
1845 printf("# List of registered ACL keywords:\n");
1846 acl_dump_kwd();
1847 }
1848
Willy Tarreauca1acd62022-03-29 15:02:44 +02001849 if (all || strcmp(kwd_dump, "cfg") == 0) {
1850 printf("# List of registered configuration keywords:\n");
1851 cfg_dump_registered_keywords();
1852 }
Willy Tarreau3b65e142022-03-29 15:03:09 +02001853
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001854 if (all || strcmp(kwd_dump, "cli") == 0) {
1855 printf("# List of registered CLI keywords:\n");
1856 cli_list_keywords();
1857 }
1858
Willy Tarreau29d799d2022-03-29 16:59:49 +02001859 if (all || strcmp(kwd_dump, "cnv") == 0) {
1860 printf("# List of registered sample converter functions:\n");
1861 smp_dump_conv_kw();
1862 }
1863
Willy Tarreau3b65e142022-03-29 15:03:09 +02001864 if (all || strcmp(kwd_dump, "flt") == 0) {
1865 printf("# List of registered filter names:\n");
1866 flt_dump_kws(NULL);
1867 }
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001868
Willy Tarreauf78813f2022-03-29 16:51:29 +02001869 if (all || strcmp(kwd_dump, "smp") == 0) {
1870 printf("# List of registered sample fetch functions:\n");
1871 smp_dump_fetch_kw();
1872 }
1873
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001874 if (all || strcmp(kwd_dump, "svc") == 0) {
1875 printf("# List of registered service names:\n");
1876 list_services(NULL);
1877 }
Willy Tarreau76871a42022-03-08 16:01:40 +01001878 }
1879}
1880
Willy Tarreau392524d2022-02-17 18:10:36 +01001881/*
1882 * This function initializes all the necessary variables. It only returns
1883 * if everything is OK. If something fails, it exits.
1884 */
1885static void init(int argc, char **argv)
1886{
1887 char *progname = global.log_tag.area;
1888 int err_code = 0;
1889 struct wordlist *wl;
1890 struct proxy *px;
1891 struct post_check_fct *pcf;
William Lallemandb53eb872022-04-21 18:02:53 +02001892 struct pre_check_fct *prcf;
Willy Tarreau392524d2022-02-17 18:10:36 +01001893 int ideal_maxconn;
1894
1895 if (!init_trash_buffers(1)) {
1896 ha_alert("failed to initialize trash buffers.\n");
1897 exit(1);
1898 }
1899
1900 if (init_acl() != 0)
1901 exit(1);
1902
1903 /* Initialise lua. */
1904 hlua_init();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001905
Christopher Faulete3a5e352017-10-24 13:53:54 +02001906 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001907 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Willy Tarreau76871a42022-03-08 16:01:40 +01001908 | MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS | MODE_DUMP_KWD));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001909
William Lallemand944e6192018-11-21 15:48:31 +01001910 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001911 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001912 global.mode |= MODE_MWORKER_WAIT;
1913 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001914 }
1915
Willy Tarreau26146192021-07-21 10:01:36 +02001916 if ((global.mode & (MODE_MWORKER | MODE_CHECK | MODE_CHECK_CONDITION)) == MODE_MWORKER &&
1917 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001918 atexit_flag = 1;
1919 atexit(reexec_on_failure);
1920 }
1921
Willy Tarreau576132e2011-09-10 19:26:56 +02001922 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001923 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001924 exit(1);
1925 }
1926
Amaury Denoyelle11124302021-06-04 18:22:08 +02001927 usermsgs_clr("config");
1928
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001929 if (global.mode & MODE_CHECK_CONDITION) {
1930 int result;
1931
1932 uint32_t err;
1933 const char *errptr;
1934 char *errmsg = NULL;
1935
1936 char *args[MAX_LINE_ARGS+1];
1937 int arg = sizeof(args) / sizeof(*args);
William Lallemand89e236f2022-05-06 17:22:36 +02001938 size_t outlen;
Willy Tarreauc8194c32021-07-16 16:38:58 +02001939 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001940
William Lallemand89e236f2022-05-06 17:22:36 +02001941 if (!check_condition)
1942 usage(progname);
1943
1944 outlen = strlen(check_condition) + 1;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001945 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02001946 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001947 &errptr);
1948
1949 if (err & PARSE_ERR_QUOTE) {
1950 ha_alert("Syntax Error in condition: Unmatched quote.\n");
1951 exit(2);
1952 }
1953
1954 if (err & PARSE_ERR_HEX) {
1955 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
1956 exit(2);
1957 }
1958
1959 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
1960 ha_alert("Error in condition: Line too long.\n");
1961 exit(2);
1962 }
1963
Willy Tarreauc8194c32021-07-16 16:38:58 +02001964 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001965 ha_alert("Error in condition: Too many words.\n");
1966 exit(2);
1967 }
1968
1969 if (err) {
1970 ha_alert("Unhandled error in condition, please report this to the developers.\n");
1971 exit(2);
1972 }
1973
Willy Tarreauc8194c32021-07-16 16:38:58 +02001974 /* remerge all words into a single expression */
1975 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
1976 ;
1977
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001978 result = cfg_eval_condition(args, &errmsg, &errptr);
1979
1980 if (result < 0) {
1981 if (errmsg)
1982 ha_alert("Failed to evaluate condition: %s\n", errmsg);
1983
1984 exit(2);
1985 }
1986
1987 exit(result ? 0 : 1);
1988 }
1989
William Lallemand944e6192018-11-21 15:48:31 +01001990 /* in wait mode, we don't try to read the configuration files */
1991 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001992 char *env_cfgfiles = NULL;
1993 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001994
William Lallemand944e6192018-11-21 15:48:31 +01001995 /* handle cfgfiles that are actually directories */
1996 cfgfiles_expand_directories();
1997
1998 if (LIST_ISEMPTY(&cfg_cfgfiles))
1999 usage(progname);
2000
2001
2002 list_for_each_entry(wl, &cfg_cfgfiles, list) {
2003 int ret;
2004
Christopher Faulet4e366822021-01-12 18:57:38 +01002005 if (env_err == 0) {
2006 if (!memprintf(&env_cfgfiles, "%s%s%s",
2007 (env_cfgfiles ? env_cfgfiles : ""),
2008 (env_cfgfiles ? ";" : ""), wl->s))
2009 env_err = 1;
2010 }
William Lallemand7b302d82019-05-20 11:15:37 +02002011
William Lallemand944e6192018-11-21 15:48:31 +01002012 ret = readcfgfile(wl->s);
2013 if (ret == -1) {
2014 ha_alert("Could not open configuration file %s : %s\n",
2015 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01002016 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002017 exit(1);
2018 }
2019 if (ret & (ERR_ABORT|ERR_FATAL))
2020 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
2021 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01002022 if (err_code & ERR_ABORT) {
2023 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002024 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01002025 }
Willy Tarreauc4382422009-12-06 13:10:44 +01002026 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02002027
William Lallemand944e6192018-11-21 15:48:31 +01002028 /* do not try to resolve arguments nor to spot inconsistencies when
2029 * the configuration contains fatal errors caused by files not found
2030 * or failed memory allocations.
2031 */
2032 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2033 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01002034 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002035 exit(1);
2036 }
Christopher Faulet4e366822021-01-12 18:57:38 +01002037 if (env_err) {
2038 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
2039 exit(1);
2040 }
2041 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
2042 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02002043
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02002044 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002045 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01002046 struct mworker_proc *tmproc;
2047
William Lallemand482f9a92019-04-12 16:15:00 +02002048 setenv("HAPROXY_MWORKER", "1", 1);
2049
William Lallemand16dd1b32018-11-19 18:46:18 +01002050 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
2051
William Lallemand56be0e02022-01-28 21:11:41 +01002052 tmproc = mworker_proc_new();
William Lallemand16dd1b32018-11-19 18:46:18 +01002053 if (!tmproc) {
2054 ha_alert("Cannot allocate process structures.\n");
2055 exit(EXIT_FAILURE);
2056 }
William Lallemand8f7069a2019-04-12 16:09:23 +02002057 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01002058 tmproc->pid = pid;
2059 tmproc->timestamp = start_date.tv_sec;
William Lallemand16dd1b32018-11-19 18:46:18 +01002060 proc_self = tmproc;
2061
Willy Tarreau2b718102021-04-21 07:32:39 +02002062 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01002063 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002064
William Lallemand56be0e02022-01-28 21:11:41 +01002065 tmproc = mworker_proc_new();
Willy Tarreau6185a032021-06-15 08:02:06 +02002066 if (!tmproc) {
2067 ha_alert("Cannot allocate process structures.\n");
2068 exit(EXIT_FAILURE);
2069 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002070 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
William Lallemandce83b4a2018-10-26 14:47:30 +02002071
Willy Tarreau6185a032021-06-15 08:02:06 +02002072 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
2073 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02002074 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002075
2076 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01002077 }
2078 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
2079 struct wordlist *it, *c;
2080
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02002081 /* get the info of the children in the env */
2082 if (mworker_env_to_proc_list() < 0) {
2083 exit(EXIT_FAILURE);
2084 }
William Lallemande7361152018-10-26 14:47:36 +02002085
William Lallemand550db6d2018-11-06 17:37:12 +01002086 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02002087
William Lallemand550db6d2018-11-06 17:37:12 +01002088 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02002089 ha_alert("Can't create the master's CLI.\n");
2090 exit(EXIT_FAILURE);
2091 }
William Lallemande7361152018-10-26 14:47:36 +02002092
William Lallemand550db6d2018-11-06 17:37:12 +01002093 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
2094
2095 if (mworker_cli_proxy_new_listener(c->s) < 0) {
2096 ha_alert("Can't create the master's CLI.\n");
2097 exit(EXIT_FAILURE);
2098 }
Willy Tarreau2b718102021-04-21 07:32:39 +02002099 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01002100 free(c->s);
2101 free(c);
2102 }
2103 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002104 }
2105
Eric Salama5ba83352021-03-16 15:11:17 +01002106 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
2107 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
2108 }
2109
Christopher Faulet27c8d202021-10-13 09:50:53 +02002110 /* destroy unreferenced defaults proxies */
2111 proxy_destroy_all_unref_defaults();
2112
William Lallemandb53eb872022-04-21 18:02:53 +02002113 list_for_each_entry(prcf, &pre_check_list, list)
2114 err_code |= prcf->fct();
Willy Tarreaue90904d2021-02-12 14:08:31 +01002115
William Lallemand8b9a2df2022-05-04 14:29:46 +02002116 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2117 ha_alert("Fatal errors found in configuration.\n");
2118 exit(1);
2119 }
2120
Willy Tarreaubb925012009-07-23 13:36:36 +02002121 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02002122 for (px = proxies_list; px; px = px->next) {
2123 struct server *srv;
2124 struct post_proxy_check_fct *ppcf;
2125 struct post_server_check_fct *pscf;
2126
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002127 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002128 continue;
2129
Christopher Fauletc1692962019-08-12 09:51:07 +02002130 list_for_each_entry(pscf, &post_server_check_list, list) {
2131 for (srv = px->srv; srv; srv = srv->next)
2132 err_code |= pscf->fct(srv);
2133 }
2134 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2135 err_code |= ppcf->fct(px);
2136 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002137 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002138 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002139 exit(1);
2140 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002141
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002142 err_code |= pattern_finalize_config();
2143 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2144 ha_alert("Failed to finalize pattern config.\n");
2145 exit(1);
2146 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002147
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002148 if (global.rlimit_memmax_all)
2149 global.rlimit_memmax = global.rlimit_memmax_all;
2150
Willy Tarreaue5733232019-05-22 19:24:06 +02002151#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002152 err_code |= netns_init();
2153 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002154 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002155 exit(1);
2156 }
2157#endif
2158
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002159 /* Apply server states */
2160 apply_server_state();
2161
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002162 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002163 srv_compute_all_admin_states(px);
2164
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002165 /* Apply servers' configured address */
2166 err_code |= srv_init_addr();
2167 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002168 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002169 exit(1);
2170 }
2171
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002172 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2173 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2174 exit(1);
2175 }
2176
Willy Tarreau654726d2021-12-28 15:43:11 +01002177#if defined(HA_HAVE_DUMP_LIBS)
2178 if (global.mode & MODE_DUMP_LIBS) {
2179 qfprintf(stdout, "List of loaded object files:\n");
2180 chunk_reset(&trash);
2181 if (dump_libs(&trash, 0))
2182 printf("%s", trash.area);
2183 }
2184#endif
2185
Willy Tarreau76871a42022-03-08 16:01:40 +01002186 if (global.mode & MODE_DUMP_KWD)
2187 dump_registered_keywords();
2188
Willy Tarreaubaaee002006-06-26 02:48:02 +02002189 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002190 struct peers *pr;
2191 struct proxy *px;
2192
Willy Tarreaubebd2122020-04-15 16:06:11 +02002193 if (warned & WARN_ANY)
2194 qfprintf(stdout, "Warnings were found.\n");
2195
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002196 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002197 if (pr->peers_fe)
2198 break;
2199
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002200 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002201 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002202 break;
2203
Emeric Brunbc5c8212021-08-13 09:32:50 +02002204 if (!px) {
2205 /* We may only have log-forward section */
2206 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002207 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002208 break;
2209 }
2210
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002211 if (pr || px) {
2212 /* At least one peer or one listener has been found */
2213 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002214 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002215 }
2216 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2217 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002218 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002219
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002220 if (global.mode & MODE_DIAG) {
2221 cfg_run_diagnostics();
2222 }
2223
Remi Tricot-Le Breton51944462022-05-16 16:24:31 +02002224 /* Initialize the random generators */
2225#ifdef USE_OPENSSL
2226 /* Initialize SSL random generator. Must be called before chroot for
2227 * access to /dev/urandom, and before ha_random_boot() which may use
2228 * RAND_bytes().
2229 */
2230 if (!ssl_initialize_random()) {
2231 ha_alert("OpenSSL random data generator initialization failed.\n");
2232 exit(EXIT_FAILURE);
2233 }
2234#endif
2235 ha_random_boot(argv); // the argv pointer brings some kernel-fed entropy
2236
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002237 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002238 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002239
Willy Tarreaue6945732016-12-21 19:57:00 +01002240 list_for_each_entry(pcf, &post_check_list, list) {
2241 err_code |= pcf->fct();
2242 if (err_code & (ERR_ABORT|ERR_FATAL))
2243 exit(1);
2244 }
2245
William Lallemand0a012aa2022-06-21 11:11:50 +02002246 /* set the default maxconn in the master, but let it be rewritable with -n */
2247 if (global.mode & MODE_MWORKER_WAIT)
2248 global.maxconn = DEFAULT_MAXCONN;
2249
Willy Tarreaubaaee002006-06-26 02:48:02 +02002250 if (cfg_maxconn > 0)
2251 global.maxconn = cfg_maxconn;
2252
Willy Tarreau4975d142021-03-13 11:00:33 +01002253 if (global.cli_fe)
2254 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002255
2256 if (cfg_peers) {
2257 /* peers also need to bypass global maxconn */
2258 struct peers *p = cfg_peers;
2259
2260 for (p = cfg_peers; p; p = p->next)
2261 if (p->peers_fe)
2262 global.maxsock += p->peers_fe->maxconn;
2263 }
2264
Willy Tarreaud0256482015-01-15 21:45:22 +01002265 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002266 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2267 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2268 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2269 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002270 *
2271 * If memmax is set, then it depends on which values are set. If
2272 * maxsslconn is set, we use memmax to determine how many cleartext
2273 * connections may be added, and set maxconn to the sum of the two.
2274 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2275 * the remaining amount of memory between memmax and the cleartext
2276 * connections. If neither are set, then it is considered that all
2277 * connections are SSL-capable, and maxconn is computed based on this,
2278 * then maxsslconn accordingly. We need to know if SSL is used on the
2279 * frontends, backends, or both, because when it's used on both sides,
2280 * we need twice the value for maxsslconn, but we only count the
2281 * handshake once since it is not performed on the two sides at the
2282 * same time (frontend-side is terminated before backend-side begins).
2283 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002284 * ssl_handshake_cost during its initialization. In any case, if
2285 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2286 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002287 */
Willy Tarreauac350932019-03-01 15:43:14 +01002288 ideal_maxconn = compute_ideal_maxconn();
2289
Willy Tarreaud0256482015-01-15 21:45:22 +01002290 if (!global.rlimit_memmax) {
2291 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002292 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002293 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2294 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2295 }
2296 }
2297#ifdef USE_OPENSSL
2298 else if (!global.maxconn && !global.maxsslconn &&
2299 (global.ssl_used_frontend || global.ssl_used_backend)) {
2300 /* memmax is set, compute everything automatically. Here we want
2301 * to ensure that all SSL connections will be served. We take
2302 * care of the number of sides where SSL is used, and consider
2303 * the worst case : SSL used on both sides and doing a handshake
2304 * simultaneously. Note that we can't have more than maxconn
2305 * handshakes at a time by definition, so for the worst case of
2306 * two SSL conns per connection, we count a single handshake.
2307 */
2308 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2309 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002310 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002311
Willy Tarreau2cb3be72022-05-24 07:43:57 +02002312 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002313 mem -= global.maxzlibmem;
2314 mem = mem * MEM_USABLE_RATIO;
2315
Willy Tarreau304e17e2020-03-10 17:54:54 +01002316 /* Principle: we test once to set maxconn according to the free
2317 * memory. If it results in values the system rejects, we try a
2318 * second time by respecting rlim_fd_max. If it fails again, we
2319 * go back to the initial value and will let the final code
2320 * dealing with rlimit report the error. That's up to 3 attempts.
2321 */
2322 do {
2323 global.maxconn = mem /
2324 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2325 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2326 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002327
Willy Tarreau304e17e2020-03-10 17:54:54 +01002328 if (retried == 1)
2329 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2330 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002331#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002332 if (global.maxconn > SYSTEM_MAXCONN)
2333 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002334#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002335 global.maxsslconn = sides * global.maxconn;
2336
2337 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2338 break;
2339 } while (retried++ < 2);
2340
Willy Tarreaud0256482015-01-15 21:45:22 +01002341 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2342 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2343 global.maxconn, global.maxsslconn);
2344 }
2345 else if (!global.maxsslconn &&
2346 (global.ssl_used_frontend || global.ssl_used_backend)) {
2347 /* memmax and maxconn are known, compute maxsslconn automatically.
2348 * maxsslconn being forced, we don't know how many of it will be
2349 * on each side if both sides are being used. The worst case is
2350 * when all connections use only one SSL instance because
2351 * handshakes may be on two sides at the same time.
2352 */
2353 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2354 int64_t mem = global.rlimit_memmax * 1048576ULL;
2355 int64_t sslmem;
2356
Willy Tarreau8e5b9582022-05-26 08:55:05 +02002357 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002358 mem -= global.maxzlibmem;
2359 mem = mem * MEM_USABLE_RATIO;
2360
Willy Tarreau87b09662015-04-03 00:22:06 +02002361 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002362 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2363 global.maxsslconn = round_2dig(global.maxsslconn);
2364
2365 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002366 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2367 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2368 "without SSL is %d, but %d was found and SSL is in use.\n",
2369 global.rlimit_memmax,
2370 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2371 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002372 exit(1);
2373 }
2374
2375 if (global.maxsslconn > sides * global.maxconn)
2376 global.maxsslconn = sides * global.maxconn;
2377
2378 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2379 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2380 }
2381#endif
2382 else if (!global.maxconn) {
2383 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2384 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2385 int64_t mem = global.rlimit_memmax * 1048576ULL;
2386 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002387 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002388
2389 if (global.ssl_used_frontend || global.ssl_used_backend)
Willy Tarreau8e5b9582022-05-26 08:55:05 +02002390 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002391
2392 mem -= global.maxzlibmem;
2393 mem = mem * MEM_USABLE_RATIO;
2394
2395 clearmem = mem;
2396 if (sides)
2397 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2398
Willy Tarreau304e17e2020-03-10 17:54:54 +01002399 /* Principle: we test once to set maxconn according to the free
2400 * memory. If it results in values the system rejects, we try a
2401 * second time by respecting rlim_fd_max. If it fails again, we
2402 * go back to the initial value and will let the final code
2403 * dealing with rlimit report the error. That's up to 3 attempts.
2404 */
2405 do {
2406 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2407 if (retried == 1)
2408 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2409 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002410#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002411 if (global.maxconn > SYSTEM_MAXCONN)
2412 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002413#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002414
Willy Tarreau304e17e2020-03-10 17:54:54 +01002415 if (clearmem <= 0 || !global.maxconn) {
2416 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2417 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2418 "is %d, but %d was found.\n",
2419 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002420 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002421 global.maxsslconn);
2422 exit(1);
2423 }
2424
2425 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2426 break;
2427 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002428
2429 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2430 if (sides && global.maxsslconn > sides * global.maxconn) {
2431 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2432 "to be limited to %d. Better reduce global.maxsslconn to get more "
2433 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2434 }
2435 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2436 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002437 }
2438
Willy Tarreaua409f302020-03-10 17:08:53 +01002439 global.maxsock = compute_ideal_maxsock(global.maxconn);
2440 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002441 if (!global.maxpipes)
2442 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443
Olivier Houchard88698d92019-04-16 19:07:22 +02002444 /* update connection pool thresholds */
2445 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2446 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2447
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002448 proxy_adjust_all_maxconn();
2449
Willy Tarreau1db37712007-06-03 17:16:49 +02002450 if (global.tune.maxpollevents <= 0)
2451 global.tune.maxpollevents = MAX_POLL_EVENTS;
2452
Willy Tarreau060a7612021-03-10 11:06:26 +01002453 if (global.tune.runqueue_depth <= 0) {
2454 /* tests on various thread counts from 1 to 64 have shown an
2455 * optimal queue depth following roughly 1/sqrt(threads).
2456 */
2457 int s = my_flsl(global.nbthread);
2458 s += (global.nbthread / s); // roughly twice the sqrt.
2459 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2460 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002461
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002462 if (global.tune.recv_enough == 0)
2463 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2464
Willy Tarreau27a674e2009-08-17 07:23:33 +02002465 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2466 global.tune.maxrewrite = global.tune.bufsize / 2;
2467
Amaury Denoyelle11124302021-06-04 18:22:08 +02002468 usermsgs_clr(NULL);
2469
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2471 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002472 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002473 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2474 }
2475
William Lallemand095ba4c2017-06-01 17:38:50 +02002476 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002477 /* command line daemon mode inhibits foreground and debug modes mode */
2478 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002479 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002481
2482 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483
William Lallemand095ba4c2017-06-01 17:38:50 +02002484 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002485 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002486 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002487 }
2488
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002489 if (global.nbthread < 1)
2490 global.nbthread = 1;
2491
Christopher Faulet3ef26392017-08-29 16:46:57 +02002492 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002493 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002494 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002495 exit(1);
2496 }
2497
Christopher Faulet96d44832017-11-14 22:02:30 +01002498 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002499 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002500 exit(1);
2501 }
2502
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002503 /*
2504 * Note: we could register external pollers here.
2505 * Built-in pollers have been registered before main().
2506 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002507
Willy Tarreau43b78992009-01-25 15:42:27 +01002508 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002509 disable_poller("kqueue");
2510
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002511 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2512 disable_poller("evports");
2513
Willy Tarreau43b78992009-01-25 15:42:27 +01002514 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002515 disable_poller("epoll");
2516
Willy Tarreau43b78992009-01-25 15:42:27 +01002517 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002518 disable_poller("poll");
2519
Willy Tarreau43b78992009-01-25 15:42:27 +01002520 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002521 disable_poller("select");
2522
2523 /* Note: we could disable any poller by name here */
2524
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002525 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002526 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002527 fprintf(stderr, "\n");
2528 list_filters(stderr);
2529 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002530
Willy Tarreau4f60f162007-04-08 16:39:58 +02002531 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002532 ha_alert("No polling mechanism available.\n"
2533 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2534 " is too low on this platform to support maxconn and the number of listeners\n"
2535 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2536 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2537 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2538 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2539 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2540 " check build settings using 'haproxy -vv'.\n\n",
2541 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002542 exit(1);
2543 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002544 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2545 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002546 }
2547
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002548 if (!global.node)
2549 global.node = strdup(hostname);
2550
Willy Tarreau02b092f2020-10-07 18:36:54 +02002551 /* stop disabled proxies */
2552 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002553 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002554 stop_proxy(px);
2555 }
2556
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002557 if (!hlua_post_init())
2558 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559}
2560
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002561void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002563 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002564 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002565 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002566 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002567 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002568 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002569 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002570 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002571 struct per_thread_init_fct *tif, *tifb;
2572 struct per_thread_deinit_fct *tdf, *tdfb;
2573 struct per_thread_alloc_fct *taf, *tafb;
2574 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002575 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002576 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002577 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreau65009eb2022-04-27 18:02:54 +02002578 struct pre_check_fct *prcf, *prcfb;
Willy Tarreau226866e2022-04-27 18:07:24 +02002579 struct cfg_postparser *pprs, *pprsb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002580 int cur_fd;
2581
2582 /* At this point the listeners state is weird:
2583 * - most listeners are still bound and referenced in their protocol
2584 * - some might be zombies that are not in their proto anymore, but
2585 * still appear in their proxy's listeners with a valid FD.
2586 * - some might be stopped and still appear in their proxy as FD #-1
2587 * - among all of them, some might be inherited hence shared and we're
2588 * not allowed to pause them or whatever, we must just close them.
2589 * - finally some are not listeners (pipes, logs, stdout, etc) and
2590 * must be left intact.
2591 *
2592 * The safe way to proceed is to unbind (and close) whatever is not yet
2593 * unbound so that no more receiver/listener remains alive. Then close
2594 * remaining listener FDs, which correspond to zombie listeners (those
2595 * belonging to disabled proxies that were in another process).
2596 * objt_listener() would be cleaner here but not converted yet.
2597 */
2598 protocol_unbind_all();
2599
2600 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002601 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002602 continue;
2603
Willy Tarreaua74cb382020-10-15 21:29:49 +02002604 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002605 struct listener *l = fdtab[cur_fd].owner;
2606
2607 BUG_ON(l->state != LI_INIT);
2608 unbind_listener(l);
2609 }
2610 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002611
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002612 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002613 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002614 /* build a list of unique uri_auths */
2615 if (!ua)
2616 ua = p->uri_auth;
2617 else {
2618 /* check if p->uri_auth is unique */
2619 for (uap = ua; uap; uap=uap->next)
2620 if (uap == p->uri_auth)
2621 break;
2622
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002623 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002624 /* add it, if it is */
2625 p->uri_auth->next = ua;
2626 ua = p->uri_auth;
2627 }
William Lallemand0f99e342011-10-12 17:50:54 +02002628 }
2629
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002630 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002631 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002632 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002633 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002634
Christopher Faulet27c8d202021-10-13 09:50:53 +02002635 /* destroy all referenced defaults proxies */
2636 proxy_destroy_all_unref_defaults();
2637
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002638 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002639 struct stat_scope *scope, *scopep;
2640
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002641 uap = ua;
2642 ua = ua->next;
2643
Willy Tarreaua534fea2008-08-03 12:19:50 +02002644 free(uap->uri_prefix);
2645 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002646 free(uap->node);
2647 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002648
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002649 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002650 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002651
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002652 scope = uap->scope;
2653 while (scope) {
2654 scopep = scope;
2655 scope = scope->next;
2656
2657 free(scopep->px_id);
2658 free(scopep);
2659 }
2660
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002661 free(uap);
2662 }
2663
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002664 userlist_free(userlist);
2665
David Carlier834cb2e2015-09-25 12:02:25 +01002666 cfg_unregister_sections();
2667
Christopher Faulet0132d062017-07-26 15:33:35 +02002668 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002669
Willy Tarreau05554e62016-12-21 20:46:26 +01002670 list_for_each_entry(pdf, &post_deinit_list, list)
2671 pdf->fct();
2672
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002673 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002674 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002675 ha_free(&global.chroot);
Frédéric Lécaille372508c2022-05-06 08:53:16 +02002676 ha_free(&global.cluster_secret);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002677 ha_free(&global.pidfile);
2678 ha_free(&global.node);
2679 ha_free(&global.desc);
2680 ha_free(&oldpids);
2681 ha_free(&old_argv);
2682 ha_free(&localpeer);
2683 ha_free(&global.server_state_base);
2684 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002685 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002686 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002687
William Lallemand0f99e342011-10-12 17:50:54 +02002688 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002689 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002690 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002691 free(log);
2692 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002693 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002694 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002695 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002696 free(wl);
2697 }
2698
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002699 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2700 if (bol->must_free)
2701 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002702 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002703 free(bol);
2704 }
2705
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002706 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002707 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002708 free(pxdf);
2709 }
2710
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002711 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002712 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002713 free(pdf);
2714 }
2715
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002716 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002717 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002718 free(srvdf);
2719 }
2720
Tim Duesterhusfc854942020-09-10 19:46:42 +02002721 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002722 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002723 free(pcf);
2724 }
2725
Tim Duesterhus34bef072020-07-04 11:49:50 +02002726 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002727 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002728 free(pscf);
2729 }
2730
Tim Duesterhus53508d62020-09-10 19:46:40 +02002731 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002732 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002733 free(ppcf);
2734 }
2735
Willy Tarreau65009eb2022-04-27 18:02:54 +02002736 list_for_each_entry_safe(prcf, prcfb, &pre_check_list, list) {
2737 LIST_DELETE(&prcf->list);
2738 free(prcf);
2739 }
2740
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002741 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002742 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002743 free(tif);
2744 }
2745
2746 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002747 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002748 free(tdf);
2749 }
2750
2751 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002752 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002753 free(taf);
2754 }
2755
2756 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002757 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002758 free(tff);
2759 }
2760
Willy Tarreau226866e2022-04-27 18:07:24 +02002761 list_for_each_entry_safe(pprs, pprsb, &postparsers, list) {
2762 LIST_DELETE(&pprs->list);
2763 free(pprs);
2764 }
2765
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002766 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002767 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002768 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002769} /* end deinit() */
2770
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002771__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002772{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002773 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002774 deinit();
2775 exit(status);
2776}
William Lallemand72160322018-11-06 17:37:16 +01002777
Willy Tarreau918ff602011-07-25 16:33:49 +02002778/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002779void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002780{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002781 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002782
Willy Tarreau55542642021-10-08 09:33:24 +02002783 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002784 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002785 wake_expired_tasks();
2786
William Lallemand1aab50b2018-06-07 09:46:01 +02002787 /* check if we caught some signals and process them in the
2788 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002789 if (signal_queue_len && tid == 0) {
2790 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002791 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002792 }
2793
2794 /* Process a few tasks */
2795 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002796
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002797 /* also stop if we failed to cleanly stop all tasks */
2798 if (killed > 1)
2799 break;
2800
Willy Tarreau10146c92015-04-13 20:44:19 +02002801 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002802 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002803 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002804 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002805 else {
Willy Tarreaue7475c82022-06-20 09:23:24 +02002806 _HA_ATOMIC_OR(&th_ctx->flags, TH_FL_SLEEPING);
Willy Tarreaudce4ad72022-06-22 15:38:38 +02002807 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_NOTIFIED);
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002808 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002809 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002810 activity[tid].wake_tasks++;
Willy Tarreaue7475c82022-06-20 09:23:24 +02002811 _HA_ATOMIC_AND(&th_ctx->flags, ~TH_FL_SLEEPING);
Olivier Houchard79321b92018-07-26 17:55:11 +02002812 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002813 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002814 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002815
Willy Tarreau4f46a352020-03-23 09:27:28 +01002816 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002817 int i;
2818
2819 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002820 /* stop muxes before acknowledging stopping */
Willy Tarreau24cfc9f2022-07-04 14:07:29 +02002821 if (!(tg_ctx->stopping_threads & ti->ltid_bit)) {
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002822 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2823 wake = 1;
2824 }
2825
Willy Tarreauef422ce2022-06-28 19:29:29 +02002826 if (_HA_ATOMIC_OR_FETCH(&tg_ctx->stopping_threads, ti->ltid_bit) == ti->ltid_bit &&
2827 _HA_ATOMIC_OR_FETCH(&stopping_tgroup_mask, tg->tgid_bit) == tg->tgid_bit) {
2828 /* first one to detect it, notify all threads that stopping was just set */
2829 for (i = 0; i < global.nbthread; i++) {
2830 if (ha_thread_info[i].tg->threads_enabled &
2831 ha_thread_info[i].ltid_bit &
2832 ~_HA_ATOMIC_LOAD(&ha_thread_info[i].tg_ctx->stopping_threads))
Willy Tarreaud6455742020-05-13 14:30:25 +02002833 wake_thread(i);
Willy Tarreauef422ce2022-06-28 19:29:29 +02002834 }
Willy Tarreaud6455742020-05-13 14:30:25 +02002835 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002836 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002837
2838 /* stop when there's nothing left to do */
2839 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreauef422ce2022-06-28 19:29:29 +02002840 (_HA_ATOMIC_LOAD(&stopping_tgroup_mask) & all_tgroups_mask) == all_tgroups_mask) {
2841 /* check that all threads are aware of the stopping status */
2842 for (i = 0; i < global.nbtgroups; i++)
Willy Tarreauf34a3fa2022-07-06 10:13:05 +02002843 if ((_HA_ATOMIC_LOAD(&ha_tgroup_ctx[i].stopping_threads) & ha_tgroup_info[i].threads_enabled) !=
2844 ha_tgroup_info[i].threads_enabled)
Willy Tarreauef422ce2022-06-28 19:29:29 +02002845 break;
2846#ifdef USE_THREAD
2847 if (i == global.nbtgroups) {
2848 /* all are OK, let's wake them all and stop */
2849 for (i = 0; i < global.nbthread; i++)
2850 if (i != tid && ha_thread_info[i].tg->threads_enabled & ha_thread_info[i].ltid_bit)
2851 wake_thread(i);
2852 break;
2853 }
2854#endif
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002855 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002856 }
2857
Willy Tarreauc49ba522019-12-11 08:12:23 +01002858 /* If we have to sleep, measure how long */
2859 next = wake ? TICK_ETERNITY : next_timer_expiry();
2860
Willy Tarreau58b458d2008-06-29 22:40:23 +02002861 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002862 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002863
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002864 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002865 }
2866}
2867
Christopher Faulet1d17c102017-08-29 15:38:48 +02002868static void *run_thread_poll_loop(void *data)
2869{
Willy Tarreau082b6282019-05-22 14:42:12 +02002870 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002871 struct per_thread_init_fct *ptif;
2872 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002873 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002874 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002875 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2876 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002877
Willy Tarreau43ab05b2021-09-28 09:43:11 +02002878 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02002879 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02002880 clock_set_local_source();
Willy Tarreau91e6df02019-05-03 17:21:18 +02002881
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002882 /* Now, initialize one thread init at a time. This is better since
2883 * some init code is a bit tricky and may release global resources
2884 * after reallocating them locally. This will also ensure there is
2885 * no race on file descriptors allocation.
2886 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002887#ifdef USE_THREAD
2888 pthread_mutex_lock(&init_mutex);
2889#endif
2890 /* The first thread must set the number of threads left */
2891 if (!init_left)
2892 init_left = global.nbthread;
2893 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002894
Willy Tarreau55542642021-10-08 09:33:24 +02002895 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002896
Willy Tarreau082b6282019-05-22 14:42:12 +02002897 /* per-thread alloc calls performed here are not allowed to snoop on
2898 * other threads, so they are free to initialize at their own rhythm
2899 * as long as they act as if they were alone. None of them may rely
2900 * on resources initialized by the other ones.
2901 */
2902 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2903 if (!ptaf->fct()) {
2904 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002905#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002906 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002907#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02002908 exit(1);
2909 }
2910 }
2911
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002912 /* per-thread init calls performed here are not allowed to snoop on
2913 * other threads, so they are free to initialize at their own rhythm
2914 * as long as they act as if they were alone.
2915 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002916 list_for_each_entry(ptif, &per_thread_init_list, list) {
2917 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002918 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002919#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002920 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002921#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002922 exit(1);
2923 }
2924 }
2925
Willy Tarreau71092822019-06-10 09:51:04 +02002926 /* enabling protocols will result in fd_insert() calls to be performed,
2927 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002928 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002929 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002930 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002931 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002932
Willy Tarreau34a150c2019-06-11 09:16:41 +02002933#ifdef USE_THREAD
2934 pthread_cond_broadcast(&init_cond);
2935 pthread_mutex_unlock(&init_mutex);
2936
2937 /* now wait for other threads to finish starting */
2938 pthread_mutex_lock(&init_mutex);
2939 while (init_left)
2940 pthread_cond_wait(&init_cond, &init_mutex);
2941 pthread_mutex_unlock(&init_mutex);
2942#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002943
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002944#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2945 /* Let's refrain from using setuid executables. This way the impact of
2946 * an eventual vulnerability in a library remains limited. It may
2947 * impact external checks but who cares about them anyway ? In the
2948 * worst case it's possible to disable the option. Obviously we do this
2949 * in workers only. We can't hard-fail on this one as it really is
2950 * implementation dependent though we're interested in feedback, hence
2951 * the warning.
2952 */
2953 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2954 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002955 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 +01002956 ha_warning("Failed to disable setuid, please report to developers with detailed "
2957 "information about your operating system. You can silence this warning "
2958 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2959 }
2960 }
2961#endif
2962
Willy Tarreaud96f1122019-12-03 07:07:36 +01002963#if defined(RLIMIT_NPROC)
2964 /* all threads have started, it's now time to prevent any new thread
2965 * or process from starting. Obviously we do this in workers only. We
2966 * can't hard-fail on this one as it really is implementation dependent
2967 * though we're interested in feedback, hence the warning.
2968 */
2969 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2970 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2971 static int warn_fail;
2972
Willy Tarreau18515722021-04-06 11:57:41 +02002973 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002974 ha_warning("Failed to disable forks, please report to developers with detailed "
2975 "information about your operating system. You can silence this warning "
2976 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2977 }
2978 }
2979#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002980 run_poll_loop();
2981
2982 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2983 ptdf->fct();
2984
Willy Tarreau082b6282019-05-22 14:42:12 +02002985 list_for_each_entry(ptff, &per_thread_free_list, list)
2986 ptff->fct();
2987
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002988#ifdef USE_THREAD
Willy Tarreau291f6ff2022-07-04 13:36:16 +02002989 if (!_HA_ATOMIC_AND_FETCH(&ha_tgroup_info[ti->tgid-1].threads_enabled, ~ti->ltid_bit))
Willy Tarreaucce203a2022-06-24 15:55:11 +02002990 _HA_ATOMIC_AND(&all_tgroups_mask, ~tg->tgid_bit);
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002991 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002992 if (tid > 0)
2993 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002994#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002995 return NULL;
2996}
Christopher Faulet1d17c102017-08-29 15:38:48 +02002997
William Dauchyf9af9d72019-11-17 15:47:16 +01002998/* set uid/gid depending on global settings */
2999static void set_identity(const char *program_name)
3000{
3001 if (global.gid) {
3002 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
3003 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
3004 " without 'uid'/'user' is generally useless.\n", program_name);
3005
3006 if (setgid(global.gid) == -1) {
3007 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
3008 protocol_unbind_all();
3009 exit(1);
3010 }
3011 }
3012
3013 if (global.uid && setuid(global.uid) == -1) {
3014 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
3015 protocol_unbind_all();
3016 exit(1);
3017 }
3018}
3019
Willy Tarreaubaaee002006-06-26 02:48:02 +02003020int main(int argc, char **argv)
3021{
3022 int err, retry;
3023 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02003024 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02003025 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
3026
3027 /* Catch forced CFLAGS that miss 2-complement integer overflow */
3028 if (intovf + 0x7FFFFFFF >= intovf) {
3029 fprintf(stderr,
3030 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
3031 "The source code was miscompiled by the compiler, which usually indicates that\n"
3032 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
3033 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
3034 "and INSTALL files to decide on the best way to pass your local build options.\n"
3035 "\nBuild options :"
3036#ifdef BUILD_TARGET
3037 "\n TARGET = " BUILD_TARGET
3038#endif
3039#ifdef BUILD_CPU
3040 "\n CPU = " BUILD_CPU
3041#endif
3042#ifdef BUILD_CC
3043 "\n CC = " BUILD_CC
3044#endif
3045#ifdef BUILD_CFLAGS
3046 "\n CFLAGS = " BUILD_CFLAGS
3047#endif
3048#ifdef BUILD_OPTIONS
3049 "\n OPTIONS = " BUILD_OPTIONS
3050#endif
3051#ifdef BUILD_DEBUG
3052 "\n DEBUG = " BUILD_DEBUG
3053#endif
3054 "\n\n");
3055 return 1;
3056 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057
Olivier Houchard5fa300d2018-02-03 15:15:21 +01003058 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003059
Willy Tarreaubf696402019-03-01 10:09:28 +01003060 /* take a copy of initial limits before we possibly change them */
3061 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02003062
3063 if (limit.rlim_max == RLIM_INFINITY)
3064 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01003065 rlim_fd_cur_at_boot = limit.rlim_cur;
3066 rlim_fd_max_at_boot = limit.rlim_max;
3067
Willy Tarreau5794fb02018-11-25 18:43:29 +01003068 /* process all initcalls in order of potential dependency */
3069 RUN_INITCALLS(STG_PREPARE);
3070 RUN_INITCALLS(STG_LOCK);
Willy Tarreau3ebe4d92022-02-18 14:51:49 +01003071 RUN_INITCALLS(STG_REGISTER);
Willy Tarreau34527d52022-02-17 17:45:58 +01003072
3073 /* now's time to initialize early boot variables */
3074 init_early(argc, argv);
3075
Willy Tarreau18f96d02022-02-23 17:25:00 +01003076 /* handles argument parsing */
3077 init_args(argc, argv);
3078
Willy Tarreau5794fb02018-11-25 18:43:29 +01003079 RUN_INITCALLS(STG_ALLOC);
3080 RUN_INITCALLS(STG_POOL);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003081 RUN_INITCALLS(STG_INIT);
3082
Willy Tarreau34527d52022-02-17 17:45:58 +01003083 /* this is the late init where the config is parsed */
Emeric Bruncf20bf12010-10-22 16:06:11 +02003084 init(argc, argv);
Willy Tarreau34527d52022-02-17 17:45:58 +01003085
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003086 signal_register_fct(SIGQUIT, dump, SIGQUIT);
3087 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
3088 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02003089 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003090
Willy Tarreaue437c442010-03-17 18:02:46 +01003091 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
3092 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
3093 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003095 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003096
Willy Tarreaudc23a922011-02-16 11:10:36 +01003097 /* ulimits */
3098 if (!global.rlimit_nofile)
3099 global.rlimit_nofile = global.maxsock;
3100
3101 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01003102 limit.rlim_cur = global.rlimit_nofile;
3103 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
3104
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003105 if ((global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit) ||
3106 setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02003107 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003108 if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
3109 limit.rlim_cur = global.fd_hard_limit;
3110
William Dauchy0fec3ab2019-10-27 20:08:11 +01003111 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3112 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
3113 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003114 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003115 }
3116 else {
3117 /* try to set it to the max possible at least */
3118 limit.rlim_cur = limit.rlim_max;
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003119 if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
3120 limit.rlim_cur = global.fd_hard_limit;
3121
William Dauchy0fec3ab2019-10-27 20:08:11 +01003122 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
3123 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02003124
William Dauchya5194602020-03-28 19:29:58 +01003125 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003126 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
3127 global.rlimit_nofile = limit.rlim_cur;
3128 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01003129 }
3130 }
3131
3132 if (global.rlimit_memmax) {
3133 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01003134 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01003135#ifdef RLIMIT_AS
3136 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003137 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3138 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3139 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003140 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003141 }
3142 else
William Dauchya5194602020-03-28 19:29:58 +01003143 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003144 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003145 }
3146#else
3147 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003148 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3149 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3150 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003151 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003152 }
3153 else
William Dauchya5194602020-03-28 19:29:58 +01003154 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003155 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003156 }
3157#endif
3158 }
3159
William Lallemandf82afbb2022-01-07 18:19:42 +01003160 /* Try to get the listeners FD from the previous process using
3161 * _getsocks on the stat socket, it must never been done in wait mode
3162 * and check mode
3163 */
3164 if (old_unixsocket &&
3165 !(global.mode & (MODE_MWORKER_WAIT|MODE_CHECK|MODE_CHECK_CONDITION))) {
William Lallemand85b0bd92017-06-01 17:38:53 +02003166 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02003167 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003168 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02003169 if (!(global.mode & MODE_MWORKER))
3170 exit(1);
3171 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02003172 }
3173 }
William Lallemand85b0bd92017-06-01 17:38:53 +02003174
Willy Tarreaubaaee002006-06-26 02:48:02 +02003175 /* We will loop at most 100 times with 10 ms delay each time.
3176 * That's at most 1 second. We only send a signal to old pids
3177 * if we cannot grab at least one port.
3178 */
3179 retry = MAX_START_RETRIES;
3180 err = ERR_NONE;
3181 while (retry >= 0) {
3182 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003183 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003184 /* exit the loop on no error or fatal error */
3185 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003186 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003187 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 break;
3189
3190 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3191 * listening sockets. So on those platforms, it would be wiser to
3192 * simply send SIGUSR1, which will not be undoable.
3193 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003194 if (tell_old_pids(SIGTTOU) == 0) {
3195 /* no need to wait if we can't contact old pids */
3196 retry = 0;
3197 continue;
3198 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 /* give some time to old processes to stop listening */
3200 w.tv_sec = 0;
3201 w.tv_usec = 10*1000;
3202 select(0, NULL, NULL, NULL, &w);
3203 retry--;
3204 }
3205
Willy Tarreaue91bff22020-09-02 11:11:43 +02003206 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003207 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003208 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003209 if (retry != MAX_START_RETRIES && nb_oldpids) {
3210 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213 exit(1);
3214 }
3215
William Lallemand944e6192018-11-21 15:48:31 +01003216 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003217 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003218 /* Note: we don't have to send anything to the old pids because we
3219 * never stopped them. */
3220 exit(1);
3221 }
3222
Willy Tarreaue91bff22020-09-02 11:11:43 +02003223 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003224 * the previous process gave us, we don't need them anymore
3225 */
Willy Tarreaub5101162022-01-28 18:28:18 +01003226 sock_drop_unused_old_sockets();
Willy Tarreaudd815982007-10-16 12:25:14 +02003227
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003229 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3230 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003231
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 /* MODE_QUIET can inhibit alerts and warnings below this line */
3233
PiBa-NL149a81a2017-12-25 21:03:31 +01003234 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3235 /* either stdin/out/err are already closed or should stay as they are. */
3236 if ((global.mode & MODE_DAEMON)) {
3237 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3238 global.mode &= ~MODE_VERBOSE;
3239 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3240 }
3241 } else {
3242 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3243 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003244 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003246 }
3247
3248 /* open log & pid files before the chroot */
William Lallemand7b820a62022-02-14 09:02:14 +01003249 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) &&
3250 !(global.mode & MODE_MWORKER_WAIT) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003251 unlink(global.pidfile);
3252 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3253 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003254 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003255 if (nb_oldpids)
3256 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003257 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003258 exit(1);
3259 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 }
3261
Willy Tarreaub38651a2007-03-24 17:24:39 +01003262 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003263 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3264 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003265 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003266 exit(1);
3267 }
3268
Jackie Tapia749f74c2020-07-22 18:59:40 -05003269 /* If the user is not root, we'll still let them try the configuration
3270 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003271 */
3272 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003273 ha_warning("[%s.main()] Some options which require full privileges"
3274 " might not work well.\n"
3275 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003276
William Lallemand095ba4c2017-06-01 17:38:50 +02003277 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3278
3279 /* chroot if needed */
3280 if (global.chroot != NULL) {
3281 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003282 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003283 if (nb_oldpids)
3284 tell_old_pids(SIGTTIN);
3285 protocol_unbind_all();
3286 exit(1);
3287 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003288 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003289 }
3290
William Lallemand944e6192018-11-21 15:48:31 +01003291 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003292 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293
William Lallemand27edc4b2019-05-07 17:49:33 +02003294 /* send a SIGTERM to workers who have a too high reloads number */
3295 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3296 mworker_kill_max_reloads(SIGTERM);
3297
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298 /* Note that any error at this stage will be fatal because we will not
3299 * be able to restart the old pids.
3300 */
3301
William Dauchyf9af9d72019-11-17 15:47:16 +01003302 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3303 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003304
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 /* check ulimits */
3306 limit.rlim_cur = limit.rlim_max = 0;
3307 getrlimit(RLIMIT_NOFILE, &limit);
3308 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003309 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3310 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3311 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3312 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3313 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003314 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003315 }
3316 else
3317 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003318 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003319 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3320 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003321 }
3322
William Lallemand944e6192018-11-21 15:48:31 +01003323 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003325 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003326 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003327
William Lallemand095ba4c2017-06-01 17:38:50 +02003328 /*
3329 * if daemon + mworker: must fork here to let a master
3330 * process live in background before forking children
3331 */
William Lallemand73b85e72017-06-01 17:38:51 +02003332
3333 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3334 && (global.mode & MODE_MWORKER)
3335 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003336 ret = fork();
3337 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003338 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003339 protocol_unbind_all();
3340 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003341 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003342 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003343 } else /* change the process group ID in the child (master process) */
3344 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003345 }
William Lallemande20b6a62017-06-01 17:38:55 +02003346
William Lallemande20b6a62017-06-01 17:38:55 +02003347
William Lallemanddeed7802017-11-06 11:00:04 +01003348 /* if in master-worker mode, write the PID of the father */
3349 if (global.mode & MODE_MWORKER) {
3350 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003351 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003352 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003353 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003354 }
3355
Willy Tarreaubaaee002006-06-26 02:48:02 +02003356 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003357 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003358 if (global.mode & MODE_MWORKER)
3359 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003360
3361 ret = fork();
3362 if (ret < 0) {
3363 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3364 protocol_unbind_all();
3365 exit(1); /* there has been an error */
3366 }
3367 else if (ret == 0) { /* child breaks here */
Willy Tarreau3c032f22021-07-21 10:17:02 +02003368 /* This one must not be exported, it's internal! */
3369 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003370 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003371 }
3372 else { /* parent here */
3373 in_parent = 1;
3374
William Lallemand944e6192018-11-21 15:48:31 +01003375 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3376 char pidstr[100];
3377 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003378 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003379 }
3380 if (global.mode & MODE_MWORKER) {
3381 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003382
William Lallemand5d71a6b2021-11-09 15:25:31 +01003383 ha_notice("New worker (%d) forked\n", ret);
William Lallemand944e6192018-11-21 15:48:31 +01003384 /* find the right mworker_proc */
3385 list_for_each_entry(child, &proc_list, list) {
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003386 if (child->reloads == 0 && child->options & PROC_O_TYPE_WORKER) {
William Lallemand944e6192018-11-21 15:48:31 +01003387 child->timestamp = now.tv_sec;
3388 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003389 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003390 break;
3391 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003392 }
3393 }
William Lallemand944e6192018-11-21 15:48:31 +01003394 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003395
William Lallemand944e6192018-11-21 15:48:31 +01003396 } else {
3397 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003398 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003399 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003400
3401#ifdef USE_CPU_AFFINITY
Willy Tarreau44ea6312021-06-15 08:57:56 +02003402 if (!in_parent && ha_cpuset_count(&cpu_map.proc)) { /* only do this if the process has a CPU map */
Olivier Houchard97148f62017-08-16 17:29:11 +02003403
David CARLIERdf91cbd2022-01-06 18:53:50 +00003404#if defined(CPUSET_USE_CPUSET) || defined(__DragonFly__)
David CARLIERbb10dad2022-01-08 09:59:38 +00003405 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003406 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
David CARLIERdf91cbd2022-01-06 18:53:50 +00003407#elif defined(__FreeBSD__)
David CARLIERbb10dad2022-01-08 09:59:38 +00003408 struct hap_cpuset *set = &cpu_map.proc;
David CARLIERdf91cbd2022-01-06 18:53:50 +00003409 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003410#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003411 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003412#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003413 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003414 if (pidfd >= 0) {
3415 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3416 close(pidfd);
3417 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003418
3419 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003420 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421
Willy Tarreaud67ff342021-06-15 07:58:09 +02003422 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003423 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
William Lallemandfab0fdc2021-11-09 18:01:22 +01003424 master = 1;
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003425
3426 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3427 (global.mode & MODE_DAEMON)) {
3428 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003429 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3430 stdio_quiet(-1);
3431
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003432 global.mode &= ~MODE_VERBOSE;
3433 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003434 }
3435
William Lallemandfab0fdc2021-11-09 18:01:22 +01003436 if (global.mode & MODE_MWORKER_WAIT) {
3437 /* only the wait mode handles the master CLI */
3438 mworker_loop();
3439 } else {
3440
3441 /* if not in wait mode, reload in wait mode to free the memory */
William Lallemand836bda22021-11-09 18:16:47 +01003442 ha_notice("Loading success.\n");
William Lallemand68836742021-11-10 10:49:06 +01003443 proc_self->failedreloads = 0; /* reset the number of failure */
William Lallemandfab0fdc2021-11-09 18:01:22 +01003444 mworker_reexec_waitmode();
3445 }
William Lallemand1499b9b2017-06-07 15:04:47 +02003446 /* should never get there */
3447 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003448 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003449#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003450 ssl_free_dh();
3451#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003452 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003453 }
3454
William Lallemandcb11fd22017-06-01 17:38:52 +02003455 /* child must never use the atexit function */
3456 atexit_flag = 0;
3457
William Lallemandbc193052018-09-11 10:06:26 +02003458 /* close useless master sockets */
3459 if (global.mode & MODE_MWORKER) {
3460 struct mworker_proc *child, *it;
3461 master = 0;
3462
William Lallemand309dc9a2018-10-26 14:47:45 +02003463 mworker_cli_proxy_stop();
3464
William Lallemandbc193052018-09-11 10:06:26 +02003465 /* free proc struct of other processes */
3466 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003467 /* close the FD of the master side for all
3468 * workers, we don't need to close the worker
3469 * side of other workers since it's done with
3470 * the bind_proc */
William Lallemand7e018782022-01-28 21:56:24 +01003471 if (child->ipc_fd[0] >= 0) {
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003472 close(child->ipc_fd[0]);
William Lallemand7e018782022-01-28 21:56:24 +01003473 child->ipc_fd[0] = -1;
3474 }
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003475 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandce83b4a2018-10-26 14:47:30 +02003476 child->reloads == 0) {
3477 /* keep this struct if this is our pid */
3478 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003479 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003480 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003481 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003482 mworker_free_child(child);
3483 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003484 }
3485 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003486
William Lallemande1340412017-12-28 16:09:36 +01003487 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3488 devnullfd = open("/dev/null", O_RDWR, 0);
3489 if (devnullfd < 0) {
3490 ha_alert("Cannot open /dev/null\n");
3491 exit(EXIT_FAILURE);
3492 }
3493 }
3494
William Lallemand095ba4c2017-06-01 17:38:50 +02003495 /* Must chroot and setgid/setuid in the children */
3496 /* chroot if needed */
3497 if (global.chroot != NULL) {
3498 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003499 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003500 if (nb_oldpids)
3501 tell_old_pids(SIGTTIN);
3502 protocol_unbind_all();
3503 exit(1);
3504 }
3505 }
3506
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003507 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003508 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003509
William Lallemand7f80eb22017-05-26 18:19:55 +02003510 /* pass through every cli socket, and check if it's bound to
3511 * the current process and if it exposes listeners sockets.
3512 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3513 * */
3514
Willy Tarreau4975d142021-03-13 11:00:33 +01003515 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003516 struct bind_conf *bind_conf;
3517
Willy Tarreau4975d142021-03-13 11:00:33 +01003518 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003519 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003520 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3521 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003522 }
3523 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003524 }
3525
William Lallemand2e8fad92018-11-13 16:18:23 +01003526 /*
3527 * This is only done in daemon mode because we might want the
3528 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3529 * we should now close the 3 first FDs to ensure that we can
3530 * detach from the TTY. We MUST NOT do it in other cases since
3531 * it would have already be done, and 0-2 would have been
3532 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003533 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003534 if ((global.mode & MODE_DAEMON) &&
3535 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003537 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003538 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003539 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3540 }
3541 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003542 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3543 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003544 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003545 }
3546
William Dauchye039f262019-11-17 15:47:15 +01003547 /* try our best to re-enable core dumps depending on system capabilities.
3548 * What is addressed here :
3549 * - remove file size limits
3550 * - remove core size limits
3551 * - mark the process dumpable again if it lost it due to user/group
3552 */
3553 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3554 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3555
3556#if defined(RLIMIT_FSIZE)
3557 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3558 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3559 ha_alert("[%s.main()] Failed to set the raise the maximum "
3560 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003561 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003562 }
3563 else
3564 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003565 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003566 }
3567#endif
3568
3569#if defined(RLIMIT_CORE)
3570 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3571 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3572 ha_alert("[%s.main()] Failed to set the raise the core "
3573 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003574 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003575 }
3576 else
3577 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003578 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003579 }
3580#endif
3581
3582#if defined(USE_PRCTL)
3583 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3584 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3585 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003586#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003587 {
3588 int traceable = PROC_TRACE_CTL_ENABLE;
3589 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3590 ha_warning("[%s.main()] Failed to set the traceable flag, "
3591 "no core will be dumped.\n", argv[0]);
3592 }
William Dauchye039f262019-11-17 15:47:15 +01003593#endif
3594 }
3595
Christopher Faulete3a5e352017-10-24 13:53:54 +02003596 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003597 reset_usermsgs_ctx();
3598
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003599 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003600 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003601
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003602 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003603 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003604
3605 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003606 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003607
3608 /* wait for all threads to terminate */
3609 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003610
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003611 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612}
3613
Willy Tarreaubaaee002006-06-26 02:48:02 +02003614/*
3615 * Local variables:
3616 * c-indent-level: 8
3617 * c-basic-offset: 8
3618 * End:
3619 */