blob: 203897b73740ab7f3ba533110fe1e1020372364c [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>
Willy Tarreau225a90a2020-06-04 15:06:28 +0200118#include <haproxy/pattern.h>
Willy Tarreau3c2a7c22020-06-04 18:38:21 +0200119#include <haproxy/peers.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200120#include <haproxy/pool.h>
121#include <haproxy/protocol.h>
Willy Tarreaubf3b06b2020-08-26 10:23:40 +0200122#include <haproxy/proto_tcp.h>
Willy Tarreaua264d962020-06-04 22:29:18 +0200123#include <haproxy/proxy.h>
Willy Tarreau7cd8b6e2020-06-02 17:32:26 +0200124#include <haproxy/regex.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200125#include <haproxy/sample.h>
Willy Tarreau1e56f922020-06-04 23:20:13 +0200126#include <haproxy/server.h>
Willy Tarreau48d25b32020-06-04 18:58:52 +0200127#include <haproxy/session.h>
Willy Tarreau3727a8a2020-06-04 17:37:26 +0200128#include <haproxy/signal.h>
Willy Tarreau063d47d2020-08-28 16:29:53 +0200129#include <haproxy/sock.h>
Willy Tarreau25140cc2020-08-28 15:40:33 +0200130#include <haproxy/sock_inet.h>
Willy Tarreau209108d2020-06-04 20:30:20 +0200131#include <haproxy/ssl_sock.h>
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +0200132#include <haproxy/stats-t.h>
Willy Tarreaudfd3de82020-06-04 23:46:14 +0200133#include <haproxy/stream.h>
Willy Tarreaucea0e1b2020-06-04 17:25:40 +0200134#include <haproxy/task.h>
Willy Tarreau3f567e42020-05-28 15:29:19 +0200135#include <haproxy/thread.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200136#include <haproxy/time.h>
137#include <haproxy/tools.h>
138#include <haproxy/uri_auth-t.h>
Willy Tarreaua1718922020-06-04 16:25:31 +0200139#include <haproxy/vars.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200140#include <haproxy/version.h>
Frédéric Lécaille92862102022-05-20 16:29:10 +0200141#include <haproxy/xprt_quic-t.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200142
Willy Tarreaubaaee002006-06-26 02:48:02 +0200143
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100144/* array of init calls for older platforms */
145DECLARE_INIT_STAGES;
146
Willy Tarreauf4596402021-04-10 16:53:05 +0200147/* create a read_mostly section to hold variables which are accessed a lot
148 * but which almost never change. The purpose is to isolate them in their
149 * own cache lines where they don't risk to be perturbated by write accesses
150 * to neighbor variables. We need to create an empty aligned variable for
151 * this. The fact that the variable is of size zero means that it will be
152 * eliminated at link time if no other variable uses it, but alignment will
153 * be respected.
154 */
155empty_t __read_mostly_align HA_SECTION("read_mostly") ALIGNED(64);
156
Willy Tarreauf0d3b732021-05-06 16:30:32 +0200157#ifdef BUILD_FEATURES
158const char *build_features = BUILD_FEATURES;
159#else
160const char *build_features = "";
161#endif
162
Willy Tarreau477ecd82010-01-03 21:12:30 +0100163/* list of config files */
164static struct list cfg_cfgfiles = LIST_HEAD_INIT(cfg_cfgfiles);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200165int pid; /* current process id */
166
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100167volatile unsigned long sleeping_thread_mask = 0; /* Threads that are about to sleep in poll() */
Willy Tarreau4b3f27b2020-03-12 17:28:01 +0100168volatile unsigned long stopping_thread_mask = 0; /* Threads acknowledged 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écaille92862102022-05-20 16:29:10 +0200208 .quic_retry_threshold = QUIC_DFLT_RETRY_THRESHOLD,
Amaury Denoyelle97e84c62022-04-19 18:26:55 +0200209 .quic_streams_buf = 30,
210#endif /* USE_QUIC */
Willy Tarreau27a674e2009-08-17 07:23:33 +0200211 },
Emeric Brun76d88952012-10-05 15:47:31 +0200212#ifdef USE_OPENSSL
213#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200214 .maxsslconn = DEFAULT_MAXSSLCONN,
215#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200216#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217 /* others NULL OK */
218};
219
220/*********************************************************************/
221
222int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100223int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200224int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100225int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100226int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100227int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreau392524d2022-02-17 18:10:36 +0100228int arg_mode = 0; /* MODE_DEBUG etc as passed on command line ... */
229char *change_dir = NULL; /* set when -C is passed */
230char *check_condition = NULL; /* check condition passed to -cc */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500232/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 * or kill. We will send them a signal every 10 ms until we can bind to all
234 * our ports. With 200 retries, that's about 2 seconds.
235 */
236#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237static int *oldpids = NULL;
238static int oldpids_sig; /* use USR1 or TERM */
239
Olivier Houchardf73629d2017-04-05 22:33:04 +0200240/* Path to the unix socket we use to retrieve listener sockets from the old process */
241static const char *old_unixsocket;
242
William Lallemandcb11fd22017-06-01 17:38:52 +0200243int atexit_flag = 0;
244
Willy Tarreaubb545b42010-08-25 12:58:59 +0200245int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200246const int zero = 0;
247const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200248const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200249
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100250char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200251char *localpeer = NULL;
Willy Tarreau76871a42022-03-08 16:01:40 +0100252static char *kwd_dump = NULL; // list of keyword dumps to produce
Willy Tarreaubaaee002006-06-26 02:48:02 +0200253
William Lallemand00417412020-06-05 14:08:41 +0200254static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200255
William Lallemandbc193052018-09-11 10:06:26 +0200256struct list proc_list = LIST_HEAD_INIT(proc_list);
257
258int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100259unsigned int rlim_fd_cur_at_boot = 0;
260unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200261
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100262/* per-boot randomness */
263unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
264
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200265/* takes the thread config in argument or NULL for any thread */
William Lallemandb3f2be32018-09-11 10:06:18 +0200266static void *run_thread_poll_loop(void *data);
267
Willy Tarreauff055502014-04-28 22:27:06 +0200268/* bitfield of a few warnings to emit just once (WARN_*) */
269unsigned int warned = 0;
270
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200271/* set if experimental features have been used for the current process */
Willy Tarreauedd42682022-02-25 10:10:00 +0100272unsigned int tainted = 0;
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200273
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200274unsigned int experimental_directives_allowed = 0;
275
276int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
277 char **errmsg)
278{
279 if (kw->flags & KWF_EXPERIMENTAL) {
280 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200281 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 +0200282 file, linenum, kw->kw);
283 return 1;
284 }
285 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
286 }
287
288 return 0;
289}
290
William Lallemande7361152018-10-26 14:47:36 +0200291/* master CLI configuration (-S flag) */
292struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100293
294/* These are strings to be reported in the output of "haproxy -vv". They may
295 * either be constants (in which case must_free must be zero) or dynamically
296 * allocated strings to pass to free() on exit, and in this case must_free
297 * must be non-zero.
298 */
299struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
300struct build_opts_str {
301 struct list list;
302 const char *str;
303 int must_free;
304};
305
Willy Tarreaubaaee002006-06-26 02:48:02 +0200306/*********************************************************************/
307/* general purpose functions ***************************************/
308/*********************************************************************/
309
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100310/* used to register some build option strings at boot. Set must_free to
311 * non-zero if the string must be freed upon exit.
312 */
313void hap_register_build_opts(const char *str, int must_free)
314{
315 struct build_opts_str *b;
316
317 b = calloc(1, sizeof(*b));
318 if (!b) {
319 fprintf(stderr, "out of memory\n");
320 exit(1);
321 }
322 b->str = str;
323 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200324 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100325}
326
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200327#define VERSION_MAX_ELTS 7
328
329/* This function splits an haproxy version string into an array of integers.
330 * The syntax of the supported version string is the following:
331 *
332 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
333 *
334 * This validates for example:
335 * 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
336 * 2.4-dev18-f6818d-20
337 *
338 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
339 * one fixed place in the array. The tags take a numeric value called <e> which
340 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
341 * considered as zero (henxe 1.5 and 1.5.0 are the same).
342 *
343 * The resulting values are:
344 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
345 * 1.2.1 1, 2, 1, 0, 3, 0, 0
346 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
347 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
348 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
349 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
350 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
351 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
352 *
353 * The function returns non-zero if the conversion succeeded, or zero if it
354 * failed.
355 */
356int split_version(const char *version, unsigned int *value)
357{
358 const char *p, *s;
359 char *error;
360 int nelts;
361
362 /* Initialize array with zeroes */
363 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
364 value[nelts] = 0;
365 value[4] = 3;
366
367 p = version;
368
369 /* If the version number is empty, return false */
370 if (*p == '\0')
371 return 0;
372
373 /* Convert first number <a> */
374 value[0] = strtol(p, &error, 10);
375 p = error + 1;
376 if (*error == '\0')
377 return 1;
378 if (*error == '-')
379 goto split_version_tag;
380 if (*error != '.')
381 return 0;
382
383 /* Convert first number <b> */
384 value[1] = strtol(p, &error, 10);
385 p = error + 1;
386 if (*error == '\0')
387 return 1;
388 if (*error == '-')
389 goto split_version_tag;
390 if (*error != '.')
391 return 0;
392
393 /* Convert first number <c> */
394 value[2] = strtol(p, &error, 10);
395 p = error + 1;
396 if (*error == '\0')
397 return 1;
398 if (*error == '-')
399 goto split_version_tag;
400 if (*error != '.')
401 return 0;
402
403 /* Convert first number <d> */
404 value[3] = strtol(p, &error, 10);
405 p = error + 1;
406 if (*error == '\0')
407 return 1;
408 if (*error != '-')
409 return 0;
410
411 split_version_tag:
412 /* Check for commit number */
413 if (*p >= '0' && *p <= '9')
414 goto split_version_commit;
415
416 /* Read tag */
417 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
418 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
419 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
420 else
421 goto split_version_commit;
422
423 /* Convert tag number */
424 value[5] = strtol(p, &error, 10);
425 p = error + 1;
426 if (*error == '\0')
427 return 1;
428 if (*error != '-')
429 return 0;
430
431 split_version_commit:
432 /* Search the last "-" */
433 s = strrchr(p, '-');
434 if (s) {
435 s++;
436 if (*s == '\0')
437 return 0;
438 value[6] = strtol(s, &error, 10);
439 if (*error != '\0')
440 value[6] = 0;
441 return 1;
442 }
443
444 /* convert the version */
445 value[6] = strtol(p, &error, 10);
446 if (*error != '\0')
447 value[6] = 0;
448
449 return 1;
450}
451
452/* This function compares the current haproxy version with an arbitrary version
453 * string. It returns:
454 * -1 : the version in argument is older than the current haproxy version
455 * 0 : the version in argument is the same as the current haproxy version
456 * 1 : the version in argument is newer than the current haproxy version
457 *
458 * Or some errors:
459 * -2 : the current haproxy version is not parsable
460 * -3 : the version in argument is not parsable
461 */
462int compare_current_version(const char *version)
463{
464 unsigned int loc[VERSION_MAX_ELTS];
465 unsigned int mod[VERSION_MAX_ELTS];
466 int i;
467
468 /* split versions */
469 if (!split_version(haproxy_version, loc))
470 return -2;
471 if (!split_version(version, mod))
472 return -3;
473
474 /* compare versions */
475 for (i = 0; i < VERSION_MAX_ELTS; i++) {
476 if (mod[i] < loc[i])
477 return -1;
478 else if (mod[i] > loc[i])
479 return 1;
480 }
481 return 0;
482}
483
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100484static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200485{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200486 struct utsname utsname;
487
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200488 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100489 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100490
491 if (strlen(PRODUCT_URL_BUGS) > 0) {
492 char base_version[20];
493 int dots = 0;
494 char *del;
495
496 /* only retrieve the base version without distro-specific extensions */
497 for (del = haproxy_version; *del; del++) {
498 if (*del == '.')
499 dots++;
500 else if (*del < '0' || *del > '9')
501 break;
502 }
503
504 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
505 if (dots < 2)
506 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
507 else
508 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
509 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200510
511 if (uname(&utsname) == 0) {
512 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
513 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200514}
515
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100516static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100517{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100518 struct build_opts_str *item;
519
Willy Tarreau7b066db2007-12-02 11:28:59 +0100520 printf("Build options :"
521#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100522 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100523#endif
524#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100525 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100526#endif
527#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100528 "\n CC = " BUILD_CC
529#endif
530#ifdef BUILD_CFLAGS
531 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100532#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100533#ifdef BUILD_OPTIONS
534 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100535#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100536#ifdef BUILD_DEBUG
537 "\n DEBUG = " BUILD_DEBUG
538#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100539#ifdef BUILD_FEATURES
540 "\n\nFeature list : " BUILD_FEATURES
541#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200542 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100543 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200544 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100545 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200546
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100547 list_for_each_entry(item, &build_opts_list, list) {
548 puts(item->str);
549 }
550
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100551 putchar('\n');
552
Willy Tarreaube5b6852009-10-03 18:57:08 +0200553 list_pollers(stdout);
554 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200555 list_mux_proto(stdout);
556 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100557 list_services(stdout);
558 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100559 list_filters(stdout);
560 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100561}
562
Willy Tarreaubaaee002006-06-26 02:48:02 +0200563/*
564 * This function prints the command line usage and exits
565 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100566static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567{
568 display_version();
569 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200570 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200571 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200572 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100573 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200574 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreauf4b79c42022-02-23 15:20:53 +0100575 " -dM[<byte>,help,...] debug memory (default: poison with <byte>/0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200576 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200577 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200578 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100579#if defined(USE_SYSTEMD)
580 " -Ws master-worker mode with systemd notify support.\n"
581#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200583 " -c check mode : only check config files and exit\n"
Maximilian Maderfc0cceb2021-06-06 00:50:22 +0200584 " -cc check condition : evaluate a condition and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100585 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200586 " -m limits the usable amount of memory (in MB)\n"
587 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200588 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 " -p writes pids of all children to this file\n"
Willy Tarreaue5733232019-05-22 19:24:06 +0200590#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200591 " -de disables epoll() usage even when available\n"
592#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200593#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200594 " -dk disables kqueue() usage even when available\n"
595#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200596#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000597 " -dv disables event ports usage even when available\n"
598#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200599#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600 " -dp disables poll() usage even when available\n"
601#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200602#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100603 " -dS disables splice usage (broken on old kernels)\n"
604#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200605#if defined(USE_GETADDRINFO)
606 " -dG disables getaddrinfo() usage\n"
607#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000608#if defined(SO_REUSEPORT)
609 " -dR disables SO_REUSEPORT usage\n"
610#endif
Willy Tarreau654726d2021-12-28 15:43:11 +0100611#if defined(HA_HAVE_DUMP_LIBS)
612 " -dL dumps loaded object files after config checks\n"
613#endif
Willy Tarreau76871a42022-03-08 16:01:40 +0100614 " -dK{class[,...]} dump registered keywords (use 'help' for list)\n"
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100615 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100616 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200617 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200618 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200619 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200620 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200621 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200622 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100623 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200624 exit(1);
625}
626
627
628
629/*********************************************************************/
630/* more specific functions ***************************************/
631/*********************************************************************/
632
William Lallemand73b85e72017-06-01 17:38:51 +0200633/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
634 * pids the signal was correctly delivered to.
635 */
William Lallemande25473c2019-04-01 11:29:56 +0200636int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200637{
638 int p;
639 int ret = 0;
640 for (p = 0; p < nb_oldpids; p++)
641 if (kill(oldpids[p], sig) == 0)
642 ret++;
643 return ret;
644}
645
William Lallemand75ea0a02017-11-15 19:02:58 +0100646/*
William Lallemand73b85e72017-06-01 17:38:51 +0200647 * remove a pid forom the olpid array and decrease nb_oldpids
648 * return 1 pid was found otherwise return 0
649 */
650
651int delete_oldpid(int pid)
652{
653 int i;
654
655 for (i = 0; i < nb_oldpids; i++) {
656 if (oldpids[i] == pid) {
657 oldpids[i] = oldpids[nb_oldpids - 1];
658 oldpids[nb_oldpids - 1] = 0;
659 nb_oldpids--;
660 return 1;
661 }
662 }
663 return 0;
664}
665
William Lallemand85b0bd92017-06-01 17:38:53 +0200666
William Lallemand73b85e72017-06-01 17:38:51 +0200667/*
668 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800669 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200670 */
William Lallemandfab0fdc2021-11-09 18:01:22 +0100671static void mworker_reexec()
William Lallemand73b85e72017-06-01 17:38:51 +0200672{
William Lallemand00417412020-06-05 14:08:41 +0200673 char **next_argv = NULL;
674 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200675 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200676 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200677 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100678 struct rlimit limit;
William Lallemand2be557f2021-11-24 18:45:37 +0100679 struct mworker_proc *current_child = NULL;
William Lallemand73b85e72017-06-01 17:38:51 +0200680
681 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100682#if defined(USE_SYSTEMD)
683 if (global.tune.options & GTUNE_USE_SYSTEMD)
684 sd_notify(0, "RELOADING=1");
685#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200686 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
687
William Lallemand55a921c2022-01-28 21:17:30 +0100688 mworker_cleanup_proc();
William Lallemandbc193052018-09-11 10:06:26 +0200689 mworker_proc_list_to_env(); /* put the children description in the env */
690
William Lallemandc4810b82021-11-18 10:51:30 +0100691 /* ensure that we close correctly every listeners before reexecuting */
692 mworker_cleanlisteners();
693
William Lallemand7c756a82018-11-26 11:53:40 +0100694 /* during the reload we must ensure that every FDs that can't be
695 * reuse (ie those that are not referenced in the proc_list)
696 * are closed or they will leak. */
697
698 /* close the listeners FD */
699 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200700
William Lallemand67e371e2021-11-25 10:03:44 +0100701 if (fdtab)
702 deinit_pollers();
William Lallemandefd95472021-11-26 14:43:57 +0100703
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500704#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200705 /* close random device FDs */
706 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100707#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100708
Willy Tarreau8dca1952019-03-01 10:21:55 +0100709 /* restore the initial FD limits */
710 limit.rlim_cur = rlim_fd_cur_at_boot;
711 limit.rlim_max = rlim_fd_max_at_boot;
712 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
713 getrlimit(RLIMIT_NOFILE, &limit);
714 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
715 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
716 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
717 }
718
William Lallemand73b85e72017-06-01 17:38:51 +0200719 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200720 while (old_argv[old_argc])
721 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200722
William Lallemand85b0bd92017-06-01 17:38:53 +0200723 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200724 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200725 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200726 if (next_argv == NULL)
727 goto alloc_error;
728
William Lallemand00417412020-06-05 14:08:41 +0200729 /* copy the program name */
730 next_argv[next_argc++] = old_argv[0];
731
732 /* insert the new options just after argv[0] in case we have a -- */
733
William Lallemandbefab9e2021-11-25 00:49:19 +0100734 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
735 /* add -sf <PID>* to argv */
736 if (mworker_child_nb() > 0) {
737 struct mworker_proc *child;
William Lallemand3f128872019-04-01 11:29:59 +0200738
William Lallemandbefab9e2021-11-25 00:49:19 +0100739 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200740
William Lallemandbefab9e2021-11-25 00:49:19 +0100741 list_for_each_entry(child, &proc_list, list) {
742 if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
743 current_child = child;
William Lallemand2be557f2021-11-24 18:45:37 +0100744
William Lallemandbefab9e2021-11-25 00:49:19 +0100745 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
746 continue;
747 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
748 goto alloc_error;
749 msg = NULL;
750 }
William Lallemand73b85e72017-06-01 17:38:51 +0200751 }
William Lallemand2be557f2021-11-24 18:45:37 +0100752
753 if (current_child) {
754 /* add the -x option with the socketpair of the current worker */
755 next_argv[next_argc++] = "-x";
756 if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
757 goto alloc_error;
758 msg = NULL;
759 }
William Lallemand85b0bd92017-06-01 17:38:53 +0200760 }
761
William Lallemand00417412020-06-05 14:08:41 +0200762 /* copy the previous options */
763 for (i = 1; i < old_argc; i++)
764 next_argv[next_argc++] = old_argv[i];
765
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200766 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100767 execvp(next_argv[0], next_argv);
Christopher Faulet767a84b2017-11-24 16:50:31 +0100768 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100769 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100770 return;
771
William Lallemand73b85e72017-06-01 17:38:51 +0200772alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100773 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800774 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200775 return;
776}
777
William Lallemandfab0fdc2021-11-09 18:01:22 +0100778/* reexec haproxy in waitmode */
779static void mworker_reexec_waitmode()
780{
781 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
782 mworker_reexec();
783}
784
785/* reload haproxy and emit a warning */
786void mworker_reload()
787{
William Lallemandad221f42021-11-09 18:43:59 +0100788 struct mworker_proc *child;
William Lallemandefd95472021-11-26 14:43:57 +0100789 struct per_thread_deinit_fct *ptdf;
William Lallemandad221f42021-11-09 18:43:59 +0100790
William Lallemand836bda22021-11-09 18:16:47 +0100791 ha_notice("Reloading HAProxy\n");
William Lallemandad221f42021-11-09 18:43:59 +0100792
William Lallemandefd95472021-11-26 14:43:57 +0100793 /* close the poller FD and the thread waker pipe FD */
794 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
795 ptdf->fct();
796
William Lallemandad221f42021-11-09 18:43:59 +0100797 /* increment the number of reloads */
798 list_for_each_entry(child, &proc_list, list) {
799 child->reloads++;
800 }
801
William Lallemandfab0fdc2021-11-09 18:01:22 +0100802 mworker_reexec();
803}
804
William Lallemandb3f2be32018-09-11 10:06:18 +0200805static void mworker_loop()
806{
807
808#if defined(USE_SYSTEMD)
809 if (global.tune.options & GTUNE_USE_SYSTEMD)
810 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
811#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200812 /* Busy polling makes no sense in the master :-) */
813 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200814
William Lallemandbc193052018-09-11 10:06:26 +0200815
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100816 signal_unregister(SIGTTIN);
817 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100818 signal_unregister(SIGUSR1);
819 signal_unregister(SIGHUP);
820 signal_unregister(SIGQUIT);
821
William Lallemandb3f2be32018-09-11 10:06:18 +0200822 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
823 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100824 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
825 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200826 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
827 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
828 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
829 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
830
831 mworker_unblock_signals();
William Lallemand27f3fa52018-12-06 14:05:20 +0100832 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200833
William Lallemandbc193052018-09-11 10:06:26 +0200834 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
835 some SIGCHLD were lost */
836
William Lallemandb3f2be32018-09-11 10:06:18 +0200837 global.nbthread = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200838
William Lallemand2672eb92018-12-14 15:52:39 +0100839#ifdef USE_THREAD
840 tid_bit = 1;
841 all_threads_mask = 1;
842#endif
843
William Lallemandb3f2be32018-09-11 10:06:18 +0200844 jobs++; /* this is the "master" job, we want to take care of the
845 signals even if there is no listener so the poll loop don't
846 leave */
847
848 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200849 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200850}
William Lallemandcb11fd22017-06-01 17:38:52 +0200851
852/*
853 * Reexec the process in failure mode, instead of exiting
854 */
855void reexec_on_failure()
856{
William Lallemand68836742021-11-10 10:49:06 +0100857 struct mworker_proc *child;
858
William Lallemandcb11fd22017-06-01 17:38:52 +0200859 if (!atexit_flag)
860 return;
William Lallemand68836742021-11-10 10:49:06 +0100861
862 /* get the info of the children in the env */
863 if (mworker_env_to_proc_list() < 0) {
864 exit(EXIT_FAILURE);
865 }
866
867 /* increment the number of failed reloads */
868 list_for_each_entry(child, &proc_list, list) {
869 child->failedreloads++;
870 }
871
Willy Tarreaue08acae2022-01-28 18:40:06 +0100872 /* do not keep unused FDs retrieved from the previous process */
873 sock_drop_unused_old_sockets();
874
William Lallemandfab0fdc2021-11-09 18:01:22 +0100875 usermsgs_clr(NULL);
William Lallemand836bda22021-11-09 18:16:47 +0100876 ha_warning("Loading failure!\n");
William Lallemandfab0fdc2021-11-09 18:01:22 +0100877 mworker_reexec_waitmode();
William Lallemandcb11fd22017-06-01 17:38:52 +0200878}
William Lallemand73b85e72017-06-01 17:38:51 +0200879
880
881/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200882 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
883 * a signal zero to all subscribers. This means that it's as easy as
884 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100886static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887{
888 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200889 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100890 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200891}
892
893/*
894 * upon SIGTTOU, we pause everything
895 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100896static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897{
Willy Tarreau775e0012020-09-24 16:36:26 +0200898 if (protocol_pause_all() & ERR_FATAL) {
899 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200900 ha_warning("%s", msg);
901 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200902 soft_stop();
903 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100904 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905}
906
907/*
908 * upon SIGTTIN, let's have a soft stop.
909 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100910static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200911{
Willy Tarreau775e0012020-09-24 16:36:26 +0200912 if (protocol_resume_all() & ERR_FATAL) {
913 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 +0200914 ha_warning("%s", msg);
915 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200916 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200917}
918
919/*
920 * this function dumps every server's state when the process receives SIGHUP.
921 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100922static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100924 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200925
Christopher Faulet767a84b2017-11-24 16:50:31 +0100926 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 while (p) {
928 struct server *s = p->srv;
929
930 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
931 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100932 chunk_printf(&trash,
933 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
934 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200935 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200936 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200937 ha_warning("%s\n", trash.area);
938 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200939 s = s->next;
940 }
941
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200942 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
943 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100944 chunk_printf(&trash,
945 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
946 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200947 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 +0200948 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100949 chunk_printf(&trash,
950 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
951 p->id,
952 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200953 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 +0200954 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100955 chunk_printf(&trash,
956 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
957 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
958 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200959 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 +0200960 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200961 ha_warning("%s\n", trash.area);
962 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963
964 p = p->next;
965 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200966}
967
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100968static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200969{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200970 /* dump memory usage then free everything possible */
971 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100972 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973}
974
William Lallemande1340412017-12-28 16:09:36 +0100975/*
976 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
977 * If <fd> < 0, it opens /dev/null and use it to dup
978 *
979 * In the case of chrooting, you have to open /dev/null before the chroot, and
980 * pass the <fd> to this function
981 */
982static void stdio_quiet(int fd)
983{
984 if (fd < 0)
985 fd = open("/dev/null", O_RDWR, 0);
986
987 if (fd > -1) {
988 fclose(stdin);
989 fclose(stdout);
990 fclose(stderr);
991
992 dup2(fd, 0);
993 dup2(fd, 1);
994 dup2(fd, 2);
995 if (fd > 2)
996 close(fd);
997 return;
998 }
999
1000 ha_alert("Cannot open /dev/null\n");
1001 exit(EXIT_FAILURE);
1002}
1003
1004
Joseph Herlant03420902018-11-15 10:41:50 -08001005/* This function checks if cfg_cfgfiles contains directories.
1006 * If it finds one, it adds all the files (and only files) it contains
1007 * in cfg_cfgfiles in place of the directory (and removes the directory).
1008 * It adds the files in lexical order.
1009 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001010 * It doesn't add files with name starting with '.'
1011 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001012static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001013{
1014 struct wordlist *wl, *wlb;
1015 char *err = NULL;
1016
1017 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1018 struct stat file_stat;
1019 struct dirent **dir_entries = NULL;
1020 int dir_entries_nb;
1021 int dir_entries_it;
1022
1023 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001024 ha_alert("Cannot open configuration file/directory %s : %s\n",
1025 wl->s,
1026 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001027 exit(1);
1028 }
1029
1030 if (!S_ISDIR(file_stat.st_mode))
1031 continue;
1032
1033 /* from this point wl->s is a directory */
1034
1035 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1036 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001037 ha_alert("Cannot open configuration directory %s : %s\n",
1038 wl->s,
1039 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001040 exit(1);
1041 }
1042
1043 /* for each element in the directory wl->s */
1044 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1045 struct dirent *dir_entry = dir_entries[dir_entries_it];
1046 char *filename = NULL;
1047 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1048
1049 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001050 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001051 */
1052 if (dir_entry->d_name[0] == '.' ||
1053 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1054 goto next_dir_entry;
1055
1056 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001057 ha_alert("Cannot load configuration files %s : out of memory.\n",
1058 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001059 exit(1);
1060 }
1061
1062 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001063 ha_alert("Cannot open configuration file %s : %s\n",
1064 wl->s,
1065 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001066 exit(1);
1067 }
1068
1069 /* don't add anything else than regular file in cfg_cfgfiles
1070 * this way we avoid loops
1071 */
1072 if (!S_ISREG(file_stat.st_mode))
1073 goto next_dir_entry;
1074
1075 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001076 ha_alert("Cannot load configuration files %s : %s\n",
1077 filename,
1078 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001079 exit(1);
1080 }
1081
1082next_dir_entry:
1083 free(filename);
1084 free(dir_entry);
1085 }
1086
1087 free(dir_entries);
1088
1089 /* remove the current directory (wl) from cfg_cfgfiles */
1090 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001091 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001092 free(wl);
1093 }
1094
1095 free(err);
1096}
1097
Willy Tarreaubaaee002006-06-26 02:48:02 +02001098/*
William Lallemand73b85e72017-06-01 17:38:51 +02001099 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001100 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001101 * Return an allocated copy of argv
1102 */
1103
1104static char **copy_argv(int argc, char **argv)
1105{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001106 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001107
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001108 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001109 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001110 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001111 return NULL;
1112 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001113 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001114
William Lallemanddf6c5a82020-06-04 17:40:23 +02001115 /* first copy argv[0] */
1116 *newargv++ = *argv++;
1117 argc--;
1118
1119 while (argc > 0) {
1120 if (**argv != '-') {
1121 /* non options are copied but will fail in the argument parser */
1122 *newargv++ = *argv++;
1123 argc--;
1124
1125 } else {
1126 char *flag;
1127
1128 flag = *argv + 1;
1129
1130 if (flag[0] == '-' && flag[1] == 0) {
1131 /* "--\0" copy every arguments till the end of argv */
1132 *newargv++ = *argv++;
1133 argc--;
1134
1135 while (argc > 0) {
1136 *newargv++ = *argv++;
1137 argc--;
1138 }
1139 } else {
1140 switch (*flag) {
1141 case 's':
1142 /* -sf / -st and their parameters are ignored */
1143 if (flag[1] == 'f' || flag[1] == 't') {
1144 argc--;
1145 argv++;
1146 /* The list can't contain a negative value since the only
1147 way to know the end of this list is by looking for the
1148 next option or the end of the options */
1149 while (argc > 0 && argv[0][0] != '-') {
1150 argc--;
1151 argv++;
1152 }
William Lallemand398da622020-09-02 16:12:23 +02001153 } else {
1154 argc--;
1155 argv++;
1156
William Lallemanddf6c5a82020-06-04 17:40:23 +02001157 }
1158 break;
1159
1160 case 'x':
1161 /* this option and its parameter are ignored */
1162 argc--;
1163 argv++;
1164 if (argc > 0) {
1165 argc--;
1166 argv++;
1167 }
1168 break;
1169
1170 case 'C':
1171 case 'n':
1172 case 'm':
1173 case 'N':
1174 case 'L':
1175 case 'f':
1176 case 'p':
1177 case 'S':
1178 /* these options have only 1 parameter which must be copied and can start with a '-' */
1179 *newargv++ = *argv++;
1180 argc--;
1181 if (argc == 0)
1182 goto error;
1183 *newargv++ = *argv++;
1184 argc--;
1185 break;
1186 default:
1187 /* for other options just copy them without parameters, this is also done
1188 * for options like "--foo", but this will fail in the argument parser.
1189 * */
1190 *newargv++ = *argv++;
1191 argc--;
1192 break;
1193 }
William Lallemand73b85e72017-06-01 17:38:51 +02001194 }
1195 }
William Lallemand73b85e72017-06-01 17:38:51 +02001196 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001197
William Lallemanddf6c5a82020-06-04 17:40:23 +02001198 return retargv;
1199
1200error:
1201 free(retargv);
1202 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001203}
1204
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001205
1206/* Performs basic random seed initialization. The main issue with this is that
1207 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1208 * which means that there will only be 4 billion possible random sequences once
1209 * srandom() is called, regardless of the internal state. Not calling it is
1210 * even worse as we'll always produce the same randoms sequences. What we do
1211 * here is to create an initial sequence from various entropy sources, hash it
1212 * using SHA1 and keep the resulting 160 bits available globally.
1213 *
1214 * We initialize the current process with the first 32 bits before starting the
1215 * polling loop, where all this will be changed to have process specific and
1216 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001217 *
1218 * Before starting threads, it's still possible to call random() as srandom()
1219 * is initialized from this, but after threads and/or processes are started,
1220 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001221 */
1222static void ha_random_boot(char *const *argv)
1223{
1224 unsigned char message[256];
1225 unsigned char *m = message;
1226 struct timeval tv;
1227 blk_SHA_CTX ctx;
1228 unsigned long l;
1229 int fd;
1230 int i;
1231
1232 /* start with current time as pseudo-random seed */
1233 gettimeofday(&tv, NULL);
1234 write_u32(m, tv.tv_sec); m += 4;
1235 write_u32(m, tv.tv_usec); m += 4;
1236
1237 /* PID and PPID add some OS-based randomness */
1238 write_u16(m, getpid()); m += 2;
1239 write_u16(m, getppid()); m += 2;
1240
1241 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1242 fd = open("/dev/urandom", O_RDONLY);
1243 if (fd >= 0) {
1244 i = read(fd, m, 20);
1245 if (i > 0)
1246 m += i;
1247 close(fd);
1248 }
1249
1250 /* take up to 160 bits bytes from openssl (non-blocking) */
1251#ifdef USE_OPENSSL
1252 if (RAND_bytes(m, 20) == 1)
1253 m += 20;
1254#endif
1255
1256 /* take 160 bits from existing random in case it was already initialized */
1257 for (i = 0; i < 5; i++) {
1258 write_u32(m, random());
1259 m += 4;
1260 }
1261
1262 /* stack address (benefit form operating system's ASLR) */
1263 l = (unsigned long)&m;
1264 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1265
1266 /* argv address (benefit form operating system's ASLR) */
1267 l = (unsigned long)&argv;
1268 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1269
1270 /* use tv_usec again after all the operations above */
1271 gettimeofday(&tv, NULL);
1272 write_u32(m, tv.tv_usec); m += 4;
1273
1274 /*
1275 * At this point, ~84-92 bytes have been used
1276 */
1277
1278 /* finish with the hostname */
1279 strncpy((char *)m, hostname, message + sizeof(message) - m);
1280 m += strlen(hostname);
1281
1282 /* total message length */
1283 l = m - message;
1284
1285 memset(&ctx, 0, sizeof(ctx));
1286 blk_SHA1_Init(&ctx);
1287 blk_SHA1_Update(&ctx, message, l);
1288 blk_SHA1_Final(boot_seed, &ctx);
1289
1290 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001291 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001292}
1293
Willy Tarreau5a023f02019-03-01 14:19:31 +01001294/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1295 * setting, and returns it. It may return -1 meaning "unlimited" if some
1296 * unlimited proxies have been found and the global.maxconn value is not yet
1297 * set. It may also return a value greater than maxconn if it's not yet set.
1298 * Note that a value of zero means there is no need for pipes. -1 is never
1299 * returned if global.maxconn is valid.
1300 */
1301static int compute_ideal_maxpipes()
1302{
1303 struct proxy *cur;
1304 int nbfe = 0, nbbe = 0;
1305 int unlimited = 0;
1306 int pipes;
1307 int max;
1308
1309 for (cur = proxies_list; cur; cur = cur->next) {
1310 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1311 if (cur->cap & PR_CAP_FE) {
1312 max = cur->maxconn;
1313 nbfe += max;
1314 if (!max) {
1315 unlimited = 1;
1316 break;
1317 }
1318 }
1319 if (cur->cap & PR_CAP_BE) {
1320 max = cur->fullconn ? cur->fullconn : global.maxconn;
1321 nbbe += max;
1322 if (!max) {
1323 unlimited = 1;
1324 break;
1325 }
1326 }
1327 }
1328 }
1329
1330 pipes = MAX(nbfe, nbbe);
1331 if (global.maxconn) {
1332 if (pipes > global.maxconn || unlimited)
1333 pipes = global.maxconn;
1334 } else if (unlimited) {
1335 pipes = -1;
1336 }
1337
1338 return pipes >= 4 ? pipes / 4 : pipes;
1339}
1340
Willy Tarreauac350932019-03-01 15:43:14 +01001341/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1342 * rlimits and computes an ideal maxconn. It's meant to be called only when
1343 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001344 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1345 * default 100) is returned as it is expected that it will even run on tight
1346 * environments, and will maintain compatibility with previous packages that
1347 * used to rely on this value as the default one. The system will emit a
1348 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001349 */
1350static int compute_ideal_maxconn()
1351{
1352 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1353 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1354 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001355 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001356 int maxconn;
1357
1358 /* we have to take into account these elements :
1359 * - number of engine_fds, which inflates the number of FD needed per
1360 * connection by this number.
1361 * - number of pipes per connection on average : for the unlimited
1362 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1363 * fixed value of 2*pipes.
1364 * - two FDs per connection
1365 */
1366
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02001367 if (global.fd_hard_limit && remain > global.fd_hard_limit)
1368 remain = global.fd_hard_limit;
1369
Willy Tarreauac350932019-03-01 15:43:14 +01001370 /* subtract listeners and checks */
1371 remain -= global.maxsock;
1372
Willy Tarreau3f200852019-03-14 19:13:17 +01001373 /* one epoll_fd/kqueue_fd per thread */
1374 remain -= global.nbthread;
1375
1376 /* one wake-up pipe (2 fd) per thread */
1377 remain -= 2 * global.nbthread;
1378
Willy Tarreauac350932019-03-01 15:43:14 +01001379 /* Fixed pipes values : we only subtract them if they're not larger
1380 * than the remaining FDs because pipes are optional.
1381 */
1382 if (pipes >= 0 && pipes * 2 < remain)
1383 remain -= pipes * 2;
1384
1385 if (pipes < 0) {
1386 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1387 * = maxconn * (2 + 0.5 + engine_fds)
1388 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1389 */
1390 maxconn = 2 * remain / (5 + 2 * engine_fds);
1391 } else {
1392 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1393 * = maxconn * (2 + engine_fds)
1394 */
1395 maxconn = remain / (2 + engine_fds);
1396 }
1397
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001398 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001399}
1400
Willy Tarreaua409f302020-03-10 17:08:53 +01001401/* computes the estimated maxsock value for the given maxconn based on the
1402 * possibly set global.maxpipes and existing partial global.maxsock. It may
1403 * temporarily change global.maxconn for the time needed to propagate the
1404 * computations, and will reset it.
1405 */
1406static int compute_ideal_maxsock(int maxconn)
1407{
1408 int maxpipes = global.maxpipes;
1409 int maxsock = global.maxsock;
1410
1411
1412 if (!maxpipes) {
1413 int old_maxconn = global.maxconn;
1414
1415 global.maxconn = maxconn;
1416 maxpipes = compute_ideal_maxpipes();
1417 global.maxconn = old_maxconn;
1418 }
1419
1420 maxsock += maxconn * 2; /* each connection needs two sockets */
1421 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1422 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1423 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1424
1425 /* compute fd used by async engines */
1426 if (global.ssl_used_async_engines) {
1427 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1428
1429 maxsock += maxconn * sides * global.ssl_used_async_engines;
1430 }
1431 return maxsock;
1432}
1433
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001434/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001435 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1436 * value is accepted, non-zero otherwise. This is used to determine if an
1437 * automatic limit may be applied or not. When it is not, the caller knows that
1438 * the highest we can do is the rlim_max at boot. In case of error, we return
1439 * that the setting is possible, so that we defer the error processing to the
1440 * final stage in charge of enforcing this.
1441 */
1442static int check_if_maxsock_permitted(int maxsock)
1443{
1444 struct rlimit orig_limit, test_limit;
1445 int ret;
1446
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02001447 if (global.fd_hard_limit && maxsock > global.fd_hard_limit)
1448 return 0;
1449
Willy Tarreau304e17e2020-03-10 17:54:54 +01001450 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1451 return 1;
1452
1453 /* don't go further if we can't even set to what we have */
1454 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1455 return 1;
1456
1457 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1458 test_limit.rlim_cur = test_limit.rlim_max;
1459 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1460
1461 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1462 return 1;
1463
1464 return ret == 0;
1465}
1466
Willy Tarreau34527d52022-02-17 17:45:58 +01001467/* This performs th every basic early initialization at the end of the PREPARE
1468 * init stage. It may only assume that list heads are initialized, but not that
1469 * anything else is correct. It will initialize a number of variables that
1470 * depend on command line and will pre-parse the command line. If it fails, it
1471 * directly exits.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001472 */
Willy Tarreau34527d52022-02-17 17:45:58 +01001473static void init_early(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001474{
Kevinm48936af2010-12-22 16:08:21 +00001475 char *progname;
Willy Tarreau34527d52022-02-17 17:45:58 +01001476 char *tmp;
1477 int len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001478
Willy Tarreau34527d52022-02-17 17:45:58 +01001479 /* First, let's initialize most global variables */
1480 totalconn = actconn = listeners = stopping = 0;
1481 killed = pid = 0;
1482
1483 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
1484 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Christopher Faulete3a5e352017-10-24 13:53:54 +02001485 global.mode = MODE_STARTING;
William Lallemand73b85e72017-06-01 17:38:51 +02001486
Willy Tarreau34527d52022-02-17 17:45:58 +01001487 /* if we were in mworker mode, we should restart in mworker mode */
1488 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1489 global.mode |= MODE_MWORKER;
David du Colombier7af46052012-05-16 14:16:48 +02001490
Willy Tarreau34527d52022-02-17 17:45:58 +01001491 /* initialize date, time, and pid */
1492 tzset();
1493 clock_init_process_date();
1494 start_date = now;
1495 pid = getpid();
1496
1497 /* Set local host name and adjust some environment variables.
1498 * NB: POSIX does not make it mandatory for gethostname() to
1499 * NULL-terminate the string in case of truncation, and at least
1500 * FreeBSD appears not to do it.
Emeric Brun2b920a12010-09-23 18:30:22 +02001501 */
1502 memset(hostname, 0, sizeof(hostname));
1503 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001504
Willy Tarreau34527d52022-02-17 17:45:58 +01001505 /* preset some environment variables */
1506 localpeer = strdup(hostname);
1507 if (!localpeer || setenv("HAPROXY_LOCALPEER", localpeer, 1) < 0) {
Dragan Dosen4f014152020-06-18 16:56:47 +02001508 ha_alert("Cannot allocate memory for local peer.\n");
1509 exit(EXIT_FAILURE);
1510 }
Emeric Brun2b920a12010-09-23 18:30:22 +02001511
Willy Tarreau34527d52022-02-17 17:45:58 +01001512 /* Some CPU affinity stuff may have to be initialized */
1513#ifdef USE_CPU_AFFINITY
1514 {
1515 int i;
1516 ha_cpuset_zero(&cpu_map.proc);
1517 ha_cpuset_zero(&cpu_map.proc_t1);
1518 for (i = 0; i < MAX_THREADS; ++i) {
1519 ha_cpuset_zero(&cpu_map.thread[i]);
1520 }
1521 }
1522#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001523
Willy Tarreau34527d52022-02-17 17:45:58 +01001524 /* extract the program name from argv[0], it will be used for the logs
1525 * and error messages.
1526 */
1527 progname = *argv;
1528 while ((tmp = strchr(progname, '/')) != NULL)
1529 progname = tmp + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001530
Willy Tarreau34527d52022-02-17 17:45:58 +01001531 len = strlen(progname);
1532 progname = strdup(progname);
1533 if (!progname) {
1534 ha_alert("Cannot allocate memory for log_tag.\n");
1535 exit(EXIT_FAILURE);
1536 }
Willy Tarreau84310e22014-02-14 11:59:04 +01001537
Willy Tarreau34527d52022-02-17 17:45:58 +01001538 chunk_initlen(&global.log_tag, progname, len, len);
1539}
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001540
Willy Tarreau392524d2022-02-17 18:10:36 +01001541/* handles program arguments. Very minimal parsing is performed, variables are
1542 * fed with some values, and lists are completed with other ones. In case of
1543 * error, it will exit.
Willy Tarreau34527d52022-02-17 17:45:58 +01001544 */
Willy Tarreau392524d2022-02-17 18:10:36 +01001545static void init_args(int argc, char **argv)
Willy Tarreau34527d52022-02-17 17:45:58 +01001546{
Willy Tarreau34527d52022-02-17 17:45:58 +01001547 char *progname = global.log_tag.area;
Willy Tarreau392524d2022-02-17 18:10:36 +01001548 char *err_msg = NULL;
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001549
Willy Tarreau34527d52022-02-17 17:45:58 +01001550 /* pre-fill in the global tuning options before we let the cmdline
1551 * change them.
1552 */
Willy Tarreau43b78992009-01-25 15:42:27 +01001553 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001554#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001555 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001556#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001557#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001558 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001560#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001561 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001562#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001563#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001564 global.tune.options |= GTUNE_USE_EVPORTS;
1565#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001566#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001567 global.tune.options |= GTUNE_USE_SPLICE;
1568#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001569#if defined(USE_GETADDRINFO)
1570 global.tune.options |= GTUNE_USE_GAI;
1571#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001572#if defined(SO_REUSEPORT)
1573 global.tune.options |= GTUNE_USE_REUSEPORT;
1574#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001575#ifdef USE_THREAD
1576 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1577#endif
William Dauchya5194602020-03-28 19:29:58 +01001578 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579
Willy Tarreau392524d2022-02-17 18:10:36 +01001580 /* keep a copy of original arguments for the master process */
1581 old_argv = copy_argv(argc, argv);
1582 if (!old_argv) {
1583 ha_alert("failed to copy argv.\n");
1584 exit(EXIT_FAILURE);
1585 }
1586
1587 /* skip program name and start */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588 argc--; argv++;
1589 while (argc > 0) {
1590 char *flag;
1591
1592 if (**argv == '-') {
1593 flag = *argv+1;
1594
1595 /* 1 arg */
1596 if (*flag == 'v') {
1597 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001598 if (flag[1] == 'v') /* -vv */
1599 display_build_opts();
Tim Duesterhus77b3db02022-04-27 00:08:11 +02001600 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001602#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001604 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001606#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001608 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001610#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001611 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001612 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001613#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001614#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001615 else if (*flag == 'd' && flag[1] == 'v')
1616 global.tune.options &= ~GTUNE_USE_EVPORTS;
1617#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001618#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001619 else if (*flag == 'd' && flag[1] == 'S')
1620 global.tune.options &= ~GTUNE_USE_SPLICE;
1621#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001622#if defined(USE_GETADDRINFO)
1623 else if (*flag == 'd' && flag[1] == 'G')
1624 global.tune.options &= ~GTUNE_USE_GAI;
1625#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001626#if defined(SO_REUSEPORT)
1627 else if (*flag == 'd' && flag[1] == 'R')
1628 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1629#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001630 else if (*flag == 'd' && flag[1] == 'V')
1631 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001632 else if (*flag == 'V')
1633 arg_mode |= MODE_VERBOSE;
1634 else if (*flag == 'd' && flag[1] == 'b')
1635 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001636 else if (*flag == 'd' && flag[1] == 'D')
1637 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001638 else if (*flag == 'd' && flag[1] == 'W')
1639 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreauef301b72022-02-23 14:15:18 +01001640 else if (*flag == 'd' && flag[1] == 'M') {
Willy Tarreau1408b1f2022-02-18 18:54:40 +01001641 int ret = pool_parse_debugging(flag + 2, &err_msg);
1642
1643 if (ret <= -1) {
1644 if (ret < -1)
1645 ha_alert("-dM: %s\n", err_msg);
1646 else
1647 printf("%s\n", err_msg);
1648 ha_free(&err_msg);
1649 exit(ret < -1 ? EXIT_FAILURE : 0);
1650 } else if (ret == 0) {
1651 ha_warning("-dM: %s\n", err_msg);
1652 ha_free(&err_msg);
1653 }
Willy Tarreauef301b72022-02-23 14:15:18 +01001654 }
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001655 else if (*flag == 'd' && flag[1] == 'r')
1656 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreau654726d2021-12-28 15:43:11 +01001657#if defined(HA_HAVE_DUMP_LIBS)
1658 else if (*flag == 'd' && flag[1] == 'L')
1659 arg_mode |= MODE_DUMP_LIBS;
1660#endif
Willy Tarreau76871a42022-03-08 16:01:40 +01001661 else if (*flag == 'd' && flag[1] == 'K') {
1662 arg_mode |= MODE_DUMP_KWD;
1663 kwd_dump = flag + 2;
1664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001665 else if (*flag == 'd')
1666 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001667 else if (*flag == 'c' && flag[1] == 'c') {
1668 arg_mode |= MODE_CHECK_CONDITION;
1669 argv++;
1670 argc--;
1671 check_condition = *argv;
1672 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001673 else if (*flag == 'c')
1674 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001675 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001676 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001677 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001678 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001679#if defined(USE_SYSTEMD)
1680 global.tune.options |= GTUNE_USE_SYSTEMD;
1681#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001682 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 +01001683 usage(progname);
1684#endif
1685 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001686 else if (*flag == 'W')
1687 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001688 else if (*flag == 'q')
1689 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001690 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001691 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001692 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001693 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001694 }
William Lallemand4fc09692017-06-19 16:37:19 +02001695 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001696 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001697 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001698
Olivier Houchardf73629d2017-04-05 22:33:04 +02001699 argv++;
1700 argc--;
1701 }
William Lallemande7361152018-10-26 14:47:36 +02001702 else if (*flag == 'S') {
1703 struct wordlist *c;
1704
William Lallemanda6b32492020-06-04 23:49:20 +02001705 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001706 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1707 usage(progname);
1708 }
1709 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1710 ha_alert("Cannot allocate memory\n");
1711 exit(EXIT_FAILURE);
1712 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001713 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001714
1715 argv++;
1716 argc--;
1717 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001718 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1719 /* list of pids to finish ('f') or terminate ('t') */
1720
1721 if (flag[1] == 'f')
1722 oldpids_sig = SIGUSR1; /* finish then exit */
1723 else
1724 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001725 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001726 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001727 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1728 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001729 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001730 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001731 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001732 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001733 errno = 0;
1734 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1735 if (errno) {
1736 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1737 flag,
1738 *argv, strerror(errno));
1739 exit(1);
1740 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001741 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001742 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001743 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1744 flag, endptr);
1745 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001746 }
Chris Lane236062f2018-02-05 23:15:44 +00001747 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001748 if (oldpids[nb_oldpids] <= 0)
1749 usage(progname);
1750 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001751 }
1752 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001753 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1754 /* now that's a cfgfile list */
1755 argv++; argc--;
1756 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001757 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001758 ha_alert("Cannot load configuration file/directory %s : %s\n",
1759 *argv,
1760 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001761 exit(1);
1762 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001763 argv++; argc--;
1764 }
1765 break;
1766 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001767 else { /* >=2 args */
1768 argv++; argc--;
1769 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001770 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771
1772 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001773 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001774 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001775 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001777 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001778 free(localpeer);
1779 if ((localpeer = strdup(*argv)) == NULL) {
1780 ha_alert("Cannot allocate memory for local peer.\n");
1781 exit(EXIT_FAILURE);
1782 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001783 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001784 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001785 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001786 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001787 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001788 ha_alert("Cannot load configuration file/directory %s : %s\n",
1789 *argv,
1790 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001791 exit(1);
1792 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001793 break;
Willy Tarreau392524d2022-02-17 18:10:36 +01001794 case 'p' :
1795 free(global.pidfile);
1796 if ((global.pidfile = strdup(*argv)) == NULL) {
1797 ha_alert("Cannot allocate memory for pidfile.\n");
1798 exit(EXIT_FAILURE);
1799 }
1800 break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001801 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802 }
1803 }
1804 }
1805 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001806 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001807 argv++; argc--;
1808 }
Willy Tarreau392524d2022-02-17 18:10:36 +01001809 free(err_msg);
1810}
1811
Willy Tarreau76871a42022-03-08 16:01:40 +01001812/* call the various keyword dump functions based on the comma-delimited list of
1813 * classes in kwd_dump.
1814 */
1815static void dump_registered_keywords(void)
1816{
1817 char *end;
1818 int all __maybe_unused = 0;
1819
1820 for (; kwd_dump && *kwd_dump; kwd_dump = end) {
1821 end = strchr(kwd_dump, ',');
1822 if (end)
1823 *(end++) = 0;
1824
1825 if (strcmp(kwd_dump, "help") == 0) {
1826 printf("# List of supported keyword classes:\n");
1827 printf("all: list all keywords\n");
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001828 printf("acl: ACL keywords\n");
Willy Tarreauca1acd62022-03-29 15:02:44 +02001829 printf("cfg: configuration keywords\n");
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001830 printf("cli: CLI keywords\n");
Willy Tarreau29d799d2022-03-29 16:59:49 +02001831 printf("cnv: sample converter keywords\n");
Willy Tarreau3b65e142022-03-29 15:03:09 +02001832 printf("flt: filter names\n");
Willy Tarreauf78813f2022-03-29 16:51:29 +02001833 printf("smp: sample fetch functions\n");
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001834 printf("svc: service names\n");
Willy Tarreau76871a42022-03-08 16:01:40 +01001835 continue;
1836 }
1837 else if (strcmp(kwd_dump, "all") == 0) {
1838 all = 1;
1839 }
Willy Tarreauca1acd62022-03-29 15:02:44 +02001840
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001841 if (all || strcmp(kwd_dump, "acl") == 0) {
1842 printf("# List of registered ACL keywords:\n");
1843 acl_dump_kwd();
1844 }
1845
Willy Tarreauca1acd62022-03-29 15:02:44 +02001846 if (all || strcmp(kwd_dump, "cfg") == 0) {
1847 printf("# List of registered configuration keywords:\n");
1848 cfg_dump_registered_keywords();
1849 }
Willy Tarreau3b65e142022-03-29 15:03:09 +02001850
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001851 if (all || strcmp(kwd_dump, "cli") == 0) {
1852 printf("# List of registered CLI keywords:\n");
1853 cli_list_keywords();
1854 }
1855
Willy Tarreau29d799d2022-03-29 16:59:49 +02001856 if (all || strcmp(kwd_dump, "cnv") == 0) {
1857 printf("# List of registered sample converter functions:\n");
1858 smp_dump_conv_kw();
1859 }
1860
Willy Tarreau3b65e142022-03-29 15:03:09 +02001861 if (all || strcmp(kwd_dump, "flt") == 0) {
1862 printf("# List of registered filter names:\n");
1863 flt_dump_kws(NULL);
1864 }
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001865
Willy Tarreauf78813f2022-03-29 16:51:29 +02001866 if (all || strcmp(kwd_dump, "smp") == 0) {
1867 printf("# List of registered sample fetch functions:\n");
1868 smp_dump_fetch_kw();
1869 }
1870
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001871 if (all || strcmp(kwd_dump, "svc") == 0) {
1872 printf("# List of registered service names:\n");
1873 list_services(NULL);
1874 }
Willy Tarreau76871a42022-03-08 16:01:40 +01001875 }
1876}
1877
Willy Tarreau392524d2022-02-17 18:10:36 +01001878/*
1879 * This function initializes all the necessary variables. It only returns
1880 * if everything is OK. If something fails, it exits.
1881 */
1882static void init(int argc, char **argv)
1883{
1884 char *progname = global.log_tag.area;
1885 int err_code = 0;
1886 struct wordlist *wl;
1887 struct proxy *px;
1888 struct post_check_fct *pcf;
William Lallemandb53eb872022-04-21 18:02:53 +02001889 struct pre_check_fct *prcf;
Willy Tarreau392524d2022-02-17 18:10:36 +01001890 int ideal_maxconn;
1891
1892 if (!init_trash_buffers(1)) {
1893 ha_alert("failed to initialize trash buffers.\n");
1894 exit(1);
1895 }
1896
1897 if (init_acl() != 0)
1898 exit(1);
1899
1900 /* Initialise lua. */
1901 hlua_init();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902
Christopher Faulete3a5e352017-10-24 13:53:54 +02001903 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001904 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Willy Tarreau76871a42022-03-08 16:01:40 +01001905 | MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS | MODE_DUMP_KWD));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001906
William Lallemand944e6192018-11-21 15:48:31 +01001907 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001908 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001909 global.mode |= MODE_MWORKER_WAIT;
1910 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001911 }
1912
Willy Tarreau26146192021-07-21 10:01:36 +02001913 if ((global.mode & (MODE_MWORKER | MODE_CHECK | MODE_CHECK_CONDITION)) == MODE_MWORKER &&
1914 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001915 atexit_flag = 1;
1916 atexit(reexec_on_failure);
1917 }
1918
Willy Tarreau576132e2011-09-10 19:26:56 +02001919 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001920 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001921 exit(1);
1922 }
1923
Amaury Denoyelle11124302021-06-04 18:22:08 +02001924 usermsgs_clr("config");
1925
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001926 if (global.mode & MODE_CHECK_CONDITION) {
1927 int result;
1928
1929 uint32_t err;
1930 const char *errptr;
1931 char *errmsg = NULL;
1932
1933 char *args[MAX_LINE_ARGS+1];
1934 int arg = sizeof(args) / sizeof(*args);
William Lallemand89e236f2022-05-06 17:22:36 +02001935 size_t outlen;
Willy Tarreauc8194c32021-07-16 16:38:58 +02001936 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001937
William Lallemand89e236f2022-05-06 17:22:36 +02001938 if (!check_condition)
1939 usage(progname);
1940
1941 outlen = strlen(check_condition) + 1;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001942 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02001943 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001944 &errptr);
1945
1946 if (err & PARSE_ERR_QUOTE) {
1947 ha_alert("Syntax Error in condition: Unmatched quote.\n");
1948 exit(2);
1949 }
1950
1951 if (err & PARSE_ERR_HEX) {
1952 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
1953 exit(2);
1954 }
1955
1956 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
1957 ha_alert("Error in condition: Line too long.\n");
1958 exit(2);
1959 }
1960
Willy Tarreauc8194c32021-07-16 16:38:58 +02001961 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001962 ha_alert("Error in condition: Too many words.\n");
1963 exit(2);
1964 }
1965
1966 if (err) {
1967 ha_alert("Unhandled error in condition, please report this to the developers.\n");
1968 exit(2);
1969 }
1970
Willy Tarreauc8194c32021-07-16 16:38:58 +02001971 /* remerge all words into a single expression */
1972 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
1973 ;
1974
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001975 result = cfg_eval_condition(args, &errmsg, &errptr);
1976
1977 if (result < 0) {
1978 if (errmsg)
1979 ha_alert("Failed to evaluate condition: %s\n", errmsg);
1980
1981 exit(2);
1982 }
1983
1984 exit(result ? 0 : 1);
1985 }
1986
William Lallemand944e6192018-11-21 15:48:31 +01001987 /* in wait mode, we don't try to read the configuration files */
1988 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001989 char *env_cfgfiles = NULL;
1990 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001991
William Lallemand944e6192018-11-21 15:48:31 +01001992 /* handle cfgfiles that are actually directories */
1993 cfgfiles_expand_directories();
1994
1995 if (LIST_ISEMPTY(&cfg_cfgfiles))
1996 usage(progname);
1997
1998
1999 list_for_each_entry(wl, &cfg_cfgfiles, list) {
2000 int ret;
2001
Christopher Faulet4e366822021-01-12 18:57:38 +01002002 if (env_err == 0) {
2003 if (!memprintf(&env_cfgfiles, "%s%s%s",
2004 (env_cfgfiles ? env_cfgfiles : ""),
2005 (env_cfgfiles ? ";" : ""), wl->s))
2006 env_err = 1;
2007 }
William Lallemand7b302d82019-05-20 11:15:37 +02002008
William Lallemand944e6192018-11-21 15:48:31 +01002009 ret = readcfgfile(wl->s);
2010 if (ret == -1) {
2011 ha_alert("Could not open configuration file %s : %s\n",
2012 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01002013 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002014 exit(1);
2015 }
2016 if (ret & (ERR_ABORT|ERR_FATAL))
2017 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
2018 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01002019 if (err_code & ERR_ABORT) {
2020 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002021 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01002022 }
Willy Tarreauc4382422009-12-06 13:10:44 +01002023 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02002024
William Lallemand944e6192018-11-21 15:48:31 +01002025 /* do not try to resolve arguments nor to spot inconsistencies when
2026 * the configuration contains fatal errors caused by files not found
2027 * or failed memory allocations.
2028 */
2029 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2030 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01002031 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002032 exit(1);
2033 }
Christopher Faulet4e366822021-01-12 18:57:38 +01002034 if (env_err) {
2035 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
2036 exit(1);
2037 }
2038 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
2039 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02002040
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02002041 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002042 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01002043 struct mworker_proc *tmproc;
2044
William Lallemand482f9a92019-04-12 16:15:00 +02002045 setenv("HAPROXY_MWORKER", "1", 1);
2046
William Lallemand16dd1b32018-11-19 18:46:18 +01002047 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
2048
William Lallemand56be0e02022-01-28 21:11:41 +01002049 tmproc = mworker_proc_new();
William Lallemand16dd1b32018-11-19 18:46:18 +01002050 if (!tmproc) {
2051 ha_alert("Cannot allocate process structures.\n");
2052 exit(EXIT_FAILURE);
2053 }
William Lallemand8f7069a2019-04-12 16:09:23 +02002054 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01002055 tmproc->pid = pid;
2056 tmproc->timestamp = start_date.tv_sec;
William Lallemand16dd1b32018-11-19 18:46:18 +01002057 proc_self = tmproc;
2058
Willy Tarreau2b718102021-04-21 07:32:39 +02002059 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01002060 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002061
William Lallemand56be0e02022-01-28 21:11:41 +01002062 tmproc = mworker_proc_new();
Willy Tarreau6185a032021-06-15 08:02:06 +02002063 if (!tmproc) {
2064 ha_alert("Cannot allocate process structures.\n");
2065 exit(EXIT_FAILURE);
2066 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002067 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
William Lallemandce83b4a2018-10-26 14:47:30 +02002068
Willy Tarreau6185a032021-06-15 08:02:06 +02002069 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
2070 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02002071 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002072
2073 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01002074 }
2075 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
2076 struct wordlist *it, *c;
2077
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02002078 /* get the info of the children in the env */
2079 if (mworker_env_to_proc_list() < 0) {
2080 exit(EXIT_FAILURE);
2081 }
William Lallemande7361152018-10-26 14:47:36 +02002082
William Lallemand550db6d2018-11-06 17:37:12 +01002083 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02002084
William Lallemand550db6d2018-11-06 17:37:12 +01002085 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02002086 ha_alert("Can't create the master's CLI.\n");
2087 exit(EXIT_FAILURE);
2088 }
William Lallemande7361152018-10-26 14:47:36 +02002089
William Lallemand550db6d2018-11-06 17:37:12 +01002090 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
2091
2092 if (mworker_cli_proxy_new_listener(c->s) < 0) {
2093 ha_alert("Can't create the master's CLI.\n");
2094 exit(EXIT_FAILURE);
2095 }
Willy Tarreau2b718102021-04-21 07:32:39 +02002096 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01002097 free(c->s);
2098 free(c);
2099 }
2100 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002101 }
2102
Eric Salama5ba83352021-03-16 15:11:17 +01002103 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
2104 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
2105 }
2106
Christopher Faulet27c8d202021-10-13 09:50:53 +02002107 /* destroy unreferenced defaults proxies */
2108 proxy_destroy_all_unref_defaults();
2109
William Lallemandb53eb872022-04-21 18:02:53 +02002110 list_for_each_entry(prcf, &pre_check_list, list)
2111 err_code |= prcf->fct();
Willy Tarreaue90904d2021-02-12 14:08:31 +01002112
William Lallemand8b9a2df2022-05-04 14:29:46 +02002113 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2114 ha_alert("Fatal errors found in configuration.\n");
2115 exit(1);
2116 }
2117
Willy Tarreaubb925012009-07-23 13:36:36 +02002118 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02002119 for (px = proxies_list; px; px = px->next) {
2120 struct server *srv;
2121 struct post_proxy_check_fct *ppcf;
2122 struct post_server_check_fct *pscf;
2123
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002124 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002125 continue;
2126
Christopher Fauletc1692962019-08-12 09:51:07 +02002127 list_for_each_entry(pscf, &post_server_check_list, list) {
2128 for (srv = px->srv; srv; srv = srv->next)
2129 err_code |= pscf->fct(srv);
2130 }
2131 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2132 err_code |= ppcf->fct(px);
2133 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002134 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002135 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002136 exit(1);
2137 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002138
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002139 err_code |= pattern_finalize_config();
2140 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2141 ha_alert("Failed to finalize pattern config.\n");
2142 exit(1);
2143 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002144
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002145 if (global.rlimit_memmax_all)
2146 global.rlimit_memmax = global.rlimit_memmax_all;
2147
Willy Tarreaue5733232019-05-22 19:24:06 +02002148#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002149 err_code |= netns_init();
2150 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002151 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002152 exit(1);
2153 }
2154#endif
2155
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002156 /* Apply server states */
2157 apply_server_state();
2158
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002159 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002160 srv_compute_all_admin_states(px);
2161
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002162 /* Apply servers' configured address */
2163 err_code |= srv_init_addr();
2164 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002165 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002166 exit(1);
2167 }
2168
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002169 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2170 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2171 exit(1);
2172 }
2173
Willy Tarreau654726d2021-12-28 15:43:11 +01002174#if defined(HA_HAVE_DUMP_LIBS)
2175 if (global.mode & MODE_DUMP_LIBS) {
2176 qfprintf(stdout, "List of loaded object files:\n");
2177 chunk_reset(&trash);
2178 if (dump_libs(&trash, 0))
2179 printf("%s", trash.area);
2180 }
2181#endif
2182
Willy Tarreau76871a42022-03-08 16:01:40 +01002183 if (global.mode & MODE_DUMP_KWD)
2184 dump_registered_keywords();
2185
Willy Tarreaubaaee002006-06-26 02:48:02 +02002186 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002187 struct peers *pr;
2188 struct proxy *px;
2189
Willy Tarreaubebd2122020-04-15 16:06:11 +02002190 if (warned & WARN_ANY)
2191 qfprintf(stdout, "Warnings were found.\n");
2192
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002193 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002194 if (pr->peers_fe)
2195 break;
2196
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002197 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002198 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002199 break;
2200
Emeric Brunbc5c8212021-08-13 09:32:50 +02002201 if (!px) {
2202 /* We may only have log-forward section */
2203 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002204 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002205 break;
2206 }
2207
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002208 if (pr || px) {
2209 /* At least one peer or one listener has been found */
2210 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002211 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002212 }
2213 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2214 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002215 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002216
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002217 if (global.mode & MODE_DIAG) {
2218 cfg_run_diagnostics();
2219 }
2220
Remi Tricot-Le Breton51944462022-05-16 16:24:31 +02002221 /* Initialize the random generators */
2222#ifdef USE_OPENSSL
2223 /* Initialize SSL random generator. Must be called before chroot for
2224 * access to /dev/urandom, and before ha_random_boot() which may use
2225 * RAND_bytes().
2226 */
2227 if (!ssl_initialize_random()) {
2228 ha_alert("OpenSSL random data generator initialization failed.\n");
2229 exit(EXIT_FAILURE);
2230 }
2231#endif
2232 ha_random_boot(argv); // the argv pointer brings some kernel-fed entropy
2233
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002234 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002235 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002236
Willy Tarreaue6945732016-12-21 19:57:00 +01002237 list_for_each_entry(pcf, &post_check_list, list) {
2238 err_code |= pcf->fct();
2239 if (err_code & (ERR_ABORT|ERR_FATAL))
2240 exit(1);
2241 }
2242
Willy Tarreaubaaee002006-06-26 02:48:02 +02002243 if (cfg_maxconn > 0)
2244 global.maxconn = cfg_maxconn;
2245
Willy Tarreau4975d142021-03-13 11:00:33 +01002246 if (global.cli_fe)
2247 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002248
2249 if (cfg_peers) {
2250 /* peers also need to bypass global maxconn */
2251 struct peers *p = cfg_peers;
2252
2253 for (p = cfg_peers; p; p = p->next)
2254 if (p->peers_fe)
2255 global.maxsock += p->peers_fe->maxconn;
2256 }
2257
Willy Tarreaud0256482015-01-15 21:45:22 +01002258 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002259 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2260 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2261 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2262 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002263 *
2264 * If memmax is set, then it depends on which values are set. If
2265 * maxsslconn is set, we use memmax to determine how many cleartext
2266 * connections may be added, and set maxconn to the sum of the two.
2267 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2268 * the remaining amount of memory between memmax and the cleartext
2269 * connections. If neither are set, then it is considered that all
2270 * connections are SSL-capable, and maxconn is computed based on this,
2271 * then maxsslconn accordingly. We need to know if SSL is used on the
2272 * frontends, backends, or both, because when it's used on both sides,
2273 * we need twice the value for maxsslconn, but we only count the
2274 * handshake once since it is not performed on the two sides at the
2275 * same time (frontend-side is terminated before backend-side begins).
2276 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002277 * ssl_handshake_cost during its initialization. In any case, if
2278 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2279 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002280 */
Willy Tarreauac350932019-03-01 15:43:14 +01002281 ideal_maxconn = compute_ideal_maxconn();
2282
Willy Tarreaud0256482015-01-15 21:45:22 +01002283 if (!global.rlimit_memmax) {
2284 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002285 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002286 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2287 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2288 }
2289 }
2290#ifdef USE_OPENSSL
2291 else if (!global.maxconn && !global.maxsslconn &&
2292 (global.ssl_used_frontend || global.ssl_used_backend)) {
2293 /* memmax is set, compute everything automatically. Here we want
2294 * to ensure that all SSL connections will be served. We take
2295 * care of the number of sides where SSL is used, and consider
2296 * the worst case : SSL used on both sides and doing a handshake
2297 * simultaneously. Note that we can't have more than maxconn
2298 * handshakes at a time by definition, so for the worst case of
2299 * two SSL conns per connection, we count a single handshake.
2300 */
2301 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2302 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002303 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002304
Willy Tarreau2cb3be72022-05-24 07:43:57 +02002305 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002306 mem -= global.maxzlibmem;
2307 mem = mem * MEM_USABLE_RATIO;
2308
Willy Tarreau304e17e2020-03-10 17:54:54 +01002309 /* Principle: we test once to set maxconn according to the free
2310 * memory. If it results in values the system rejects, we try a
2311 * second time by respecting rlim_fd_max. If it fails again, we
2312 * go back to the initial value and will let the final code
2313 * dealing with rlimit report the error. That's up to 3 attempts.
2314 */
2315 do {
2316 global.maxconn = mem /
2317 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2318 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2319 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002320
Willy Tarreau304e17e2020-03-10 17:54:54 +01002321 if (retried == 1)
2322 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2323 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002324#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002325 if (global.maxconn > SYSTEM_MAXCONN)
2326 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002327#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002328 global.maxsslconn = sides * global.maxconn;
2329
2330 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2331 break;
2332 } while (retried++ < 2);
2333
Willy Tarreaud0256482015-01-15 21:45:22 +01002334 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2335 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2336 global.maxconn, global.maxsslconn);
2337 }
2338 else if (!global.maxsslconn &&
2339 (global.ssl_used_frontend || global.ssl_used_backend)) {
2340 /* memmax and maxconn are known, compute maxsslconn automatically.
2341 * maxsslconn being forced, we don't know how many of it will be
2342 * on each side if both sides are being used. The worst case is
2343 * when all connections use only one SSL instance because
2344 * handshakes may be on two sides at the same time.
2345 */
2346 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2347 int64_t mem = global.rlimit_memmax * 1048576ULL;
2348 int64_t sslmem;
2349
Willy Tarreau8e5b9582022-05-26 08:55:05 +02002350 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002351 mem -= global.maxzlibmem;
2352 mem = mem * MEM_USABLE_RATIO;
2353
Willy Tarreau87b09662015-04-03 00:22:06 +02002354 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002355 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2356 global.maxsslconn = round_2dig(global.maxsslconn);
2357
2358 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002359 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2360 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2361 "without SSL is %d, but %d was found and SSL is in use.\n",
2362 global.rlimit_memmax,
2363 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2364 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002365 exit(1);
2366 }
2367
2368 if (global.maxsslconn > sides * global.maxconn)
2369 global.maxsslconn = sides * global.maxconn;
2370
2371 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2372 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2373 }
2374#endif
2375 else if (!global.maxconn) {
2376 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2377 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2378 int64_t mem = global.rlimit_memmax * 1048576ULL;
2379 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002380 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002381
2382 if (global.ssl_used_frontend || global.ssl_used_backend)
Willy Tarreau8e5b9582022-05-26 08:55:05 +02002383 mem -= global.tune.sslcachesize * 200ULL; // about 200 bytes per SSL cache entry
Willy Tarreaud0256482015-01-15 21:45:22 +01002384
2385 mem -= global.maxzlibmem;
2386 mem = mem * MEM_USABLE_RATIO;
2387
2388 clearmem = mem;
2389 if (sides)
2390 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2391
Willy Tarreau304e17e2020-03-10 17:54:54 +01002392 /* Principle: we test once to set maxconn according to the free
2393 * memory. If it results in values the system rejects, we try a
2394 * second time by respecting rlim_fd_max. If it fails again, we
2395 * go back to the initial value and will let the final code
2396 * dealing with rlimit report the error. That's up to 3 attempts.
2397 */
2398 do {
2399 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2400 if (retried == 1)
2401 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2402 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002403#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002404 if (global.maxconn > SYSTEM_MAXCONN)
2405 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002406#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002407
Willy Tarreau304e17e2020-03-10 17:54:54 +01002408 if (clearmem <= 0 || !global.maxconn) {
2409 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2410 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2411 "is %d, but %d was found.\n",
2412 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002413 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002414 global.maxsslconn);
2415 exit(1);
2416 }
2417
2418 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2419 break;
2420 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002421
2422 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2423 if (sides && global.maxsslconn > sides * global.maxconn) {
2424 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2425 "to be limited to %d. Better reduce global.maxsslconn to get more "
2426 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2427 }
2428 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2429 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002430 }
2431
Willy Tarreaua409f302020-03-10 17:08:53 +01002432 global.maxsock = compute_ideal_maxsock(global.maxconn);
2433 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002434 if (!global.maxpipes)
2435 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002436
Olivier Houchard88698d92019-04-16 19:07:22 +02002437 /* update connection pool thresholds */
2438 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2439 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2440
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002441 proxy_adjust_all_maxconn();
2442
Willy Tarreau1db37712007-06-03 17:16:49 +02002443 if (global.tune.maxpollevents <= 0)
2444 global.tune.maxpollevents = MAX_POLL_EVENTS;
2445
Willy Tarreau060a7612021-03-10 11:06:26 +01002446 if (global.tune.runqueue_depth <= 0) {
2447 /* tests on various thread counts from 1 to 64 have shown an
2448 * optimal queue depth following roughly 1/sqrt(threads).
2449 */
2450 int s = my_flsl(global.nbthread);
2451 s += (global.nbthread / s); // roughly twice the sqrt.
2452 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2453 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002454
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002455 if (global.tune.recv_enough == 0)
2456 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2457
Willy Tarreau27a674e2009-08-17 07:23:33 +02002458 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2459 global.tune.maxrewrite = global.tune.bufsize / 2;
2460
Amaury Denoyelle11124302021-06-04 18:22:08 +02002461 usermsgs_clr(NULL);
2462
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2464 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002465 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002466 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2467 }
2468
William Lallemand095ba4c2017-06-01 17:38:50 +02002469 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002470 /* command line daemon mode inhibits foreground and debug modes mode */
2471 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002472 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002473 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002474
2475 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476
William Lallemand095ba4c2017-06-01 17:38:50 +02002477 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002478 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002479 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480 }
2481
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002482 if (global.nbthread < 1)
2483 global.nbthread = 1;
2484
Christopher Faulet3ef26392017-08-29 16:46:57 +02002485 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002486 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002487 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002488 exit(1);
2489 }
2490
Christopher Faulet96d44832017-11-14 22:02:30 +01002491 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002492 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002493 exit(1);
2494 }
2495
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002496 /*
2497 * Note: we could register external pollers here.
2498 * Built-in pollers have been registered before main().
2499 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002500
Willy Tarreau43b78992009-01-25 15:42:27 +01002501 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002502 disable_poller("kqueue");
2503
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002504 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2505 disable_poller("evports");
2506
Willy Tarreau43b78992009-01-25 15:42:27 +01002507 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002508 disable_poller("epoll");
2509
Willy Tarreau43b78992009-01-25 15:42:27 +01002510 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002511 disable_poller("poll");
2512
Willy Tarreau43b78992009-01-25 15:42:27 +01002513 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002514 disable_poller("select");
2515
2516 /* Note: we could disable any poller by name here */
2517
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002518 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002519 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002520 fprintf(stderr, "\n");
2521 list_filters(stderr);
2522 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002523
Willy Tarreau4f60f162007-04-08 16:39:58 +02002524 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002525 ha_alert("No polling mechanism available.\n"
2526 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2527 " is too low on this platform to support maxconn and the number of listeners\n"
2528 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2529 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2530 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2531 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2532 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2533 " check build settings using 'haproxy -vv'.\n\n",
2534 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002535 exit(1);
2536 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002537 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2538 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002539 }
2540
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002541 if (!global.node)
2542 global.node = strdup(hostname);
2543
Willy Tarreau02b092f2020-10-07 18:36:54 +02002544 /* stop disabled proxies */
2545 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002546 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002547 stop_proxy(px);
2548 }
2549
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002550 if (!hlua_post_init())
2551 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002552}
2553
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002554void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002555{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002556 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002557 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002558 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002559 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002560 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002561 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002562 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002563 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002564 struct per_thread_init_fct *tif, *tifb;
2565 struct per_thread_deinit_fct *tdf, *tdfb;
2566 struct per_thread_alloc_fct *taf, *tafb;
2567 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002568 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002569 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002570 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreau65009eb2022-04-27 18:02:54 +02002571 struct pre_check_fct *prcf, *prcfb;
Willy Tarreau226866e2022-04-27 18:07:24 +02002572 struct cfg_postparser *pprs, *pprsb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002573 int cur_fd;
2574
2575 /* At this point the listeners state is weird:
2576 * - most listeners are still bound and referenced in their protocol
2577 * - some might be zombies that are not in their proto anymore, but
2578 * still appear in their proxy's listeners with a valid FD.
2579 * - some might be stopped and still appear in their proxy as FD #-1
2580 * - among all of them, some might be inherited hence shared and we're
2581 * not allowed to pause them or whatever, we must just close them.
2582 * - finally some are not listeners (pipes, logs, stdout, etc) and
2583 * must be left intact.
2584 *
2585 * The safe way to proceed is to unbind (and close) whatever is not yet
2586 * unbound so that no more receiver/listener remains alive. Then close
2587 * remaining listener FDs, which correspond to zombie listeners (those
2588 * belonging to disabled proxies that were in another process).
2589 * objt_listener() would be cleaner here but not converted yet.
2590 */
2591 protocol_unbind_all();
2592
2593 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002594 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002595 continue;
2596
Willy Tarreaua74cb382020-10-15 21:29:49 +02002597 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002598 struct listener *l = fdtab[cur_fd].owner;
2599
2600 BUG_ON(l->state != LI_INIT);
2601 unbind_listener(l);
2602 }
2603 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002604
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002605 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002606 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002607 /* build a list of unique uri_auths */
2608 if (!ua)
2609 ua = p->uri_auth;
2610 else {
2611 /* check if p->uri_auth is unique */
2612 for (uap = ua; uap; uap=uap->next)
2613 if (uap == p->uri_auth)
2614 break;
2615
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002616 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002617 /* add it, if it is */
2618 p->uri_auth->next = ua;
2619 ua = p->uri_auth;
2620 }
William Lallemand0f99e342011-10-12 17:50:54 +02002621 }
2622
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002623 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002625 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002626 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002627
Christopher Faulet27c8d202021-10-13 09:50:53 +02002628 /* destroy all referenced defaults proxies */
2629 proxy_destroy_all_unref_defaults();
2630
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002631 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002632 struct stat_scope *scope, *scopep;
2633
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002634 uap = ua;
2635 ua = ua->next;
2636
Willy Tarreaua534fea2008-08-03 12:19:50 +02002637 free(uap->uri_prefix);
2638 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002639 free(uap->node);
2640 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002641
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002642 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002643 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002644
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002645 scope = uap->scope;
2646 while (scope) {
2647 scopep = scope;
2648 scope = scope->next;
2649
2650 free(scopep->px_id);
2651 free(scopep);
2652 }
2653
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002654 free(uap);
2655 }
2656
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002657 userlist_free(userlist);
2658
David Carlier834cb2e2015-09-25 12:02:25 +01002659 cfg_unregister_sections();
2660
Christopher Faulet0132d062017-07-26 15:33:35 +02002661 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002662
Willy Tarreau05554e62016-12-21 20:46:26 +01002663 list_for_each_entry(pdf, &post_deinit_list, list)
2664 pdf->fct();
2665
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002666 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002667 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002668 ha_free(&global.chroot);
Frédéric Lécaille372508c2022-05-06 08:53:16 +02002669 ha_free(&global.cluster_secret);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002670 ha_free(&global.pidfile);
2671 ha_free(&global.node);
2672 ha_free(&global.desc);
2673 ha_free(&oldpids);
2674 ha_free(&old_argv);
2675 ha_free(&localpeer);
2676 ha_free(&global.server_state_base);
2677 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002678 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002679 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002680
William Lallemand0f99e342011-10-12 17:50:54 +02002681 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002682 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002683 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002684 free(log);
2685 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002686 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002687 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002688 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002689 free(wl);
2690 }
2691
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002692 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2693 if (bol->must_free)
2694 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002695 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002696 free(bol);
2697 }
2698
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002699 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002700 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002701 free(pxdf);
2702 }
2703
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002704 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002705 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002706 free(pdf);
2707 }
2708
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002709 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002710 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002711 free(srvdf);
2712 }
2713
Tim Duesterhusfc854942020-09-10 19:46:42 +02002714 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002715 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002716 free(pcf);
2717 }
2718
Tim Duesterhus34bef072020-07-04 11:49:50 +02002719 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002720 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002721 free(pscf);
2722 }
2723
Tim Duesterhus53508d62020-09-10 19:46:40 +02002724 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002725 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002726 free(ppcf);
2727 }
2728
Willy Tarreau65009eb2022-04-27 18:02:54 +02002729 list_for_each_entry_safe(prcf, prcfb, &pre_check_list, list) {
2730 LIST_DELETE(&prcf->list);
2731 free(prcf);
2732 }
2733
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002734 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002735 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002736 free(tif);
2737 }
2738
2739 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002740 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002741 free(tdf);
2742 }
2743
2744 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002745 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002746 free(taf);
2747 }
2748
2749 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002750 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002751 free(tff);
2752 }
2753
Willy Tarreau226866e2022-04-27 18:07:24 +02002754 list_for_each_entry_safe(pprs, pprsb, &postparsers, list) {
2755 LIST_DELETE(&pprs->list);
2756 free(pprs);
2757 }
2758
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002759 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002760 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002761 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002762} /* end deinit() */
2763
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002764__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002765{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002766 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002767 deinit();
2768 exit(status);
2769}
William Lallemand72160322018-11-06 17:37:16 +01002770
Willy Tarreau918ff602011-07-25 16:33:49 +02002771/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002772void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002773{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002774 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002775
Willy Tarreau55542642021-10-08 09:33:24 +02002776 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002777 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002778 wake_expired_tasks();
2779
William Lallemand1aab50b2018-06-07 09:46:01 +02002780 /* check if we caught some signals and process them in the
2781 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002782 if (signal_queue_len && tid == 0) {
2783 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002784 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002785 }
2786
2787 /* Process a few tasks */
2788 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002789
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002790 /* also stop if we failed to cleanly stop all tasks */
2791 if (killed > 1)
2792 break;
2793
Willy Tarreau10146c92015-04-13 20:44:19 +02002794 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002795 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002796 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002797 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002798 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002799 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2800 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002801 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002802 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002803 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002804 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002805 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002806 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002807
Willy Tarreau4f46a352020-03-23 09:27:28 +01002808 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002809 int i;
2810
2811 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002812 /* stop muxes before acknowledging stopping */
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002813 if (!(stopping_thread_mask & tid_bit)) {
2814 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2815 wake = 1;
2816 }
2817
Willy Tarreau1db42732021-04-06 11:44:07 +02002818 if (_HA_ATOMIC_OR_FETCH(&stopping_thread_mask, tid_bit) == tid_bit) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002819 /* notify all threads that stopping was just set */
2820 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002821 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002822 wake_thread(i);
2823 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002824 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002825
2826 /* stop when there's nothing left to do */
2827 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002828 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2829 /* wake all threads waiting on jobs==0 */
2830 for (i = 0; i < global.nbthread; i++)
2831 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2832 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002833 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002834 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002835 }
2836
Willy Tarreauc49ba522019-12-11 08:12:23 +01002837 /* If we have to sleep, measure how long */
2838 next = wake ? TICK_ETERNITY : next_timer_expiry();
2839
Willy Tarreau58b458d2008-06-29 22:40:23 +02002840 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002841 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002842
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002843 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002844 }
2845}
2846
Christopher Faulet1d17c102017-08-29 15:38:48 +02002847static void *run_thread_poll_loop(void *data)
2848{
Willy Tarreau082b6282019-05-22 14:42:12 +02002849 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002850 struct per_thread_init_fct *ptif;
2851 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002852 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002853 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002854 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2855 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002856
Willy Tarreau43ab05b2021-09-28 09:43:11 +02002857 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02002858 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02002859 clock_set_local_source();
Willy Tarreau91e6df02019-05-03 17:21:18 +02002860
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002861 /* Now, initialize one thread init at a time. This is better since
2862 * some init code is a bit tricky and may release global resources
2863 * after reallocating them locally. This will also ensure there is
2864 * no race on file descriptors allocation.
2865 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002866#ifdef USE_THREAD
2867 pthread_mutex_lock(&init_mutex);
2868#endif
2869 /* The first thread must set the number of threads left */
2870 if (!init_left)
2871 init_left = global.nbthread;
2872 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002873
Willy Tarreau55542642021-10-08 09:33:24 +02002874 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002875
Willy Tarreau082b6282019-05-22 14:42:12 +02002876 /* per-thread alloc calls performed here are not allowed to snoop on
2877 * other threads, so they are free to initialize at their own rhythm
2878 * as long as they act as if they were alone. None of them may rely
2879 * on resources initialized by the other ones.
2880 */
2881 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2882 if (!ptaf->fct()) {
2883 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002884#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002885 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002886#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02002887 exit(1);
2888 }
2889 }
2890
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002891 /* per-thread init calls performed here are not allowed to snoop on
2892 * other threads, so they are free to initialize at their own rhythm
2893 * as long as they act as if they were alone.
2894 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002895 list_for_each_entry(ptif, &per_thread_init_list, list) {
2896 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002897 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002898#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002899 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002900#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002901 exit(1);
2902 }
2903 }
2904
Willy Tarreau71092822019-06-10 09:51:04 +02002905 /* enabling protocols will result in fd_insert() calls to be performed,
2906 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002907 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002908 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002909 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002910 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002911
Willy Tarreau34a150c2019-06-11 09:16:41 +02002912#ifdef USE_THREAD
2913 pthread_cond_broadcast(&init_cond);
2914 pthread_mutex_unlock(&init_mutex);
2915
2916 /* now wait for other threads to finish starting */
2917 pthread_mutex_lock(&init_mutex);
2918 while (init_left)
2919 pthread_cond_wait(&init_cond, &init_mutex);
2920 pthread_mutex_unlock(&init_mutex);
2921#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002922
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002923#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2924 /* Let's refrain from using setuid executables. This way the impact of
2925 * an eventual vulnerability in a library remains limited. It may
2926 * impact external checks but who cares about them anyway ? In the
2927 * worst case it's possible to disable the option. Obviously we do this
2928 * in workers only. We can't hard-fail on this one as it really is
2929 * implementation dependent though we're interested in feedback, hence
2930 * the warning.
2931 */
2932 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2933 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002934 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 +01002935 ha_warning("Failed to disable setuid, please report to developers with detailed "
2936 "information about your operating system. You can silence this warning "
2937 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2938 }
2939 }
2940#endif
2941
Willy Tarreaud96f1122019-12-03 07:07:36 +01002942#if defined(RLIMIT_NPROC)
2943 /* all threads have started, it's now time to prevent any new thread
2944 * or process from starting. Obviously we do this in workers only. We
2945 * can't hard-fail on this one as it really is implementation dependent
2946 * though we're interested in feedback, hence the warning.
2947 */
2948 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2949 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2950 static int warn_fail;
2951
Willy Tarreau18515722021-04-06 11:57:41 +02002952 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002953 ha_warning("Failed to disable forks, please report to developers with detailed "
2954 "information about your operating system. You can silence this warning "
2955 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2956 }
2957 }
2958#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002959 run_poll_loop();
2960
2961 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2962 ptdf->fct();
2963
Willy Tarreau082b6282019-05-22 14:42:12 +02002964 list_for_each_entry(ptff, &per_thread_free_list, list)
2965 ptff->fct();
2966
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002967#ifdef USE_THREAD
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002968 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002969 if (tid > 0)
2970 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002971#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002972 return NULL;
2973}
Christopher Faulet1d17c102017-08-29 15:38:48 +02002974
William Dauchyf9af9d72019-11-17 15:47:16 +01002975/* set uid/gid depending on global settings */
2976static void set_identity(const char *program_name)
2977{
2978 if (global.gid) {
2979 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
2980 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
2981 " without 'uid'/'user' is generally useless.\n", program_name);
2982
2983 if (setgid(global.gid) == -1) {
2984 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
2985 protocol_unbind_all();
2986 exit(1);
2987 }
2988 }
2989
2990 if (global.uid && setuid(global.uid) == -1) {
2991 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
2992 protocol_unbind_all();
2993 exit(1);
2994 }
2995}
2996
Willy Tarreaubaaee002006-06-26 02:48:02 +02002997int main(int argc, char **argv)
2998{
2999 int err, retry;
3000 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02003001 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02003002 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
3003
3004 /* Catch forced CFLAGS that miss 2-complement integer overflow */
3005 if (intovf + 0x7FFFFFFF >= intovf) {
3006 fprintf(stderr,
3007 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
3008 "The source code was miscompiled by the compiler, which usually indicates that\n"
3009 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
3010 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
3011 "and INSTALL files to decide on the best way to pass your local build options.\n"
3012 "\nBuild options :"
3013#ifdef BUILD_TARGET
3014 "\n TARGET = " BUILD_TARGET
3015#endif
3016#ifdef BUILD_CPU
3017 "\n CPU = " BUILD_CPU
3018#endif
3019#ifdef BUILD_CC
3020 "\n CC = " BUILD_CC
3021#endif
3022#ifdef BUILD_CFLAGS
3023 "\n CFLAGS = " BUILD_CFLAGS
3024#endif
3025#ifdef BUILD_OPTIONS
3026 "\n OPTIONS = " BUILD_OPTIONS
3027#endif
3028#ifdef BUILD_DEBUG
3029 "\n DEBUG = " BUILD_DEBUG
3030#endif
3031 "\n\n");
3032 return 1;
3033 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003034
Olivier Houchard5fa300d2018-02-03 15:15:21 +01003035 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003036
Willy Tarreaubf696402019-03-01 10:09:28 +01003037 /* take a copy of initial limits before we possibly change them */
3038 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02003039
3040 if (limit.rlim_max == RLIM_INFINITY)
3041 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01003042 rlim_fd_cur_at_boot = limit.rlim_cur;
3043 rlim_fd_max_at_boot = limit.rlim_max;
3044
Willy Tarreau5794fb02018-11-25 18:43:29 +01003045 /* process all initcalls in order of potential dependency */
3046 RUN_INITCALLS(STG_PREPARE);
3047 RUN_INITCALLS(STG_LOCK);
Willy Tarreau3ebe4d92022-02-18 14:51:49 +01003048 RUN_INITCALLS(STG_REGISTER);
Willy Tarreau34527d52022-02-17 17:45:58 +01003049
3050 /* now's time to initialize early boot variables */
3051 init_early(argc, argv);
3052
Willy Tarreau18f96d02022-02-23 17:25:00 +01003053 /* handles argument parsing */
3054 init_args(argc, argv);
3055
Willy Tarreau5794fb02018-11-25 18:43:29 +01003056 RUN_INITCALLS(STG_ALLOC);
3057 RUN_INITCALLS(STG_POOL);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003058 RUN_INITCALLS(STG_INIT);
3059
Willy Tarreau34527d52022-02-17 17:45:58 +01003060 /* this is the late init where the config is parsed */
Emeric Bruncf20bf12010-10-22 16:06:11 +02003061 init(argc, argv);
Willy Tarreau34527d52022-02-17 17:45:58 +01003062
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003063 signal_register_fct(SIGQUIT, dump, SIGQUIT);
3064 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
3065 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02003066 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067
Willy Tarreaue437c442010-03-17 18:02:46 +01003068 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
3069 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
3070 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003072 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003073
Willy Tarreaudc23a922011-02-16 11:10:36 +01003074 /* ulimits */
3075 if (!global.rlimit_nofile)
3076 global.rlimit_nofile = global.maxsock;
3077
3078 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01003079 limit.rlim_cur = global.rlimit_nofile;
3080 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
3081
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003082 if ((global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit) ||
3083 setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02003084 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003085 if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
3086 limit.rlim_cur = global.fd_hard_limit;
3087
William Dauchy0fec3ab2019-10-27 20:08:11 +01003088 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3089 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
3090 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003091 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003092 }
3093 else {
3094 /* try to set it to the max possible at least */
3095 limit.rlim_cur = limit.rlim_max;
Willy Tarreau2df1fbf2022-04-25 18:02:03 +02003096 if (global.fd_hard_limit && limit.rlim_cur > global.fd_hard_limit)
3097 limit.rlim_cur = global.fd_hard_limit;
3098
William Dauchy0fec3ab2019-10-27 20:08:11 +01003099 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
3100 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02003101
William Dauchya5194602020-03-28 19:29:58 +01003102 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003103 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
3104 global.rlimit_nofile = limit.rlim_cur;
3105 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01003106 }
3107 }
3108
3109 if (global.rlimit_memmax) {
3110 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01003111 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01003112#ifdef RLIMIT_AS
3113 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003114 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3115 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3116 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003117 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003118 }
3119 else
William Dauchya5194602020-03-28 19:29:58 +01003120 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003121 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003122 }
3123#else
3124 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003125 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3126 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3127 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003128 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003129 }
3130 else
William Dauchya5194602020-03-28 19:29:58 +01003131 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003132 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003133 }
3134#endif
3135 }
3136
William Lallemandf82afbb2022-01-07 18:19:42 +01003137 /* Try to get the listeners FD from the previous process using
3138 * _getsocks on the stat socket, it must never been done in wait mode
3139 * and check mode
3140 */
3141 if (old_unixsocket &&
3142 !(global.mode & (MODE_MWORKER_WAIT|MODE_CHECK|MODE_CHECK_CONDITION))) {
William Lallemand85b0bd92017-06-01 17:38:53 +02003143 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02003144 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003145 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02003146 if (!(global.mode & MODE_MWORKER))
3147 exit(1);
3148 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02003149 }
3150 }
William Lallemand85b0bd92017-06-01 17:38:53 +02003151
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152 /* We will loop at most 100 times with 10 ms delay each time.
3153 * That's at most 1 second. We only send a signal to old pids
3154 * if we cannot grab at least one port.
3155 */
3156 retry = MAX_START_RETRIES;
3157 err = ERR_NONE;
3158 while (retry >= 0) {
3159 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003160 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003161 /* exit the loop on no error or fatal error */
3162 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003163 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003164 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003165 break;
3166
3167 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3168 * listening sockets. So on those platforms, it would be wiser to
3169 * simply send SIGUSR1, which will not be undoable.
3170 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003171 if (tell_old_pids(SIGTTOU) == 0) {
3172 /* no need to wait if we can't contact old pids */
3173 retry = 0;
3174 continue;
3175 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003176 /* give some time to old processes to stop listening */
3177 w.tv_sec = 0;
3178 w.tv_usec = 10*1000;
3179 select(0, NULL, NULL, NULL, &w);
3180 retry--;
3181 }
3182
Willy Tarreaue91bff22020-09-02 11:11:43 +02003183 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003184 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003185 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003186 if (retry != MAX_START_RETRIES && nb_oldpids) {
3187 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 exit(1);
3191 }
3192
William Lallemand944e6192018-11-21 15:48:31 +01003193 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003194 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 /* Note: we don't have to send anything to the old pids because we
3196 * never stopped them. */
3197 exit(1);
3198 }
3199
Willy Tarreaue91bff22020-09-02 11:11:43 +02003200 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003201 * the previous process gave us, we don't need them anymore
3202 */
Willy Tarreaub5101162022-01-28 18:28:18 +01003203 sock_drop_unused_old_sockets();
Willy Tarreaudd815982007-10-16 12:25:14 +02003204
Willy Tarreaubaaee002006-06-26 02:48:02 +02003205 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003206 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3207 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208
Willy Tarreaubaaee002006-06-26 02:48:02 +02003209 /* MODE_QUIET can inhibit alerts and warnings below this line */
3210
PiBa-NL149a81a2017-12-25 21:03:31 +01003211 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3212 /* either stdin/out/err are already closed or should stay as they are. */
3213 if ((global.mode & MODE_DAEMON)) {
3214 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3215 global.mode &= ~MODE_VERBOSE;
3216 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3217 }
3218 } else {
3219 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3220 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003221 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003223 }
3224
3225 /* open log & pid files before the chroot */
William Lallemand7b820a62022-02-14 09:02:14 +01003226 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) &&
3227 !(global.mode & MODE_MWORKER_WAIT) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003228 unlink(global.pidfile);
3229 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3230 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003231 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 if (nb_oldpids)
3233 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003234 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003235 exit(1);
3236 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003237 }
3238
Willy Tarreaub38651a2007-03-24 17:24:39 +01003239 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003240 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3241 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003242 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003243 exit(1);
3244 }
3245
Jackie Tapia749f74c2020-07-22 18:59:40 -05003246 /* If the user is not root, we'll still let them try the configuration
3247 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003248 */
3249 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003250 ha_warning("[%s.main()] Some options which require full privileges"
3251 " might not work well.\n"
3252 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003253
William Lallemand095ba4c2017-06-01 17:38:50 +02003254 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3255
3256 /* chroot if needed */
3257 if (global.chroot != NULL) {
3258 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003259 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003260 if (nb_oldpids)
3261 tell_old_pids(SIGTTIN);
3262 protocol_unbind_all();
3263 exit(1);
3264 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003265 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003266 }
3267
William Lallemand944e6192018-11-21 15:48:31 +01003268 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003269 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270
William Lallemand27edc4b2019-05-07 17:49:33 +02003271 /* send a SIGTERM to workers who have a too high reloads number */
3272 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3273 mworker_kill_max_reloads(SIGTERM);
3274
Willy Tarreaubaaee002006-06-26 02:48:02 +02003275 /* Note that any error at this stage will be fatal because we will not
3276 * be able to restart the old pids.
3277 */
3278
William Dauchyf9af9d72019-11-17 15:47:16 +01003279 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3280 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003281
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 /* check ulimits */
3283 limit.rlim_cur = limit.rlim_max = 0;
3284 getrlimit(RLIMIT_NOFILE, &limit);
3285 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003286 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3287 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3288 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3289 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3290 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003291 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003292 }
3293 else
3294 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003295 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003296 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3297 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298 }
3299
William Lallemand944e6192018-11-21 15:48:31 +01003300 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003301 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003302 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003303 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003304
William Lallemand095ba4c2017-06-01 17:38:50 +02003305 /*
3306 * if daemon + mworker: must fork here to let a master
3307 * process live in background before forking children
3308 */
William Lallemand73b85e72017-06-01 17:38:51 +02003309
3310 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3311 && (global.mode & MODE_MWORKER)
3312 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003313 ret = fork();
3314 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003315 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003316 protocol_unbind_all();
3317 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003318 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003319 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003320 } else /* change the process group ID in the child (master process) */
3321 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003322 }
William Lallemande20b6a62017-06-01 17:38:55 +02003323
William Lallemande20b6a62017-06-01 17:38:55 +02003324
William Lallemanddeed7802017-11-06 11:00:04 +01003325 /* if in master-worker mode, write the PID of the father */
3326 if (global.mode & MODE_MWORKER) {
3327 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003328 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003329 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003330 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003331 }
3332
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003334 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003335 if (global.mode & MODE_MWORKER)
3336 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003337
3338 ret = fork();
3339 if (ret < 0) {
3340 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3341 protocol_unbind_all();
3342 exit(1); /* there has been an error */
3343 }
3344 else if (ret == 0) { /* child breaks here */
Willy Tarreau3c032f22021-07-21 10:17:02 +02003345 /* This one must not be exported, it's internal! */
3346 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003347 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003348 }
3349 else { /* parent here */
3350 in_parent = 1;
3351
William Lallemand944e6192018-11-21 15:48:31 +01003352 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3353 char pidstr[100];
3354 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003355 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003356 }
3357 if (global.mode & MODE_MWORKER) {
3358 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003359
William Lallemand5d71a6b2021-11-09 15:25:31 +01003360 ha_notice("New worker (%d) forked\n", ret);
William Lallemand944e6192018-11-21 15:48:31 +01003361 /* find the right mworker_proc */
3362 list_for_each_entry(child, &proc_list, list) {
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003363 if (child->reloads == 0 && child->options & PROC_O_TYPE_WORKER) {
William Lallemand944e6192018-11-21 15:48:31 +01003364 child->timestamp = now.tv_sec;
3365 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003366 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003367 break;
3368 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003369 }
3370 }
William Lallemand944e6192018-11-21 15:48:31 +01003371 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003372
William Lallemand944e6192018-11-21 15:48:31 +01003373 } else {
3374 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003375 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003376 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003377
3378#ifdef USE_CPU_AFFINITY
Willy Tarreau44ea6312021-06-15 08:57:56 +02003379 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 +02003380
David CARLIERdf91cbd2022-01-06 18:53:50 +00003381#if defined(CPUSET_USE_CPUSET) || defined(__DragonFly__)
David CARLIERbb10dad2022-01-08 09:59:38 +00003382 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003383 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
David CARLIERdf91cbd2022-01-06 18:53:50 +00003384#elif defined(__FreeBSD__)
David CARLIERbb10dad2022-01-08 09:59:38 +00003385 struct hap_cpuset *set = &cpu_map.proc;
David CARLIERdf91cbd2022-01-06 18:53:50 +00003386 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003387#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003388 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003389#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003391 if (pidfd >= 0) {
3392 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3393 close(pidfd);
3394 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003395
3396 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003397 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003398
Willy Tarreaud67ff342021-06-15 07:58:09 +02003399 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003400 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
William Lallemandfab0fdc2021-11-09 18:01:22 +01003401 master = 1;
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003402
3403 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3404 (global.mode & MODE_DAEMON)) {
3405 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003406 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3407 stdio_quiet(-1);
3408
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003409 global.mode &= ~MODE_VERBOSE;
3410 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003411 }
3412
William Lallemandfab0fdc2021-11-09 18:01:22 +01003413 if (global.mode & MODE_MWORKER_WAIT) {
3414 /* only the wait mode handles the master CLI */
3415 mworker_loop();
3416 } else {
3417
3418 /* if not in wait mode, reload in wait mode to free the memory */
William Lallemand836bda22021-11-09 18:16:47 +01003419 ha_notice("Loading success.\n");
William Lallemand68836742021-11-10 10:49:06 +01003420 proc_self->failedreloads = 0; /* reset the number of failure */
William Lallemandfab0fdc2021-11-09 18:01:22 +01003421 mworker_reexec_waitmode();
3422 }
William Lallemand1499b9b2017-06-07 15:04:47 +02003423 /* should never get there */
3424 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003425 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003426#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003427 ssl_free_dh();
3428#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003429 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003430 }
3431
William Lallemandcb11fd22017-06-01 17:38:52 +02003432 /* child must never use the atexit function */
3433 atexit_flag = 0;
3434
William Lallemandbc193052018-09-11 10:06:26 +02003435 /* close useless master sockets */
3436 if (global.mode & MODE_MWORKER) {
3437 struct mworker_proc *child, *it;
3438 master = 0;
3439
William Lallemand309dc9a2018-10-26 14:47:45 +02003440 mworker_cli_proxy_stop();
3441
William Lallemandbc193052018-09-11 10:06:26 +02003442 /* free proc struct of other processes */
3443 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003444 /* close the FD of the master side for all
3445 * workers, we don't need to close the worker
3446 * side of other workers since it's done with
3447 * the bind_proc */
William Lallemand7e018782022-01-28 21:56:24 +01003448 if (child->ipc_fd[0] >= 0) {
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003449 close(child->ipc_fd[0]);
William Lallemand7e018782022-01-28 21:56:24 +01003450 child->ipc_fd[0] = -1;
3451 }
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003452 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandce83b4a2018-10-26 14:47:30 +02003453 child->reloads == 0) {
3454 /* keep this struct if this is our pid */
3455 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003456 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003457 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003458 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003459 mworker_free_child(child);
3460 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003461 }
3462 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003463
William Lallemande1340412017-12-28 16:09:36 +01003464 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3465 devnullfd = open("/dev/null", O_RDWR, 0);
3466 if (devnullfd < 0) {
3467 ha_alert("Cannot open /dev/null\n");
3468 exit(EXIT_FAILURE);
3469 }
3470 }
3471
William Lallemand095ba4c2017-06-01 17:38:50 +02003472 /* Must chroot and setgid/setuid in the children */
3473 /* chroot if needed */
3474 if (global.chroot != NULL) {
3475 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003476 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003477 if (nb_oldpids)
3478 tell_old_pids(SIGTTIN);
3479 protocol_unbind_all();
3480 exit(1);
3481 }
3482 }
3483
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003484 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003485 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003486
William Lallemand7f80eb22017-05-26 18:19:55 +02003487 /* pass through every cli socket, and check if it's bound to
3488 * the current process and if it exposes listeners sockets.
3489 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3490 * */
3491
Willy Tarreau4975d142021-03-13 11:00:33 +01003492 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003493 struct bind_conf *bind_conf;
3494
Willy Tarreau4975d142021-03-13 11:00:33 +01003495 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003496 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003497 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3498 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003499 }
3500 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003501 }
3502
William Lallemand2e8fad92018-11-13 16:18:23 +01003503 /*
3504 * This is only done in daemon mode because we might want the
3505 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3506 * we should now close the 3 first FDs to ensure that we can
3507 * detach from the TTY. We MUST NOT do it in other cases since
3508 * it would have already be done, and 0-2 would have been
3509 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003511 if ((global.mode & MODE_DAEMON) &&
3512 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003513 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003514 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003515 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003516 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3517 }
3518 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003519 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3520 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003521 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003522 }
3523
William Dauchye039f262019-11-17 15:47:15 +01003524 /* try our best to re-enable core dumps depending on system capabilities.
3525 * What is addressed here :
3526 * - remove file size limits
3527 * - remove core size limits
3528 * - mark the process dumpable again if it lost it due to user/group
3529 */
3530 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3531 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3532
3533#if defined(RLIMIT_FSIZE)
3534 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3535 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3536 ha_alert("[%s.main()] Failed to set the raise the maximum "
3537 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003538 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003539 }
3540 else
3541 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003542 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003543 }
3544#endif
3545
3546#if defined(RLIMIT_CORE)
3547 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3548 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3549 ha_alert("[%s.main()] Failed to set the raise the core "
3550 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003551 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003552 }
3553 else
3554 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003555 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003556 }
3557#endif
3558
3559#if defined(USE_PRCTL)
3560 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3561 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3562 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003563#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003564 {
3565 int traceable = PROC_TRACE_CTL_ENABLE;
3566 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3567 ha_warning("[%s.main()] Failed to set the traceable flag, "
3568 "no core will be dumped.\n", argv[0]);
3569 }
William Dauchye039f262019-11-17 15:47:15 +01003570#endif
3571 }
3572
Christopher Faulete3a5e352017-10-24 13:53:54 +02003573 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003574 reset_usermsgs_ctx();
3575
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003576 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003577 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003578
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003579 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003580 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003581
3582 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003583 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003584
3585 /* wait for all threads to terminate */
3586 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003587
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003588 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003589}
3590
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591/*
3592 * Local variables:
3593 * c-indent-level: 8
3594 * c-basic-offset: 8
3595 * End:
3596 */