blob: dda03a9946a7d002ef98bdf397aa205253633aaf [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 Tarreau421ed392021-01-06 17:41:32 +01003 * Copyright 2000-2021 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>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200141
Willy Tarreaubaaee002006-06-26 02:48:02 +0200142
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100143/* array of init calls for older platforms */
144DECLARE_INIT_STAGES;
145
Willy Tarreauf4596402021-04-10 16:53:05 +0200146/* create a read_mostly section to hold variables which are accessed a lot
147 * but which almost never change. The purpose is to isolate them in their
148 * own cache lines where they don't risk to be perturbated by write accesses
149 * to neighbor variables. We need to create an empty aligned variable for
150 * this. The fact that the variable is of size zero means that it will be
151 * eliminated at link time if no other variable uses it, but alignment will
152 * be respected.
153 */
154empty_t __read_mostly_align HA_SECTION("read_mostly") ALIGNED(64);
155
Willy Tarreauf0d3b732021-05-06 16:30:32 +0200156#ifdef BUILD_FEATURES
157const char *build_features = BUILD_FEATURES;
158#else
159const char *build_features = "";
160#endif
161
Willy Tarreau477ecd82010-01-03 21:12:30 +0100162/* list of config files */
163static struct list cfg_cfgfiles = LIST_HEAD_INIT(cfg_cfgfiles);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200164int pid; /* current process id */
165
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100166volatile unsigned long sleeping_thread_mask = 0; /* Threads that are about to sleep in poll() */
Willy Tarreau4b3f27b2020-03-12 17:28:01 +0100167volatile unsigned long stopping_thread_mask = 0; /* Threads acknowledged stopping */
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100168
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169/* global options */
170struct global global = {
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100171 .hard_stop_after = TICK_ETERNITY,
Amaury Denoyelle0f50cb92021-03-26 18:50:33 +0100172 .numa_cpu_mapping = 1,
Willy Tarreau149ab772019-01-26 14:27:06 +0100173 .nbthread = 0,
William Lallemand5f232402012-04-05 18:02:55 +0200174 .req_count = 0,
William Lallemand0f99e342011-10-12 17:50:54 +0200175 .logsrvs = LIST_HEAD_INIT(global.logsrvs),
William Lallemand9d5f5482012-11-07 16:12:57 +0100176 .maxzlibmem = 0,
William Lallemandd85f9172012-11-09 17:05:39 +0100177 .comp_rate_lim = 0,
Emeric Brun850efd52014-01-29 12:24:34 +0100178 .ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED,
Emeric Bruned760922010-10-22 17:59:25 +0200179 .unix_bind = {
180 .ux = {
181 .uid = -1,
182 .gid = -1,
183 .mode = 0,
184 }
185 },
Willy Tarreau27a674e2009-08-17 07:23:33 +0200186 .tune = {
Willy Tarreau7ac908b2019-02-27 12:02:18 +0100187 .options = GTUNE_LISTENER_MQ,
Willy Tarreauc77d3642018-12-12 06:19:42 +0100188 .bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
Christopher Faulet546c4692020-01-22 14:31:21 +0100189 .maxrewrite = MAXREWRITE,
Willy Tarreaua24adf02014-11-27 01:11:56 +0100190 .reserved_bufs = RESERVED_BUFS,
Willy Tarreauf3045d22015-04-29 16:24:50 +0200191 .pattern_cache = DEFAULT_PAT_LRU_SIZE,
Olivier Houchard88698d92019-04-16 19:07:22 +0200192 .pool_low_ratio = 20,
193 .pool_high_ratio = 25,
Christopher Faulet41ba36f2019-07-19 09:36:45 +0200194 .max_http_hdr = MAX_HTTP_HDR,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200195#ifdef USE_OPENSSL
Emeric Brun46635772012-11-14 11:32:56 +0100196 .sslcachesize = SSLCACHESIZE,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200197#endif
William Lallemandf3747832012-11-09 12:33:10 +0100198 .comp_maxlevel = 1,
Willy Tarreau7e312732014-02-12 16:35:14 +0100199#ifdef DEFAULT_IDLE_TIMER
200 .idle_timer = DEFAULT_IDLE_TIMER,
201#else
202 .idle_timer = 1000, /* 1 second */
203#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200204 },
Emeric Brun76d88952012-10-05 15:47:31 +0200205#ifdef USE_OPENSSL
206#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200207 .maxsslconn = DEFAULT_MAXSSLCONN,
208#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200209#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210 /* others NULL OK */
211};
212
213/*********************************************************************/
214
215int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100216int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200217int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100218int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100219int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100220int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500222/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 * or kill. We will send them a signal every 10 ms until we can bind to all
224 * our ports. With 200 retries, that's about 2 seconds.
225 */
226#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227static int *oldpids = NULL;
228static int oldpids_sig; /* use USR1 or TERM */
229
Olivier Houchardf73629d2017-04-05 22:33:04 +0200230/* Path to the unix socket we use to retrieve listener sockets from the old process */
231static const char *old_unixsocket;
232
William Lallemandcb11fd22017-06-01 17:38:52 +0200233int atexit_flag = 0;
234
Willy Tarreaubb545b42010-08-25 12:58:59 +0200235int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236const int zero = 0;
237const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200238const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100240char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200241char *localpeer = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242
William Lallemand00417412020-06-05 14:08:41 +0200243static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200244
William Lallemandbc193052018-09-11 10:06:26 +0200245struct list proc_list = LIST_HEAD_INIT(proc_list);
246
247int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100248unsigned int rlim_fd_cur_at_boot = 0;
249unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200250
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100251/* per-boot randomness */
252unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
253
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200254/* takes the thread config in argument or NULL for any thread */
William Lallemandb3f2be32018-09-11 10:06:18 +0200255static void *run_thread_poll_loop(void *data);
256
Willy Tarreauff055502014-04-28 22:27:06 +0200257/* bitfield of a few warnings to emit just once (WARN_*) */
258unsigned int warned = 0;
259
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200260/* set if experimental features have been used for the current process */
261static unsigned int tainted = 0;
262
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200263unsigned int experimental_directives_allowed = 0;
264
265int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
266 char **errmsg)
267{
268 if (kw->flags & KWF_EXPERIMENTAL) {
269 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200270 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 +0200271 file, linenum, kw->kw);
272 return 1;
273 }
274 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
275 }
276
277 return 0;
278}
279
William Lallemande7361152018-10-26 14:47:36 +0200280/* master CLI configuration (-S flag) */
281struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100282
283/* These are strings to be reported in the output of "haproxy -vv". They may
284 * either be constants (in which case must_free must be zero) or dynamically
285 * allocated strings to pass to free() on exit, and in this case must_free
286 * must be non-zero.
287 */
288struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
289struct build_opts_str {
290 struct list list;
291 const char *str;
292 int must_free;
293};
294
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295/*********************************************************************/
296/* general purpose functions ***************************************/
297/*********************************************************************/
298
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100299/* used to register some build option strings at boot. Set must_free to
300 * non-zero if the string must be freed upon exit.
301 */
302void hap_register_build_opts(const char *str, int must_free)
303{
304 struct build_opts_str *b;
305
306 b = calloc(1, sizeof(*b));
307 if (!b) {
308 fprintf(stderr, "out of memory\n");
309 exit(1);
310 }
311 b->str = str;
312 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200313 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100314}
315
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200316#define VERSION_MAX_ELTS 7
317
318/* This function splits an haproxy version string into an array of integers.
319 * The syntax of the supported version string is the following:
320 *
321 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
322 *
323 * This validates for example:
324 * 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
325 * 2.4-dev18-f6818d-20
326 *
327 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
328 * one fixed place in the array. The tags take a numeric value called <e> which
329 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
330 * considered as zero (henxe 1.5 and 1.5.0 are the same).
331 *
332 * The resulting values are:
333 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
334 * 1.2.1 1, 2, 1, 0, 3, 0, 0
335 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
336 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
337 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
338 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
339 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
340 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
341 *
342 * The function returns non-zero if the conversion succeeded, or zero if it
343 * failed.
344 */
345int split_version(const char *version, unsigned int *value)
346{
347 const char *p, *s;
348 char *error;
349 int nelts;
350
351 /* Initialize array with zeroes */
352 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
353 value[nelts] = 0;
354 value[4] = 3;
355
356 p = version;
357
358 /* If the version number is empty, return false */
359 if (*p == '\0')
360 return 0;
361
362 /* Convert first number <a> */
363 value[0] = strtol(p, &error, 10);
364 p = error + 1;
365 if (*error == '\0')
366 return 1;
367 if (*error == '-')
368 goto split_version_tag;
369 if (*error != '.')
370 return 0;
371
372 /* Convert first number <b> */
373 value[1] = strtol(p, &error, 10);
374 p = error + 1;
375 if (*error == '\0')
376 return 1;
377 if (*error == '-')
378 goto split_version_tag;
379 if (*error != '.')
380 return 0;
381
382 /* Convert first number <c> */
383 value[2] = strtol(p, &error, 10);
384 p = error + 1;
385 if (*error == '\0')
386 return 1;
387 if (*error == '-')
388 goto split_version_tag;
389 if (*error != '.')
390 return 0;
391
392 /* Convert first number <d> */
393 value[3] = strtol(p, &error, 10);
394 p = error + 1;
395 if (*error == '\0')
396 return 1;
397 if (*error != '-')
398 return 0;
399
400 split_version_tag:
401 /* Check for commit number */
402 if (*p >= '0' && *p <= '9')
403 goto split_version_commit;
404
405 /* Read tag */
406 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
407 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
408 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
409 else
410 goto split_version_commit;
411
412 /* Convert tag number */
413 value[5] = strtol(p, &error, 10);
414 p = error + 1;
415 if (*error == '\0')
416 return 1;
417 if (*error != '-')
418 return 0;
419
420 split_version_commit:
421 /* Search the last "-" */
422 s = strrchr(p, '-');
423 if (s) {
424 s++;
425 if (*s == '\0')
426 return 0;
427 value[6] = strtol(s, &error, 10);
428 if (*error != '\0')
429 value[6] = 0;
430 return 1;
431 }
432
433 /* convert the version */
434 value[6] = strtol(p, &error, 10);
435 if (*error != '\0')
436 value[6] = 0;
437
438 return 1;
439}
440
441/* This function compares the current haproxy version with an arbitrary version
442 * string. It returns:
443 * -1 : the version in argument is older than the current haproxy version
444 * 0 : the version in argument is the same as the current haproxy version
445 * 1 : the version in argument is newer than the current haproxy version
446 *
447 * Or some errors:
448 * -2 : the current haproxy version is not parsable
449 * -3 : the version in argument is not parsable
450 */
451int compare_current_version(const char *version)
452{
453 unsigned int loc[VERSION_MAX_ELTS];
454 unsigned int mod[VERSION_MAX_ELTS];
455 int i;
456
457 /* split versions */
458 if (!split_version(haproxy_version, loc))
459 return -2;
460 if (!split_version(version, mod))
461 return -3;
462
463 /* compare versions */
464 for (i = 0; i < VERSION_MAX_ELTS; i++) {
465 if (mod[i] < loc[i])
466 return -1;
467 else if (mod[i] > loc[i])
468 return 1;
469 }
470 return 0;
471}
472
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100473static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200474{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200475 struct utsname utsname;
476
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200477 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100478 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100479
480 if (strlen(PRODUCT_URL_BUGS) > 0) {
481 char base_version[20];
482 int dots = 0;
483 char *del;
484
485 /* only retrieve the base version without distro-specific extensions */
486 for (del = haproxy_version; *del; del++) {
487 if (*del == '.')
488 dots++;
489 else if (*del < '0' || *del > '9')
490 break;
491 }
492
493 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
494 if (dots < 2)
495 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
496 else
497 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
498 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200499
500 if (uname(&utsname) == 0) {
501 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200503}
504
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100505static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100506{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100507 struct build_opts_str *item;
508
Willy Tarreau7b066db2007-12-02 11:28:59 +0100509 printf("Build options :"
510#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100511 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100512#endif
513#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100514 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100515#endif
516#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100517 "\n CC = " BUILD_CC
518#endif
519#ifdef BUILD_CFLAGS
520 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100521#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100522#ifdef BUILD_OPTIONS
523 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100524#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100525#ifdef BUILD_DEBUG
526 "\n DEBUG = " BUILD_DEBUG
527#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100528#ifdef BUILD_FEATURES
529 "\n\nFeature list : " BUILD_FEATURES
530#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200531 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100532 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200533 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100534 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200535
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100536 list_for_each_entry(item, &build_opts_list, list) {
537 puts(item->str);
538 }
539
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100540 putchar('\n');
541
Willy Tarreaube5b6852009-10-03 18:57:08 +0200542 list_pollers(stdout);
543 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200544 list_mux_proto(stdout);
545 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100546 list_services(stdout);
547 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100548 list_filters(stdout);
549 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100550}
551
Willy Tarreaubaaee002006-06-26 02:48:02 +0200552/*
553 * This function prints the command line usage and exits
554 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100555static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200556{
557 display_version();
558 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200559 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200560 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200561 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100562 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200563 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreau6e064432012-05-08 15:40:42 +0200564 " -dM[<byte>] poisons memory with <byte> (defaults to 0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200565 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200566 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200567 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100568#if defined(USE_SYSTEMD)
569 " -Ws master-worker mode with systemd notify support.\n"
570#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200571 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200572 " -c check mode : only check config files and exit\n"
Maximilian Maderfc0cceb2021-06-06 00:50:22 +0200573 " -cc check condition : evaluate a condition and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100574 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575 " -m limits the usable amount of memory (in MB)\n"
576 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200577 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200578 " -p writes pids of all children to this file\n"
Willy Tarreaue5733232019-05-22 19:24:06 +0200579#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 " -de disables epoll() usage even when available\n"
581#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200582#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200583 " -dk disables kqueue() usage even when available\n"
584#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200585#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000586 " -dv disables event ports usage even when available\n"
587#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200588#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 " -dp disables poll() usage even when available\n"
590#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200591#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100592 " -dS disables splice usage (broken on old kernels)\n"
593#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200594#if defined(USE_GETADDRINFO)
595 " -dG disables getaddrinfo() usage\n"
596#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000597#if defined(SO_REUSEPORT)
598 " -dR disables SO_REUSEPORT usage\n"
599#endif
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100600 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100601 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200602 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200603 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200604 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200605 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200606 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100608 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200609 exit(1);
610}
611
612
613
614/*********************************************************************/
615/* more specific functions ***************************************/
616/*********************************************************************/
617
William Lallemand73b85e72017-06-01 17:38:51 +0200618/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
619 * pids the signal was correctly delivered to.
620 */
William Lallemande25473c2019-04-01 11:29:56 +0200621int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200622{
623 int p;
624 int ret = 0;
625 for (p = 0; p < nb_oldpids; p++)
626 if (kill(oldpids[p], sig) == 0)
627 ret++;
628 return ret;
629}
630
William Lallemand75ea0a02017-11-15 19:02:58 +0100631/*
William Lallemand73b85e72017-06-01 17:38:51 +0200632 * remove a pid forom the olpid array and decrease nb_oldpids
633 * return 1 pid was found otherwise return 0
634 */
635
636int delete_oldpid(int pid)
637{
638 int i;
639
640 for (i = 0; i < nb_oldpids; i++) {
641 if (oldpids[i] == pid) {
642 oldpids[i] = oldpids[nb_oldpids - 1];
643 oldpids[nb_oldpids - 1] = 0;
644 nb_oldpids--;
645 return 1;
646 }
647 }
648 return 0;
649}
650
William Lallemand85b0bd92017-06-01 17:38:53 +0200651
William Lallemand73b85e72017-06-01 17:38:51 +0200652/*
653 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800654 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200655 */
William Lallemandfab0fdc2021-11-09 18:01:22 +0100656static void mworker_reexec()
William Lallemand73b85e72017-06-01 17:38:51 +0200657{
William Lallemand00417412020-06-05 14:08:41 +0200658 char **next_argv = NULL;
659 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200660 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200661 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200662 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100663 struct rlimit limit;
William Lallemand2be557f2021-11-24 18:45:37 +0100664 struct mworker_proc *current_child = NULL;
William Lallemand73b85e72017-06-01 17:38:51 +0200665
666 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100667#if defined(USE_SYSTEMD)
668 if (global.tune.options & GTUNE_USE_SYSTEMD)
669 sd_notify(0, "RELOADING=1");
670#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200671 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
672
William Lallemandbc193052018-09-11 10:06:26 +0200673 mworker_proc_list_to_env(); /* put the children description in the env */
674
William Lallemandc4810b82021-11-18 10:51:30 +0100675 /* ensure that we close correctly every listeners before reexecuting */
676 mworker_cleanlisteners();
677
William Lallemand7c756a82018-11-26 11:53:40 +0100678 /* during the reload we must ensure that every FDs that can't be
679 * reuse (ie those that are not referenced in the proc_list)
680 * are closed or they will leak. */
681
682 /* close the listeners FD */
683 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200684
William Lallemand67e371e2021-11-25 10:03:44 +0100685 if (fdtab)
686 deinit_pollers();
William Lallemandefd95472021-11-26 14:43:57 +0100687
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500688#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200689 /* close random device FDs */
690 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100691#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100692
Willy Tarreau8dca1952019-03-01 10:21:55 +0100693 /* restore the initial FD limits */
694 limit.rlim_cur = rlim_fd_cur_at_boot;
695 limit.rlim_max = rlim_fd_max_at_boot;
696 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
697 getrlimit(RLIMIT_NOFILE, &limit);
698 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
699 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
700 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
701 }
702
William Lallemand73b85e72017-06-01 17:38:51 +0200703 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200704 while (old_argv[old_argc])
705 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200706
William Lallemand85b0bd92017-06-01 17:38:53 +0200707 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200708 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200709 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200710 if (next_argv == NULL)
711 goto alloc_error;
712
William Lallemand00417412020-06-05 14:08:41 +0200713 /* copy the program name */
714 next_argv[next_argc++] = old_argv[0];
715
716 /* insert the new options just after argv[0] in case we have a -- */
717
William Lallemandbefab9e2021-11-25 00:49:19 +0100718 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
719 /* add -sf <PID>* to argv */
720 if (mworker_child_nb() > 0) {
721 struct mworker_proc *child;
William Lallemand3f128872019-04-01 11:29:59 +0200722
William Lallemandbefab9e2021-11-25 00:49:19 +0100723 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200724
William Lallemandbefab9e2021-11-25 00:49:19 +0100725 list_for_each_entry(child, &proc_list, list) {
726 if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
727 current_child = child;
William Lallemand2be557f2021-11-24 18:45:37 +0100728
William Lallemandbefab9e2021-11-25 00:49:19 +0100729 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
730 continue;
731 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
732 goto alloc_error;
733 msg = NULL;
734 }
William Lallemand73b85e72017-06-01 17:38:51 +0200735 }
William Lallemand2be557f2021-11-24 18:45:37 +0100736
737 if (current_child) {
738 /* add the -x option with the socketpair of the current worker */
739 next_argv[next_argc++] = "-x";
740 if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
741 goto alloc_error;
742 msg = NULL;
743 }
William Lallemand85b0bd92017-06-01 17:38:53 +0200744 }
745
William Lallemand00417412020-06-05 14:08:41 +0200746 /* copy the previous options */
747 for (i = 1; i < old_argc; i++)
748 next_argv[next_argc++] = old_argv[i];
749
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200750 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100751 execvp(next_argv[0], next_argv);
Christopher Faulet767a84b2017-11-24 16:50:31 +0100752 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100753 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100754 return;
755
William Lallemand73b85e72017-06-01 17:38:51 +0200756alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100757 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800758 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200759 return;
760}
761
William Lallemandfab0fdc2021-11-09 18:01:22 +0100762/* reexec haproxy in waitmode */
763static void mworker_reexec_waitmode()
764{
765 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
766 mworker_reexec();
767}
768
769/* reload haproxy and emit a warning */
770void mworker_reload()
771{
William Lallemandad221f42021-11-09 18:43:59 +0100772 struct mworker_proc *child;
William Lallemandefd95472021-11-26 14:43:57 +0100773 struct per_thread_deinit_fct *ptdf;
William Lallemandad221f42021-11-09 18:43:59 +0100774
William Lallemand836bda22021-11-09 18:16:47 +0100775 ha_notice("Reloading HAProxy\n");
William Lallemandad221f42021-11-09 18:43:59 +0100776
William Lallemandefd95472021-11-26 14:43:57 +0100777 /* close the poller FD and the thread waker pipe FD */
778 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
779 ptdf->fct();
780
William Lallemandad221f42021-11-09 18:43:59 +0100781 /* increment the number of reloads */
782 list_for_each_entry(child, &proc_list, list) {
783 child->reloads++;
784 }
785
William Lallemandfab0fdc2021-11-09 18:01:22 +0100786 mworker_reexec();
787}
788
William Lallemandb3f2be32018-09-11 10:06:18 +0200789static void mworker_loop()
790{
791
792#if defined(USE_SYSTEMD)
793 if (global.tune.options & GTUNE_USE_SYSTEMD)
794 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
795#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200796 /* Busy polling makes no sense in the master :-) */
797 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200798
William Lallemandbc193052018-09-11 10:06:26 +0200799
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100800 signal_unregister(SIGTTIN);
801 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100802 signal_unregister(SIGUSR1);
803 signal_unregister(SIGHUP);
804 signal_unregister(SIGQUIT);
805
William Lallemandb3f2be32018-09-11 10:06:18 +0200806 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
807 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100808 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
809 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200810 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
811 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
812 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
813 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
814
815 mworker_unblock_signals();
William Lallemand27f3fa52018-12-06 14:05:20 +0100816 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200817
William Lallemandbc193052018-09-11 10:06:26 +0200818 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
819 some SIGCHLD were lost */
820
William Lallemandb3f2be32018-09-11 10:06:18 +0200821 global.nbthread = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200822
William Lallemand2672eb92018-12-14 15:52:39 +0100823#ifdef USE_THREAD
824 tid_bit = 1;
825 all_threads_mask = 1;
826#endif
827
William Lallemandb3f2be32018-09-11 10:06:18 +0200828 jobs++; /* this is the "master" job, we want to take care of the
829 signals even if there is no listener so the poll loop don't
830 leave */
831
832 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200833 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200834}
William Lallemandcb11fd22017-06-01 17:38:52 +0200835
836/*
837 * Reexec the process in failure mode, instead of exiting
838 */
839void reexec_on_failure()
840{
William Lallemand68836742021-11-10 10:49:06 +0100841 struct mworker_proc *child;
842
William Lallemandcb11fd22017-06-01 17:38:52 +0200843 if (!atexit_flag)
844 return;
William Lallemand68836742021-11-10 10:49:06 +0100845
846 /* get the info of the children in the env */
847 if (mworker_env_to_proc_list() < 0) {
848 exit(EXIT_FAILURE);
849 }
850
851 /* increment the number of failed reloads */
852 list_for_each_entry(child, &proc_list, list) {
853 child->failedreloads++;
854 }
855
William Lallemandfab0fdc2021-11-09 18:01:22 +0100856 usermsgs_clr(NULL);
William Lallemand836bda22021-11-09 18:16:47 +0100857 ha_warning("Loading failure!\n");
William Lallemandfab0fdc2021-11-09 18:01:22 +0100858 mworker_reexec_waitmode();
William Lallemandcb11fd22017-06-01 17:38:52 +0200859}
William Lallemand73b85e72017-06-01 17:38:51 +0200860
861
862/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200863 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
864 * a signal zero to all subscribers. This means that it's as easy as
865 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200866 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100867static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200868{
869 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200870 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100871 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200872}
873
874/*
875 * upon SIGTTOU, we pause everything
876 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100877static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200878{
Willy Tarreau775e0012020-09-24 16:36:26 +0200879 if (protocol_pause_all() & ERR_FATAL) {
880 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200881 ha_warning("%s", msg);
882 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200883 soft_stop();
884 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100885 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886}
887
888/*
889 * upon SIGTTIN, let's have a soft stop.
890 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100891static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892{
Willy Tarreau775e0012020-09-24 16:36:26 +0200893 if (protocol_resume_all() & ERR_FATAL) {
894 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 +0200895 ha_warning("%s", msg);
896 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200897 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200898}
899
900/*
901 * this function dumps every server's state when the process receives SIGHUP.
902 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100903static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100905 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906
Christopher Faulet767a84b2017-11-24 16:50:31 +0100907 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908 while (p) {
909 struct server *s = p->srv;
910
911 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
912 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100913 chunk_printf(&trash,
914 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
915 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200916 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200917 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200918 ha_warning("%s\n", trash.area);
919 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920 s = s->next;
921 }
922
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200923 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
924 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100925 chunk_printf(&trash,
926 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
927 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200928 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 +0200929 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100930 chunk_printf(&trash,
931 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
932 p->id,
933 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200934 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 +0200935 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100936 chunk_printf(&trash,
937 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
938 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
939 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200940 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 +0200941 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200942 ha_warning("%s\n", trash.area);
943 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200944
945 p = p->next;
946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947}
948
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100949static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200951 /* dump memory usage then free everything possible */
952 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100953 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954}
955
William Lallemande1340412017-12-28 16:09:36 +0100956/*
957 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
958 * If <fd> < 0, it opens /dev/null and use it to dup
959 *
960 * In the case of chrooting, you have to open /dev/null before the chroot, and
961 * pass the <fd> to this function
962 */
963static void stdio_quiet(int fd)
964{
965 if (fd < 0)
966 fd = open("/dev/null", O_RDWR, 0);
967
968 if (fd > -1) {
969 fclose(stdin);
970 fclose(stdout);
971 fclose(stderr);
972
973 dup2(fd, 0);
974 dup2(fd, 1);
975 dup2(fd, 2);
976 if (fd > 2)
977 close(fd);
978 return;
979 }
980
981 ha_alert("Cannot open /dev/null\n");
982 exit(EXIT_FAILURE);
983}
984
985
Joseph Herlant03420902018-11-15 10:41:50 -0800986/* This function checks if cfg_cfgfiles contains directories.
987 * If it finds one, it adds all the files (and only files) it contains
988 * in cfg_cfgfiles in place of the directory (and removes the directory).
989 * It adds the files in lexical order.
990 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200991 * It doesn't add files with name starting with '.'
992 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100993static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200994{
995 struct wordlist *wl, *wlb;
996 char *err = NULL;
997
998 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
999 struct stat file_stat;
1000 struct dirent **dir_entries = NULL;
1001 int dir_entries_nb;
1002 int dir_entries_it;
1003
1004 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001005 ha_alert("Cannot open configuration file/directory %s : %s\n",
1006 wl->s,
1007 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001008 exit(1);
1009 }
1010
1011 if (!S_ISDIR(file_stat.st_mode))
1012 continue;
1013
1014 /* from this point wl->s is a directory */
1015
1016 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1017 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001018 ha_alert("Cannot open configuration directory %s : %s\n",
1019 wl->s,
1020 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001021 exit(1);
1022 }
1023
1024 /* for each element in the directory wl->s */
1025 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1026 struct dirent *dir_entry = dir_entries[dir_entries_it];
1027 char *filename = NULL;
1028 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1029
1030 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001031 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001032 */
1033 if (dir_entry->d_name[0] == '.' ||
1034 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1035 goto next_dir_entry;
1036
1037 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001038 ha_alert("Cannot load configuration files %s : out of memory.\n",
1039 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001040 exit(1);
1041 }
1042
1043 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001044 ha_alert("Cannot open configuration file %s : %s\n",
1045 wl->s,
1046 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001047 exit(1);
1048 }
1049
1050 /* don't add anything else than regular file in cfg_cfgfiles
1051 * this way we avoid loops
1052 */
1053 if (!S_ISREG(file_stat.st_mode))
1054 goto next_dir_entry;
1055
1056 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001057 ha_alert("Cannot load configuration files %s : %s\n",
1058 filename,
1059 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001060 exit(1);
1061 }
1062
1063next_dir_entry:
1064 free(filename);
1065 free(dir_entry);
1066 }
1067
1068 free(dir_entries);
1069
1070 /* remove the current directory (wl) from cfg_cfgfiles */
1071 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001072 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001073 free(wl);
1074 }
1075
1076 free(err);
1077}
1078
Willy Tarreaubaaee002006-06-26 02:48:02 +02001079/*
William Lallemand73b85e72017-06-01 17:38:51 +02001080 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001081 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001082 * Return an allocated copy of argv
1083 */
1084
1085static char **copy_argv(int argc, char **argv)
1086{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001087 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001088
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001089 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001090 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001091 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001092 return NULL;
1093 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001094 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001095
William Lallemanddf6c5a82020-06-04 17:40:23 +02001096 /* first copy argv[0] */
1097 *newargv++ = *argv++;
1098 argc--;
1099
1100 while (argc > 0) {
1101 if (**argv != '-') {
1102 /* non options are copied but will fail in the argument parser */
1103 *newargv++ = *argv++;
1104 argc--;
1105
1106 } else {
1107 char *flag;
1108
1109 flag = *argv + 1;
1110
1111 if (flag[0] == '-' && flag[1] == 0) {
1112 /* "--\0" copy every arguments till the end of argv */
1113 *newargv++ = *argv++;
1114 argc--;
1115
1116 while (argc > 0) {
1117 *newargv++ = *argv++;
1118 argc--;
1119 }
1120 } else {
1121 switch (*flag) {
1122 case 's':
1123 /* -sf / -st and their parameters are ignored */
1124 if (flag[1] == 'f' || flag[1] == 't') {
1125 argc--;
1126 argv++;
1127 /* The list can't contain a negative value since the only
1128 way to know the end of this list is by looking for the
1129 next option or the end of the options */
1130 while (argc > 0 && argv[0][0] != '-') {
1131 argc--;
1132 argv++;
1133 }
William Lallemand398da622020-09-02 16:12:23 +02001134 } else {
1135 argc--;
1136 argv++;
1137
William Lallemanddf6c5a82020-06-04 17:40:23 +02001138 }
1139 break;
1140
1141 case 'x':
1142 /* this option and its parameter are ignored */
1143 argc--;
1144 argv++;
1145 if (argc > 0) {
1146 argc--;
1147 argv++;
1148 }
1149 break;
1150
1151 case 'C':
1152 case 'n':
1153 case 'm':
1154 case 'N':
1155 case 'L':
1156 case 'f':
1157 case 'p':
1158 case 'S':
1159 /* these options have only 1 parameter which must be copied and can start with a '-' */
1160 *newargv++ = *argv++;
1161 argc--;
1162 if (argc == 0)
1163 goto error;
1164 *newargv++ = *argv++;
1165 argc--;
1166 break;
1167 default:
1168 /* for other options just copy them without parameters, this is also done
1169 * for options like "--foo", but this will fail in the argument parser.
1170 * */
1171 *newargv++ = *argv++;
1172 argc--;
1173 break;
1174 }
William Lallemand73b85e72017-06-01 17:38:51 +02001175 }
1176 }
William Lallemand73b85e72017-06-01 17:38:51 +02001177 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001178
William Lallemanddf6c5a82020-06-04 17:40:23 +02001179 return retargv;
1180
1181error:
1182 free(retargv);
1183 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001184}
1185
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001186
1187/* Performs basic random seed initialization. The main issue with this is that
1188 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1189 * which means that there will only be 4 billion possible random sequences once
1190 * srandom() is called, regardless of the internal state. Not calling it is
1191 * even worse as we'll always produce the same randoms sequences. What we do
1192 * here is to create an initial sequence from various entropy sources, hash it
1193 * using SHA1 and keep the resulting 160 bits available globally.
1194 *
1195 * We initialize the current process with the first 32 bits before starting the
1196 * polling loop, where all this will be changed to have process specific and
1197 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001198 *
1199 * Before starting threads, it's still possible to call random() as srandom()
1200 * is initialized from this, but after threads and/or processes are started,
1201 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001202 */
1203static void ha_random_boot(char *const *argv)
1204{
1205 unsigned char message[256];
1206 unsigned char *m = message;
1207 struct timeval tv;
1208 blk_SHA_CTX ctx;
1209 unsigned long l;
1210 int fd;
1211 int i;
1212
1213 /* start with current time as pseudo-random seed */
1214 gettimeofday(&tv, NULL);
1215 write_u32(m, tv.tv_sec); m += 4;
1216 write_u32(m, tv.tv_usec); m += 4;
1217
1218 /* PID and PPID add some OS-based randomness */
1219 write_u16(m, getpid()); m += 2;
1220 write_u16(m, getppid()); m += 2;
1221
1222 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1223 fd = open("/dev/urandom", O_RDONLY);
1224 if (fd >= 0) {
1225 i = read(fd, m, 20);
1226 if (i > 0)
1227 m += i;
1228 close(fd);
1229 }
1230
1231 /* take up to 160 bits bytes from openssl (non-blocking) */
1232#ifdef USE_OPENSSL
1233 if (RAND_bytes(m, 20) == 1)
1234 m += 20;
1235#endif
1236
1237 /* take 160 bits from existing random in case it was already initialized */
1238 for (i = 0; i < 5; i++) {
1239 write_u32(m, random());
1240 m += 4;
1241 }
1242
1243 /* stack address (benefit form operating system's ASLR) */
1244 l = (unsigned long)&m;
1245 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1246
1247 /* argv address (benefit form operating system's ASLR) */
1248 l = (unsigned long)&argv;
1249 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1250
1251 /* use tv_usec again after all the operations above */
1252 gettimeofday(&tv, NULL);
1253 write_u32(m, tv.tv_usec); m += 4;
1254
1255 /*
1256 * At this point, ~84-92 bytes have been used
1257 */
1258
1259 /* finish with the hostname */
1260 strncpy((char *)m, hostname, message + sizeof(message) - m);
1261 m += strlen(hostname);
1262
1263 /* total message length */
1264 l = m - message;
1265
1266 memset(&ctx, 0, sizeof(ctx));
1267 blk_SHA1_Init(&ctx);
1268 blk_SHA1_Update(&ctx, message, l);
1269 blk_SHA1_Final(boot_seed, &ctx);
1270
1271 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001272 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001273}
1274
Willy Tarreau5a023f02019-03-01 14:19:31 +01001275/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1276 * setting, and returns it. It may return -1 meaning "unlimited" if some
1277 * unlimited proxies have been found and the global.maxconn value is not yet
1278 * set. It may also return a value greater than maxconn if it's not yet set.
1279 * Note that a value of zero means there is no need for pipes. -1 is never
1280 * returned if global.maxconn is valid.
1281 */
1282static int compute_ideal_maxpipes()
1283{
1284 struct proxy *cur;
1285 int nbfe = 0, nbbe = 0;
1286 int unlimited = 0;
1287 int pipes;
1288 int max;
1289
1290 for (cur = proxies_list; cur; cur = cur->next) {
1291 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1292 if (cur->cap & PR_CAP_FE) {
1293 max = cur->maxconn;
1294 nbfe += max;
1295 if (!max) {
1296 unlimited = 1;
1297 break;
1298 }
1299 }
1300 if (cur->cap & PR_CAP_BE) {
1301 max = cur->fullconn ? cur->fullconn : global.maxconn;
1302 nbbe += max;
1303 if (!max) {
1304 unlimited = 1;
1305 break;
1306 }
1307 }
1308 }
1309 }
1310
1311 pipes = MAX(nbfe, nbbe);
1312 if (global.maxconn) {
1313 if (pipes > global.maxconn || unlimited)
1314 pipes = global.maxconn;
1315 } else if (unlimited) {
1316 pipes = -1;
1317 }
1318
1319 return pipes >= 4 ? pipes / 4 : pipes;
1320}
1321
Willy Tarreauac350932019-03-01 15:43:14 +01001322/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1323 * rlimits and computes an ideal maxconn. It's meant to be called only when
1324 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001325 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1326 * default 100) is returned as it is expected that it will even run on tight
1327 * environments, and will maintain compatibility with previous packages that
1328 * used to rely on this value as the default one. The system will emit a
1329 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001330 */
1331static int compute_ideal_maxconn()
1332{
1333 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1334 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1335 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001336 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001337 int maxconn;
1338
1339 /* we have to take into account these elements :
1340 * - number of engine_fds, which inflates the number of FD needed per
1341 * connection by this number.
1342 * - number of pipes per connection on average : for the unlimited
1343 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1344 * fixed value of 2*pipes.
1345 * - two FDs per connection
1346 */
1347
1348 /* subtract listeners and checks */
1349 remain -= global.maxsock;
1350
Willy Tarreau3f200852019-03-14 19:13:17 +01001351 /* one epoll_fd/kqueue_fd per thread */
1352 remain -= global.nbthread;
1353
1354 /* one wake-up pipe (2 fd) per thread */
1355 remain -= 2 * global.nbthread;
1356
Willy Tarreauac350932019-03-01 15:43:14 +01001357 /* Fixed pipes values : we only subtract them if they're not larger
1358 * than the remaining FDs because pipes are optional.
1359 */
1360 if (pipes >= 0 && pipes * 2 < remain)
1361 remain -= pipes * 2;
1362
1363 if (pipes < 0) {
1364 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1365 * = maxconn * (2 + 0.5 + engine_fds)
1366 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1367 */
1368 maxconn = 2 * remain / (5 + 2 * engine_fds);
1369 } else {
1370 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1371 * = maxconn * (2 + engine_fds)
1372 */
1373 maxconn = remain / (2 + engine_fds);
1374 }
1375
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001376 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001377}
1378
Willy Tarreaua409f302020-03-10 17:08:53 +01001379/* computes the estimated maxsock value for the given maxconn based on the
1380 * possibly set global.maxpipes and existing partial global.maxsock. It may
1381 * temporarily change global.maxconn for the time needed to propagate the
1382 * computations, and will reset it.
1383 */
1384static int compute_ideal_maxsock(int maxconn)
1385{
1386 int maxpipes = global.maxpipes;
1387 int maxsock = global.maxsock;
1388
1389
1390 if (!maxpipes) {
1391 int old_maxconn = global.maxconn;
1392
1393 global.maxconn = maxconn;
1394 maxpipes = compute_ideal_maxpipes();
1395 global.maxconn = old_maxconn;
1396 }
1397
1398 maxsock += maxconn * 2; /* each connection needs two sockets */
1399 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1400 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1401 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1402
1403 /* compute fd used by async engines */
1404 if (global.ssl_used_async_engines) {
1405 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1406
1407 maxsock += maxconn * sides * global.ssl_used_async_engines;
1408 }
1409 return maxsock;
1410}
1411
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001412/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001413 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1414 * value is accepted, non-zero otherwise. This is used to determine if an
1415 * automatic limit may be applied or not. When it is not, the caller knows that
1416 * the highest we can do is the rlim_max at boot. In case of error, we return
1417 * that the setting is possible, so that we defer the error processing to the
1418 * final stage in charge of enforcing this.
1419 */
1420static int check_if_maxsock_permitted(int maxsock)
1421{
1422 struct rlimit orig_limit, test_limit;
1423 int ret;
1424
1425 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1426 return 1;
1427
1428 /* don't go further if we can't even set to what we have */
1429 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1430 return 1;
1431
1432 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1433 test_limit.rlim_cur = test_limit.rlim_max;
1434 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1435
1436 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1437 return 1;
1438
1439 return ret == 0;
1440}
1441
Amaury Denoyelle484454d2021-05-05 16:18:45 +02001442void mark_tainted(const enum tainted_flags flag)
1443{
1444 HA_ATOMIC_OR(&tainted, flag);
1445}
1446
1447unsigned int get_tainted()
1448{
1449 int tainted_state;
1450 HA_ATOMIC_STORE(&tainted_state, tainted);
1451 return tainted_state;
1452}
Willy Tarreau304e17e2020-03-10 17:54:54 +01001453
William Lallemand73b85e72017-06-01 17:38:51 +02001454/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455 * This function initializes all the necessary variables. It only returns
1456 * if everything is OK. If something fails, it exits.
1457 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001458static void init(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459{
Willy Tarreaubaaee002006-06-26 02:48:02 +02001460 int arg_mode = 0; /* MODE_DEBUG, ... */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001461 char *tmp;
1462 char *cfg_pidfile = NULL;
Willy Tarreau058e9072009-07-20 09:30:05 +02001463 int err_code = 0;
Maxime de Roucy0f503922016-05-13 23:52:55 +02001464 char *err_msg = NULL;
Willy Tarreau477ecd82010-01-03 21:12:30 +01001465 struct wordlist *wl;
Kevinm48936af2010-12-22 16:08:21 +00001466 char *progname;
Willy Tarreau576132e2011-09-10 19:26:56 +02001467 char *change_dir = NULL;
Christopher Fauletd7c91962015-04-30 11:48:27 +02001468 struct proxy *px;
Willy Tarreaue6945732016-12-21 19:57:00 +01001469 struct post_check_fct *pcf;
Willy Tarreauac350932019-03-01 15:43:14 +01001470 int ideal_maxconn;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001471 char *check_condition = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001472
Christopher Faulete3a5e352017-10-24 13:53:54 +02001473 global.mode = MODE_STARTING;
William Lallemand00417412020-06-05 14:08:41 +02001474 old_argv = copy_argv(argc, argv);
1475 if (!old_argv) {
William Lallemanddf6c5a82020-06-04 17:40:23 +02001476 ha_alert("failed to copy argv.\n");
1477 exit(1);
1478 }
William Lallemand73b85e72017-06-01 17:38:51 +02001479
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001480 if (!init_trash_buffers(1)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001481 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet748919a2017-07-26 14:59:46 +02001482 exit(1);
1483 }
David du Colombier7af46052012-05-16 14:16:48 +02001484
Emeric Brun2b920a12010-09-23 18:30:22 +02001485 /* NB: POSIX does not make it mandatory for gethostname() to NULL-terminate
1486 * the string in case of truncation, and at least FreeBSD appears not to do
1487 * it.
1488 */
1489 memset(hostname, 0, sizeof(hostname));
1490 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001491
1492 if ((localpeer = strdup(hostname)) == NULL) {
1493 ha_alert("Cannot allocate memory for local peer.\n");
1494 exit(EXIT_FAILURE);
1495 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001496 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Emeric Brun2b920a12010-09-23 18:30:22 +02001497
William Lallemand24c928c2020-01-14 17:58:18 +01001498 /* we were in mworker mode, we should restart in mworker mode */
1499 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1500 global.mode |= MODE_MWORKER;
1501
Willy Tarreaubaaee002006-06-26 02:48:02 +02001502 /*
1503 * Initialize the previously static variables.
1504 */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001505
Willy Tarreau173d9952018-01-26 21:48:23 +01001506 totalconn = actconn = listeners = stopping = 0;
Cyril Bonté203ec5a2017-03-23 22:44:13 +01001507 killed = 0;
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001508
Willy Tarreaubaaee002006-06-26 02:48:02 +02001509
1510#ifdef HAPROXY_MEMMAX
Willy Tarreau70060452015-12-14 12:46:07 +01001511 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001512#endif
1513
Benoit GARNIERb413c2a2016-03-27 11:08:03 +02001514 tzset();
Willy Tarreau55542642021-10-08 09:33:24 +02001515 clock_init_process_date();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001516 start_date = now;
1517
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001518 ha_random_boot(argv);
Willy Tarreau84310e22014-02-14 11:59:04 +01001519
Willy Tarreau8ed669b2013-01-11 15:49:37 +01001520 if (init_acl() != 0)
1521 exit(1);
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001522
Amaury Denoyellec593bcd2021-05-19 15:35:29 +02001523#ifdef USE_OPENSSL
1524 /* Initialize the random generator.
1525 * Must be called before chroot for access to /dev/urandom
1526 */
1527 if (!ssl_initialize_random()) {
1528 ha_alert("OpenSSL random data generator initialization failed.\n");
1529 exit(1);
1530 }
1531#endif
1532
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001533 /* Initialise lua. */
1534 hlua_init();
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001535
Christopher Fauletff2613e2016-11-09 11:36:17 +01001536 /* Initialize process vars */
Willy Tarreaub7bfcb32021-08-31 08:13:25 +02001537 vars_init_head(&proc_vars, SCOPE_PROC);
Christopher Fauletff2613e2016-11-09 11:36:17 +01001538
Willy Tarreau43b78992009-01-25 15:42:27 +01001539 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001540#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001541 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001542#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001543#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001544 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001545#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001546#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001547 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001548#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001549#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001550 global.tune.options |= GTUNE_USE_EVPORTS;
1551#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001552#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001553 global.tune.options |= GTUNE_USE_SPLICE;
1554#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001555#if defined(USE_GETADDRINFO)
1556 global.tune.options |= GTUNE_USE_GAI;
1557#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001558#if defined(SO_REUSEPORT)
1559 global.tune.options |= GTUNE_USE_REUSEPORT;
1560#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001561#ifdef USE_THREAD
1562 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1563#endif
William Dauchya5194602020-03-28 19:29:58 +01001564 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565
1566 pid = getpid();
1567 progname = *argv;
1568 while ((tmp = strchr(progname, '/')) != NULL)
1569 progname = tmp + 1;
1570
Kevinm48936af2010-12-22 16:08:21 +00001571 /* the process name is used for the logs only */
Eric Salama7cea6062020-10-02 11:58:19 +02001572 chunk_initlen(&global.log_tag, strdup(progname), strlen(progname), strlen(progname));
1573 if (b_orig(&global.log_tag) == NULL) {
1574 chunk_destroy(&global.log_tag);
1575 ha_alert("Cannot allocate memory for log_tag.\n");
1576 exit(EXIT_FAILURE);
1577 }
Kevinm48936af2010-12-22 16:08:21 +00001578
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 argc--; argv++;
1580 while (argc > 0) {
1581 char *flag;
1582
1583 if (**argv == '-') {
1584 flag = *argv+1;
1585
1586 /* 1 arg */
1587 if (*flag == 'v') {
1588 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001589 if (flag[1] == 'v') /* -vv */
1590 display_build_opts();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591 exit(0);
1592 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001593#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001595 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001597#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001599 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001601#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001602 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001603 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001604#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001605#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001606 else if (*flag == 'd' && flag[1] == 'v')
1607 global.tune.options &= ~GTUNE_USE_EVPORTS;
1608#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001609#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001610 else if (*flag == 'd' && flag[1] == 'S')
1611 global.tune.options &= ~GTUNE_USE_SPLICE;
1612#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001613#if defined(USE_GETADDRINFO)
1614 else if (*flag == 'd' && flag[1] == 'G')
1615 global.tune.options &= ~GTUNE_USE_GAI;
1616#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001617#if defined(SO_REUSEPORT)
1618 else if (*flag == 'd' && flag[1] == 'R')
1619 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1620#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001621 else if (*flag == 'd' && flag[1] == 'V')
1622 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623 else if (*flag == 'V')
1624 arg_mode |= MODE_VERBOSE;
1625 else if (*flag == 'd' && flag[1] == 'b')
1626 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001627 else if (*flag == 'd' && flag[1] == 'D')
1628 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001629 else if (*flag == 'd' && flag[1] == 'W')
1630 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreau6e064432012-05-08 15:40:42 +02001631 else if (*flag == 'd' && flag[1] == 'M')
1632 mem_poison_byte = flag[2] ? strtol(flag + 2, NULL, 0) : 'P';
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001633 else if (*flag == 'd' && flag[1] == 'r')
1634 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001635 else if (*flag == 'd')
1636 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001637 else if (*flag == 'c' && flag[1] == 'c') {
1638 arg_mode |= MODE_CHECK_CONDITION;
1639 argv++;
1640 argc--;
1641 check_condition = *argv;
1642 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001643 else if (*flag == 'c')
1644 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001645 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001646 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001647 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001648 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001649#if defined(USE_SYSTEMD)
1650 global.tune.options |= GTUNE_USE_SYSTEMD;
1651#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001652 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 +01001653 usage(progname);
1654#endif
1655 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001656 else if (*flag == 'W')
1657 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001658 else if (*flag == 'q')
1659 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001660 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001661 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001662 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001663 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001664 }
William Lallemand4fc09692017-06-19 16:37:19 +02001665 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001666 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001667 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001668
Olivier Houchardf73629d2017-04-05 22:33:04 +02001669 argv++;
1670 argc--;
1671 }
William Lallemande7361152018-10-26 14:47:36 +02001672 else if (*flag == 'S') {
1673 struct wordlist *c;
1674
William Lallemanda6b32492020-06-04 23:49:20 +02001675 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001676 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1677 usage(progname);
1678 }
1679 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1680 ha_alert("Cannot allocate memory\n");
1681 exit(EXIT_FAILURE);
1682 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001683 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001684
1685 argv++;
1686 argc--;
1687 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001688 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1689 /* list of pids to finish ('f') or terminate ('t') */
1690
1691 if (flag[1] == 'f')
1692 oldpids_sig = SIGUSR1; /* finish then exit */
1693 else
1694 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001695 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001696 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001697 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1698 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001699 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001700 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001701 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001702 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001703 errno = 0;
1704 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1705 if (errno) {
1706 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1707 flag,
1708 *argv, strerror(errno));
1709 exit(1);
1710 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001711 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001712 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001713 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1714 flag, endptr);
1715 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001716 }
Chris Lane236062f2018-02-05 23:15:44 +00001717 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001718 if (oldpids[nb_oldpids] <= 0)
1719 usage(progname);
1720 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001721 }
1722 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001723 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1724 /* now that's a cfgfile list */
1725 argv++; argc--;
1726 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001727 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001728 ha_alert("Cannot load configuration file/directory %s : %s\n",
1729 *argv,
1730 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001731 exit(1);
1732 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001733 argv++; argc--;
1734 }
1735 break;
1736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001737 else { /* >=2 args */
1738 argv++; argc--;
1739 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001740 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001741
1742 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001743 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001744 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001745 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001747 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001748 free(localpeer);
1749 if ((localpeer = strdup(*argv)) == NULL) {
1750 ha_alert("Cannot allocate memory for local peer.\n");
1751 exit(EXIT_FAILURE);
1752 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001753 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001754 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001755 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001756 case 'f' :
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 Tarreau5d01a632009-06-22 16:02:30 +02001761 exit(1);
1762 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001763 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001764 case 'p' : cfg_pidfile = *argv; break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001765 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001766 }
1767 }
1768 }
1769 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001770 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771 argv++; argc--;
1772 }
1773
Christopher Faulete3a5e352017-10-24 13:53:54 +02001774 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001775 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001776 | MODE_DIAG | MODE_CHECK_CONDITION));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001777
William Lallemand944e6192018-11-21 15:48:31 +01001778 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001779 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001780 global.mode |= MODE_MWORKER_WAIT;
1781 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001782 }
1783
Willy Tarreau26146192021-07-21 10:01:36 +02001784 if ((global.mode & (MODE_MWORKER | MODE_CHECK | MODE_CHECK_CONDITION)) == MODE_MWORKER &&
1785 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001786 atexit_flag = 1;
1787 atexit(reexec_on_failure);
1788 }
1789
Willy Tarreau576132e2011-09-10 19:26:56 +02001790 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001791 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001792 exit(1);
1793 }
1794
Willy Tarreaubaaee002006-06-26 02:48:02 +02001795 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001796
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001797#ifdef USE_CPU_AFFINITY
1798 {
1799 int i;
Willy Tarreau44ea6312021-06-15 08:57:56 +02001800 ha_cpuset_zero(&cpu_map.proc);
1801 ha_cpuset_zero(&cpu_map.proc_t1);
Willy Tarreau26f42a02021-05-14 08:26:38 +02001802 for (i = 0; i < MAX_THREADS; ++i) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02001803 ha_cpuset_zero(&cpu_map.thread[i]);
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001804 }
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001805 }
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001806#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001807
Amaury Denoyelle11124302021-06-04 18:22:08 +02001808 usermsgs_clr("config");
1809
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001810 if (global.mode & MODE_CHECK_CONDITION) {
1811 int result;
1812
1813 uint32_t err;
1814 const char *errptr;
1815 char *errmsg = NULL;
1816
1817 char *args[MAX_LINE_ARGS+1];
1818 int arg = sizeof(args) / sizeof(*args);
1819 size_t outlen = strlen(check_condition) + 1;
Willy Tarreauc8194c32021-07-16 16:38:58 +02001820 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001821
1822 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02001823 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001824 &errptr);
1825
1826 if (err & PARSE_ERR_QUOTE) {
1827 ha_alert("Syntax Error in condition: Unmatched quote.\n");
1828 exit(2);
1829 }
1830
1831 if (err & PARSE_ERR_HEX) {
1832 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
1833 exit(2);
1834 }
1835
1836 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
1837 ha_alert("Error in condition: Line too long.\n");
1838 exit(2);
1839 }
1840
Willy Tarreauc8194c32021-07-16 16:38:58 +02001841 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001842 ha_alert("Error in condition: Too many words.\n");
1843 exit(2);
1844 }
1845
1846 if (err) {
1847 ha_alert("Unhandled error in condition, please report this to the developers.\n");
1848 exit(2);
1849 }
1850
Willy Tarreauc8194c32021-07-16 16:38:58 +02001851 /* remerge all words into a single expression */
1852 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
1853 ;
1854
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001855 result = cfg_eval_condition(args, &errmsg, &errptr);
1856
1857 if (result < 0) {
1858 if (errmsg)
1859 ha_alert("Failed to evaluate condition: %s\n", errmsg);
1860
1861 exit(2);
1862 }
1863
1864 exit(result ? 0 : 1);
1865 }
1866
William Lallemand944e6192018-11-21 15:48:31 +01001867 /* in wait mode, we don't try to read the configuration files */
1868 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001869 char *env_cfgfiles = NULL;
1870 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001871
William Lallemand944e6192018-11-21 15:48:31 +01001872 /* handle cfgfiles that are actually directories */
1873 cfgfiles_expand_directories();
1874
1875 if (LIST_ISEMPTY(&cfg_cfgfiles))
1876 usage(progname);
1877
1878
1879 list_for_each_entry(wl, &cfg_cfgfiles, list) {
1880 int ret;
1881
Christopher Faulet4e366822021-01-12 18:57:38 +01001882 if (env_err == 0) {
1883 if (!memprintf(&env_cfgfiles, "%s%s%s",
1884 (env_cfgfiles ? env_cfgfiles : ""),
1885 (env_cfgfiles ? ";" : ""), wl->s))
1886 env_err = 1;
1887 }
William Lallemand7b302d82019-05-20 11:15:37 +02001888
William Lallemand944e6192018-11-21 15:48:31 +01001889 ret = readcfgfile(wl->s);
1890 if (ret == -1) {
1891 ha_alert("Could not open configuration file %s : %s\n",
1892 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01001893 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001894 exit(1);
1895 }
1896 if (ret & (ERR_ABORT|ERR_FATAL))
1897 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
1898 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01001899 if (err_code & ERR_ABORT) {
1900 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001901 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01001902 }
Willy Tarreauc4382422009-12-06 13:10:44 +01001903 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001904
William Lallemand944e6192018-11-21 15:48:31 +01001905 /* do not try to resolve arguments nor to spot inconsistencies when
1906 * the configuration contains fatal errors caused by files not found
1907 * or failed memory allocations.
1908 */
1909 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1910 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01001911 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001912 exit(1);
1913 }
Christopher Faulet4e366822021-01-12 18:57:38 +01001914 if (env_err) {
1915 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
1916 exit(1);
1917 }
1918 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
1919 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02001920
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02001921 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001922 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01001923 struct mworker_proc *tmproc;
1924
William Lallemand482f9a92019-04-12 16:15:00 +02001925 setenv("HAPROXY_MWORKER", "1", 1);
1926
William Lallemand16dd1b32018-11-19 18:46:18 +01001927 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
1928
William Lallemandf3a86832019-04-01 11:29:58 +02001929 tmproc = calloc(1, sizeof(*tmproc));
William Lallemand16dd1b32018-11-19 18:46:18 +01001930 if (!tmproc) {
1931 ha_alert("Cannot allocate process structures.\n");
1932 exit(EXIT_FAILURE);
1933 }
William Lallemand8f7069a2019-04-12 16:09:23 +02001934 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand68836742021-11-10 10:49:06 +01001935 tmproc->failedreloads = 0;
William Lallemand16dd1b32018-11-19 18:46:18 +01001936 tmproc->reloads = 0;
William Lallemand16dd1b32018-11-19 18:46:18 +01001937 tmproc->pid = pid;
1938 tmproc->timestamp = start_date.tv_sec;
1939 tmproc->ipc_fd[0] = -1;
1940 tmproc->ipc_fd[1] = -1;
1941
1942 proc_self = tmproc;
1943
Willy Tarreau2b718102021-04-21 07:32:39 +02001944 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01001945 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001946
Willy Tarreau6185a032021-06-15 08:02:06 +02001947 tmproc = calloc(1, sizeof(*tmproc));
1948 if (!tmproc) {
1949 ha_alert("Cannot allocate process structures.\n");
1950 exit(EXIT_FAILURE);
1951 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001952
Willy Tarreau6185a032021-06-15 08:02:06 +02001953 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
1954 tmproc->pid = -1;
William Lallemand68836742021-11-10 10:49:06 +01001955 tmproc->failedreloads = 0;
Willy Tarreau6185a032021-06-15 08:02:06 +02001956 tmproc->reloads = 0;
1957 tmproc->timestamp = -1;
Willy Tarreau6185a032021-06-15 08:02:06 +02001958 tmproc->ipc_fd[0] = -1;
1959 tmproc->ipc_fd[1] = -1;
William Lallemandce83b4a2018-10-26 14:47:30 +02001960
Willy Tarreau6185a032021-06-15 08:02:06 +02001961 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
1962 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02001963 }
Willy Tarreau6185a032021-06-15 08:02:06 +02001964
1965 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01001966 }
1967 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
1968 struct wordlist *it, *c;
1969
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02001970 /* get the info of the children in the env */
1971 if (mworker_env_to_proc_list() < 0) {
1972 exit(EXIT_FAILURE);
1973 }
William Lallemande7361152018-10-26 14:47:36 +02001974
William Lallemand550db6d2018-11-06 17:37:12 +01001975 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02001976
William Lallemand550db6d2018-11-06 17:37:12 +01001977 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02001978 ha_alert("Can't create the master's CLI.\n");
1979 exit(EXIT_FAILURE);
1980 }
William Lallemande7361152018-10-26 14:47:36 +02001981
William Lallemand550db6d2018-11-06 17:37:12 +01001982 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
1983
1984 if (mworker_cli_proxy_new_listener(c->s) < 0) {
1985 ha_alert("Can't create the master's CLI.\n");
1986 exit(EXIT_FAILURE);
1987 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001988 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01001989 free(c->s);
1990 free(c);
1991 }
1992 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001993 }
1994
Eric Salama5ba83352021-03-16 15:11:17 +01001995 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
1996 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
1997 }
1998
Christopher Faulet27c8d202021-10-13 09:50:53 +02001999 /* destroy unreferenced defaults proxies */
2000 proxy_destroy_all_unref_defaults();
2001
Willy Tarreaue90904d2021-02-12 14:08:31 +01002002
Willy Tarreaubb925012009-07-23 13:36:36 +02002003 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02002004 for (px = proxies_list; px; px = px->next) {
2005 struct server *srv;
2006 struct post_proxy_check_fct *ppcf;
2007 struct post_server_check_fct *pscf;
2008
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002009 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002010 continue;
2011
Christopher Fauletc1692962019-08-12 09:51:07 +02002012 list_for_each_entry(pscf, &post_server_check_list, list) {
2013 for (srv = px->srv; srv; srv = srv->next)
2014 err_code |= pscf->fct(srv);
2015 }
2016 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2017 err_code |= ppcf->fct(px);
2018 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002019 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002020 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002021 exit(1);
2022 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002023
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002024 err_code |= pattern_finalize_config();
2025 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2026 ha_alert("Failed to finalize pattern config.\n");
2027 exit(1);
2028 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002029
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002030 if (global.rlimit_memmax_all)
2031 global.rlimit_memmax = global.rlimit_memmax_all;
2032
Willy Tarreaue5733232019-05-22 19:24:06 +02002033#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002034 err_code |= netns_init();
2035 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002036 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002037 exit(1);
2038 }
2039#endif
2040
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002041 /* Apply server states */
2042 apply_server_state();
2043
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002044 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002045 srv_compute_all_admin_states(px);
2046
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002047 /* Apply servers' configured address */
2048 err_code |= srv_init_addr();
2049 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002050 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002051 exit(1);
2052 }
2053
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002054 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2055 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2056 exit(1);
2057 }
2058
Willy Tarreaubaaee002006-06-26 02:48:02 +02002059 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002060 struct peers *pr;
2061 struct proxy *px;
2062
Willy Tarreaubebd2122020-04-15 16:06:11 +02002063 if (warned & WARN_ANY)
2064 qfprintf(stdout, "Warnings were found.\n");
2065
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002066 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002067 if (pr->peers_fe)
2068 break;
2069
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002070 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002071 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002072 break;
2073
Emeric Brunbc5c8212021-08-13 09:32:50 +02002074 if (!px) {
2075 /* We may only have log-forward section */
2076 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002077 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002078 break;
2079 }
2080
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002081 if (pr || px) {
2082 /* At least one peer or one listener has been found */
2083 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002084 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002085 }
2086 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2087 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002088 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002089
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002090 if (global.mode & MODE_DIAG) {
2091 cfg_run_diagnostics();
2092 }
2093
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002094 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002095 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002096
Willy Tarreaue6945732016-12-21 19:57:00 +01002097 list_for_each_entry(pcf, &post_check_list, list) {
2098 err_code |= pcf->fct();
2099 if (err_code & (ERR_ABORT|ERR_FATAL))
2100 exit(1);
2101 }
2102
Willy Tarreaubaaee002006-06-26 02:48:02 +02002103 if (cfg_maxconn > 0)
2104 global.maxconn = cfg_maxconn;
2105
Willy Tarreau4975d142021-03-13 11:00:33 +01002106 if (global.cli_fe)
2107 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002108
2109 if (cfg_peers) {
2110 /* peers also need to bypass global maxconn */
2111 struct peers *p = cfg_peers;
2112
2113 for (p = cfg_peers; p; p = p->next)
2114 if (p->peers_fe)
2115 global.maxsock += p->peers_fe->maxconn;
2116 }
2117
Willy Tarreaubaaee002006-06-26 02:48:02 +02002118 if (cfg_pidfile) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002119 free(global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002120 global.pidfile = strdup(cfg_pidfile);
2121 }
2122
Willy Tarreaud0256482015-01-15 21:45:22 +01002123 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002124 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2125 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2126 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2127 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002128 *
2129 * If memmax is set, then it depends on which values are set. If
2130 * maxsslconn is set, we use memmax to determine how many cleartext
2131 * connections may be added, and set maxconn to the sum of the two.
2132 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2133 * the remaining amount of memory between memmax and the cleartext
2134 * connections. If neither are set, then it is considered that all
2135 * connections are SSL-capable, and maxconn is computed based on this,
2136 * then maxsslconn accordingly. We need to know if SSL is used on the
2137 * frontends, backends, or both, because when it's used on both sides,
2138 * we need twice the value for maxsslconn, but we only count the
2139 * handshake once since it is not performed on the two sides at the
2140 * same time (frontend-side is terminated before backend-side begins).
2141 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002142 * ssl_handshake_cost during its initialization. In any case, if
2143 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2144 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002145 */
Willy Tarreauac350932019-03-01 15:43:14 +01002146 ideal_maxconn = compute_ideal_maxconn();
2147
Willy Tarreaud0256482015-01-15 21:45:22 +01002148 if (!global.rlimit_memmax) {
2149 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002150 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002151 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2152 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2153 }
2154 }
2155#ifdef USE_OPENSSL
2156 else if (!global.maxconn && !global.maxsslconn &&
2157 (global.ssl_used_frontend || global.ssl_used_backend)) {
2158 /* memmax is set, compute everything automatically. Here we want
2159 * to ensure that all SSL connections will be served. We take
2160 * care of the number of sides where SSL is used, and consider
2161 * the worst case : SSL used on both sides and doing a handshake
2162 * simultaneously. Note that we can't have more than maxconn
2163 * handshakes at a time by definition, so for the worst case of
2164 * two SSL conns per connection, we count a single handshake.
2165 */
2166 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2167 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002168 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002169
2170 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2171 mem -= global.maxzlibmem;
2172 mem = mem * MEM_USABLE_RATIO;
2173
Willy Tarreau304e17e2020-03-10 17:54:54 +01002174 /* Principle: we test once to set maxconn according to the free
2175 * memory. If it results in values the system rejects, we try a
2176 * second time by respecting rlim_fd_max. If it fails again, we
2177 * go back to the initial value and will let the final code
2178 * dealing with rlimit report the error. That's up to 3 attempts.
2179 */
2180 do {
2181 global.maxconn = mem /
2182 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2183 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2184 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002185
Willy Tarreau304e17e2020-03-10 17:54:54 +01002186 if (retried == 1)
2187 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2188 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002189#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002190 if (global.maxconn > SYSTEM_MAXCONN)
2191 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002192#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002193 global.maxsslconn = sides * global.maxconn;
2194
2195 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2196 break;
2197 } while (retried++ < 2);
2198
Willy Tarreaud0256482015-01-15 21:45:22 +01002199 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2200 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2201 global.maxconn, global.maxsslconn);
2202 }
2203 else if (!global.maxsslconn &&
2204 (global.ssl_used_frontend || global.ssl_used_backend)) {
2205 /* memmax and maxconn are known, compute maxsslconn automatically.
2206 * maxsslconn being forced, we don't know how many of it will be
2207 * on each side if both sides are being used. The worst case is
2208 * when all connections use only one SSL instance because
2209 * handshakes may be on two sides at the same time.
2210 */
2211 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2212 int64_t mem = global.rlimit_memmax * 1048576ULL;
2213 int64_t sslmem;
2214
2215 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2216 mem -= global.maxzlibmem;
2217 mem = mem * MEM_USABLE_RATIO;
2218
Willy Tarreau87b09662015-04-03 00:22:06 +02002219 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002220 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2221 global.maxsslconn = round_2dig(global.maxsslconn);
2222
2223 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002224 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2225 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2226 "without SSL is %d, but %d was found and SSL is in use.\n",
2227 global.rlimit_memmax,
2228 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2229 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002230 exit(1);
2231 }
2232
2233 if (global.maxsslconn > sides * global.maxconn)
2234 global.maxsslconn = sides * global.maxconn;
2235
2236 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2237 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2238 }
2239#endif
2240 else if (!global.maxconn) {
2241 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2242 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2243 int64_t mem = global.rlimit_memmax * 1048576ULL;
2244 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002245 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002246
2247 if (global.ssl_used_frontend || global.ssl_used_backend)
2248 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2249
2250 mem -= global.maxzlibmem;
2251 mem = mem * MEM_USABLE_RATIO;
2252
2253 clearmem = mem;
2254 if (sides)
2255 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2256
Willy Tarreau304e17e2020-03-10 17:54:54 +01002257 /* Principle: we test once to set maxconn according to the free
2258 * memory. If it results in values the system rejects, we try a
2259 * second time by respecting rlim_fd_max. If it fails again, we
2260 * go back to the initial value and will let the final code
2261 * dealing with rlimit report the error. That's up to 3 attempts.
2262 */
2263 do {
2264 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2265 if (retried == 1)
2266 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2267 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002268#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002269 if (global.maxconn > SYSTEM_MAXCONN)
2270 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002271#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002272
Willy Tarreau304e17e2020-03-10 17:54:54 +01002273 if (clearmem <= 0 || !global.maxconn) {
2274 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2275 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2276 "is %d, but %d was found.\n",
2277 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002278 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002279 global.maxsslconn);
2280 exit(1);
2281 }
2282
2283 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2284 break;
2285 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002286
2287 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2288 if (sides && global.maxsslconn > sides * global.maxconn) {
2289 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2290 "to be limited to %d. Better reduce global.maxsslconn to get more "
2291 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2292 }
2293 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2294 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002295 }
2296
Willy Tarreaua409f302020-03-10 17:08:53 +01002297 global.maxsock = compute_ideal_maxsock(global.maxconn);
2298 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002299 if (!global.maxpipes)
2300 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301
Olivier Houchard88698d92019-04-16 19:07:22 +02002302 /* update connection pool thresholds */
2303 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2304 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2305
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002306 proxy_adjust_all_maxconn();
2307
Willy Tarreau1db37712007-06-03 17:16:49 +02002308 if (global.tune.maxpollevents <= 0)
2309 global.tune.maxpollevents = MAX_POLL_EVENTS;
2310
Willy Tarreau060a7612021-03-10 11:06:26 +01002311 if (global.tune.runqueue_depth <= 0) {
2312 /* tests on various thread counts from 1 to 64 have shown an
2313 * optimal queue depth following roughly 1/sqrt(threads).
2314 */
2315 int s = my_flsl(global.nbthread);
2316 s += (global.nbthread / s); // roughly twice the sqrt.
2317 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2318 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002319
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002320 if (global.tune.recv_enough == 0)
2321 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2322
Willy Tarreau27a674e2009-08-17 07:23:33 +02002323 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2324 global.tune.maxrewrite = global.tune.bufsize / 2;
2325
Amaury Denoyelle11124302021-06-04 18:22:08 +02002326 usermsgs_clr(NULL);
2327
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2329 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002330 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002331 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2332 }
2333
William Lallemand095ba4c2017-06-01 17:38:50 +02002334 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002335 /* command line daemon mode inhibits foreground and debug modes mode */
2336 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002337 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002338 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002339
2340 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002341
William Lallemand095ba4c2017-06-01 17:38:50 +02002342 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002343 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002344 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002345 }
2346
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002347 if (global.nbthread < 1)
2348 global.nbthread = 1;
2349
Christopher Faulet3ef26392017-08-29 16:46:57 +02002350 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002351 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002352 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002353 exit(1);
2354 }
2355
Christopher Faulet96d44832017-11-14 22:02:30 +01002356 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002357 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002358 exit(1);
2359 }
2360
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002361 /*
2362 * Note: we could register external pollers here.
2363 * Built-in pollers have been registered before main().
2364 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002365
Willy Tarreau43b78992009-01-25 15:42:27 +01002366 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002367 disable_poller("kqueue");
2368
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002369 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2370 disable_poller("evports");
2371
Willy Tarreau43b78992009-01-25 15:42:27 +01002372 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002373 disable_poller("epoll");
2374
Willy Tarreau43b78992009-01-25 15:42:27 +01002375 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002376 disable_poller("poll");
2377
Willy Tarreau43b78992009-01-25 15:42:27 +01002378 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002379 disable_poller("select");
2380
2381 /* Note: we could disable any poller by name here */
2382
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002383 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002384 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002385 fprintf(stderr, "\n");
2386 list_filters(stderr);
2387 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002388
Willy Tarreau4f60f162007-04-08 16:39:58 +02002389 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002390 ha_alert("No polling mechanism available.\n"
2391 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2392 " is too low on this platform to support maxconn and the number of listeners\n"
2393 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2394 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2395 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2396 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2397 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2398 " check build settings using 'haproxy -vv'.\n\n",
2399 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002400 exit(1);
2401 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002402 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2403 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002404 }
2405
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002406 if (!global.node)
2407 global.node = strdup(hostname);
2408
Willy Tarreau02b092f2020-10-07 18:36:54 +02002409 /* stop disabled proxies */
2410 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002411 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002412 stop_proxy(px);
2413 }
2414
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002415 if (!hlua_post_init())
2416 exit(1);
Thomas Holmes6abded42015-05-12 16:23:58 +01002417
Maxime de Roucy0f503922016-05-13 23:52:55 +02002418 free(err_msg);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002419}
2420
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002421void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002423 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002424 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002425 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002426 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002427 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002428 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002429 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002430 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002431 struct per_thread_init_fct *tif, *tifb;
2432 struct per_thread_deinit_fct *tdf, *tdfb;
2433 struct per_thread_alloc_fct *taf, *tafb;
2434 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002435 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002436 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002437 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002438 int cur_fd;
2439
2440 /* At this point the listeners state is weird:
2441 * - most listeners are still bound and referenced in their protocol
2442 * - some might be zombies that are not in their proto anymore, but
2443 * still appear in their proxy's listeners with a valid FD.
2444 * - some might be stopped and still appear in their proxy as FD #-1
2445 * - among all of them, some might be inherited hence shared and we're
2446 * not allowed to pause them or whatever, we must just close them.
2447 * - finally some are not listeners (pipes, logs, stdout, etc) and
2448 * must be left intact.
2449 *
2450 * The safe way to proceed is to unbind (and close) whatever is not yet
2451 * unbound so that no more receiver/listener remains alive. Then close
2452 * remaining listener FDs, which correspond to zombie listeners (those
2453 * belonging to disabled proxies that were in another process).
2454 * objt_listener() would be cleaner here but not converted yet.
2455 */
2456 protocol_unbind_all();
2457
2458 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002459 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002460 continue;
2461
Willy Tarreaua74cb382020-10-15 21:29:49 +02002462 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002463 struct listener *l = fdtab[cur_fd].owner;
2464
2465 BUG_ON(l->state != LI_INIT);
2466 unbind_listener(l);
2467 }
2468 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002469
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002470 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002471 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002472 /* build a list of unique uri_auths */
2473 if (!ua)
2474 ua = p->uri_auth;
2475 else {
2476 /* check if p->uri_auth is unique */
2477 for (uap = ua; uap; uap=uap->next)
2478 if (uap == p->uri_auth)
2479 break;
2480
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002481 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002482 /* add it, if it is */
2483 p->uri_auth->next = ua;
2484 ua = p->uri_auth;
2485 }
William Lallemand0f99e342011-10-12 17:50:54 +02002486 }
2487
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002488 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002490 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002491 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002492
Christopher Faulet27c8d202021-10-13 09:50:53 +02002493 /* destroy all referenced defaults proxies */
2494 proxy_destroy_all_unref_defaults();
2495
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002496 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002497 struct stat_scope *scope, *scopep;
2498
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002499 uap = ua;
2500 ua = ua->next;
2501
Willy Tarreaua534fea2008-08-03 12:19:50 +02002502 free(uap->uri_prefix);
2503 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002504 free(uap->node);
2505 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002506
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002507 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002508 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002509
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002510 scope = uap->scope;
2511 while (scope) {
2512 scopep = scope;
2513 scope = scope->next;
2514
2515 free(scopep->px_id);
2516 free(scopep);
2517 }
2518
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002519 free(uap);
2520 }
2521
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002522 userlist_free(userlist);
2523
David Carlier834cb2e2015-09-25 12:02:25 +01002524 cfg_unregister_sections();
2525
Christopher Faulet0132d062017-07-26 15:33:35 +02002526 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002527
Willy Tarreau05554e62016-12-21 20:46:26 +01002528 list_for_each_entry(pdf, &post_deinit_list, list)
2529 pdf->fct();
2530
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002531 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002532 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002533 ha_free(&global.chroot);
2534 ha_free(&global.pidfile);
2535 ha_free(&global.node);
2536 ha_free(&global.desc);
2537 ha_free(&oldpids);
2538 ha_free(&old_argv);
2539 ha_free(&localpeer);
2540 ha_free(&global.server_state_base);
2541 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002542 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002543 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002544
William Lallemand0f99e342011-10-12 17:50:54 +02002545 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002546 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002547 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002548 free(log);
2549 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002550 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002551 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002552 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002553 free(wl);
2554 }
2555
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002556 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2557 if (bol->must_free)
2558 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002559 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002560 free(bol);
2561 }
2562
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002563 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002564 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002565 free(pxdf);
2566 }
2567
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002568 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002569 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002570 free(pdf);
2571 }
2572
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002573 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002574 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002575 free(srvdf);
2576 }
2577
Tim Duesterhusfc854942020-09-10 19:46:42 +02002578 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002579 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002580 free(pcf);
2581 }
2582
Tim Duesterhus34bef072020-07-04 11:49:50 +02002583 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002584 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002585 free(pscf);
2586 }
2587
Tim Duesterhus53508d62020-09-10 19:46:40 +02002588 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002589 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002590 free(ppcf);
2591 }
2592
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002593 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002594 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002595 free(tif);
2596 }
2597
2598 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002599 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002600 free(tdf);
2601 }
2602
2603 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002604 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002605 free(taf);
2606 }
2607
2608 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002609 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002610 free(tff);
2611 }
2612
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002613 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002614 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002615 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002616} /* end deinit() */
2617
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002618__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002619{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002620 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002621 deinit();
2622 exit(status);
2623}
William Lallemand72160322018-11-06 17:37:16 +01002624
Willy Tarreau918ff602011-07-25 16:33:49 +02002625/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002626void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002627{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002628 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002629
Willy Tarreau55542642021-10-08 09:33:24 +02002630 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002631 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002632 wake_expired_tasks();
2633
William Lallemand1aab50b2018-06-07 09:46:01 +02002634 /* check if we caught some signals and process them in the
2635 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002636 if (signal_queue_len && tid == 0) {
2637 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002638 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002639 }
2640
2641 /* Process a few tasks */
2642 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002643
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002644 /* also stop if we failed to cleanly stop all tasks */
2645 if (killed > 1)
2646 break;
2647
Willy Tarreau10146c92015-04-13 20:44:19 +02002648 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002649 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002650 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002651 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002652 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002653 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2654 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002655 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002656 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002657 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002658 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002659 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002660 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002661
Willy Tarreau4f46a352020-03-23 09:27:28 +01002662 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002663 int i;
2664
2665 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002666 /* stop muxes before acknowledging stopping */
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002667 if (!(stopping_thread_mask & tid_bit)) {
2668 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2669 wake = 1;
2670 }
2671
Willy Tarreau1db42732021-04-06 11:44:07 +02002672 if (_HA_ATOMIC_OR_FETCH(&stopping_thread_mask, tid_bit) == tid_bit) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002673 /* notify all threads that stopping was just set */
2674 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002675 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002676 wake_thread(i);
2677 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002678 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002679
2680 /* stop when there's nothing left to do */
2681 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002682 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2683 /* wake all threads waiting on jobs==0 */
2684 for (i = 0; i < global.nbthread; i++)
2685 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2686 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002687 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002688 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002689 }
2690
Willy Tarreauc49ba522019-12-11 08:12:23 +01002691 /* If we have to sleep, measure how long */
2692 next = wake ? TICK_ETERNITY : next_timer_expiry();
2693
Willy Tarreau58b458d2008-06-29 22:40:23 +02002694 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002695 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002696
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002697 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002698 }
2699}
2700
Christopher Faulet1d17c102017-08-29 15:38:48 +02002701static void *run_thread_poll_loop(void *data)
2702{
Willy Tarreau082b6282019-05-22 14:42:12 +02002703 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002704 struct per_thread_init_fct *ptif;
2705 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002706 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002707 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002708 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2709 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002710
Willy Tarreau43ab05b2021-09-28 09:43:11 +02002711 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02002712 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02002713 clock_set_local_source();
Willy Tarreau91e6df02019-05-03 17:21:18 +02002714
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002715 /* Now, initialize one thread init at a time. This is better since
2716 * some init code is a bit tricky and may release global resources
2717 * after reallocating them locally. This will also ensure there is
2718 * no race on file descriptors allocation.
2719 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002720#ifdef USE_THREAD
2721 pthread_mutex_lock(&init_mutex);
2722#endif
2723 /* The first thread must set the number of threads left */
2724 if (!init_left)
2725 init_left = global.nbthread;
2726 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002727
Willy Tarreau55542642021-10-08 09:33:24 +02002728 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002729
Willy Tarreau082b6282019-05-22 14:42:12 +02002730 /* per-thread alloc calls performed here are not allowed to snoop on
2731 * other threads, so they are free to initialize at their own rhythm
2732 * as long as they act as if they were alone. None of them may rely
2733 * on resources initialized by the other ones.
2734 */
2735 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2736 if (!ptaf->fct()) {
2737 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002738#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002739 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002740#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02002741 exit(1);
2742 }
2743 }
2744
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002745 /* per-thread init calls performed here are not allowed to snoop on
2746 * other threads, so they are free to initialize at their own rhythm
2747 * as long as they act as if they were alone.
2748 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002749 list_for_each_entry(ptif, &per_thread_init_list, list) {
2750 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002751 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002752#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002753 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002754#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002755 exit(1);
2756 }
2757 }
2758
Willy Tarreau71092822019-06-10 09:51:04 +02002759 /* enabling protocols will result in fd_insert() calls to be performed,
2760 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002761 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002762 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002763 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002764 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002765
Willy Tarreau34a150c2019-06-11 09:16:41 +02002766#ifdef USE_THREAD
2767 pthread_cond_broadcast(&init_cond);
2768 pthread_mutex_unlock(&init_mutex);
2769
2770 /* now wait for other threads to finish starting */
2771 pthread_mutex_lock(&init_mutex);
2772 while (init_left)
2773 pthread_cond_wait(&init_cond, &init_mutex);
2774 pthread_mutex_unlock(&init_mutex);
2775#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002776
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002777#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2778 /* Let's refrain from using setuid executables. This way the impact of
2779 * an eventual vulnerability in a library remains limited. It may
2780 * impact external checks but who cares about them anyway ? In the
2781 * worst case it's possible to disable the option. Obviously we do this
2782 * in workers only. We can't hard-fail on this one as it really is
2783 * implementation dependent though we're interested in feedback, hence
2784 * the warning.
2785 */
2786 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2787 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002788 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 +01002789 ha_warning("Failed to disable setuid, please report to developers with detailed "
2790 "information about your operating system. You can silence this warning "
2791 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2792 }
2793 }
2794#endif
2795
Willy Tarreaud96f1122019-12-03 07:07:36 +01002796#if defined(RLIMIT_NPROC)
2797 /* all threads have started, it's now time to prevent any new thread
2798 * or process from starting. Obviously we do this in workers only. We
2799 * can't hard-fail on this one as it really is implementation dependent
2800 * though we're interested in feedback, hence the warning.
2801 */
2802 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2803 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2804 static int warn_fail;
2805
Willy Tarreau18515722021-04-06 11:57:41 +02002806 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002807 ha_warning("Failed to disable forks, please report to developers with detailed "
2808 "information about your operating system. You can silence this warning "
2809 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2810 }
2811 }
2812#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002813 run_poll_loop();
2814
2815 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2816 ptdf->fct();
2817
Willy Tarreau082b6282019-05-22 14:42:12 +02002818 list_for_each_entry(ptff, &per_thread_free_list, list)
2819 ptff->fct();
2820
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002821#ifdef USE_THREAD
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002822 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002823 if (tid > 0)
2824 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002825#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002826 return NULL;
2827}
Christopher Faulet1d17c102017-08-29 15:38:48 +02002828
William Dauchyf9af9d72019-11-17 15:47:16 +01002829/* set uid/gid depending on global settings */
2830static void set_identity(const char *program_name)
2831{
2832 if (global.gid) {
2833 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
2834 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
2835 " without 'uid'/'user' is generally useless.\n", program_name);
2836
2837 if (setgid(global.gid) == -1) {
2838 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
2839 protocol_unbind_all();
2840 exit(1);
2841 }
2842 }
2843
2844 if (global.uid && setuid(global.uid) == -1) {
2845 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
2846 protocol_unbind_all();
2847 exit(1);
2848 }
2849}
2850
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851int main(int argc, char **argv)
2852{
2853 int err, retry;
2854 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02002855 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02002856 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
2857
2858 /* Catch forced CFLAGS that miss 2-complement integer overflow */
2859 if (intovf + 0x7FFFFFFF >= intovf) {
2860 fprintf(stderr,
2861 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
2862 "The source code was miscompiled by the compiler, which usually indicates that\n"
2863 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
2864 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
2865 "and INSTALL files to decide on the best way to pass your local build options.\n"
2866 "\nBuild options :"
2867#ifdef BUILD_TARGET
2868 "\n TARGET = " BUILD_TARGET
2869#endif
2870#ifdef BUILD_CPU
2871 "\n CPU = " BUILD_CPU
2872#endif
2873#ifdef BUILD_CC
2874 "\n CC = " BUILD_CC
2875#endif
2876#ifdef BUILD_CFLAGS
2877 "\n CFLAGS = " BUILD_CFLAGS
2878#endif
2879#ifdef BUILD_OPTIONS
2880 "\n OPTIONS = " BUILD_OPTIONS
2881#endif
2882#ifdef BUILD_DEBUG
2883 "\n DEBUG = " BUILD_DEBUG
2884#endif
2885 "\n\n");
2886 return 1;
2887 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002888
Olivier Houchard5fa300d2018-02-03 15:15:21 +01002889 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01002890
Willy Tarreaubf696402019-03-01 10:09:28 +01002891 /* take a copy of initial limits before we possibly change them */
2892 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02002893
2894 if (limit.rlim_max == RLIM_INFINITY)
2895 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01002896 rlim_fd_cur_at_boot = limit.rlim_cur;
2897 rlim_fd_max_at_boot = limit.rlim_max;
2898
Willy Tarreau5794fb02018-11-25 18:43:29 +01002899 /* process all initcalls in order of potential dependency */
2900 RUN_INITCALLS(STG_PREPARE);
2901 RUN_INITCALLS(STG_LOCK);
2902 RUN_INITCALLS(STG_ALLOC);
2903 RUN_INITCALLS(STG_POOL);
2904 RUN_INITCALLS(STG_REGISTER);
2905 RUN_INITCALLS(STG_INIT);
2906
Emeric Bruncf20bf12010-10-22 16:06:11 +02002907 init(argc, argv);
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002908 signal_register_fct(SIGQUIT, dump, SIGQUIT);
2909 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
2910 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02002911 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912
Willy Tarreaue437c442010-03-17 18:02:46 +01002913 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
2914 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
2915 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002917 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918
Willy Tarreaudc23a922011-02-16 11:10:36 +01002919 /* ulimits */
2920 if (!global.rlimit_nofile)
2921 global.rlimit_nofile = global.maxsock;
2922
2923 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01002924 limit.rlim_cur = global.rlimit_nofile;
2925 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
2926
Willy Tarreaudc23a922011-02-16 11:10:36 +01002927 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02002928 getrlimit(RLIMIT_NOFILE, &limit);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002929 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2930 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
2931 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002932 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002933 }
2934 else {
2935 /* try to set it to the max possible at least */
2936 limit.rlim_cur = limit.rlim_max;
2937 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
2938 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02002939
William Dauchya5194602020-03-28 19:29:58 +01002940 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002941 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
2942 global.rlimit_nofile = limit.rlim_cur;
2943 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01002944 }
2945 }
2946
2947 if (global.rlimit_memmax) {
2948 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01002949 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01002950#ifdef RLIMIT_AS
2951 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002952 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2953 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2954 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002955 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002956 }
2957 else
William Dauchya5194602020-03-28 19:29:58 +01002958 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002959 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002960 }
2961#else
2962 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002963 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2964 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2965 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002966 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002967 }
2968 else
William Dauchya5194602020-03-28 19:29:58 +01002969 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002970 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002971 }
2972#endif
2973 }
2974
Olivier Houchardf73629d2017-04-05 22:33:04 +02002975 if (old_unixsocket) {
William Lallemand85b0bd92017-06-01 17:38:53 +02002976 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02002977 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002978 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02002979 if (!(global.mode & MODE_MWORKER))
2980 exit(1);
2981 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02002982 }
2983 }
William Lallemand85b0bd92017-06-01 17:38:53 +02002984
Willy Tarreaubaaee002006-06-26 02:48:02 +02002985 /* We will loop at most 100 times with 10 ms delay each time.
2986 * That's at most 1 second. We only send a signal to old pids
2987 * if we cannot grab at least one port.
2988 */
2989 retry = MAX_START_RETRIES;
2990 err = ERR_NONE;
2991 while (retry >= 0) {
2992 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02002993 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01002994 /* exit the loop on no error or fatal error */
2995 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002996 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02002997 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 break;
2999
3000 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3001 * listening sockets. So on those platforms, it would be wiser to
3002 * simply send SIGUSR1, which will not be undoable.
3003 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003004 if (tell_old_pids(SIGTTOU) == 0) {
3005 /* no need to wait if we can't contact old pids */
3006 retry = 0;
3007 continue;
3008 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 /* give some time to old processes to stop listening */
3010 w.tv_sec = 0;
3011 w.tv_usec = 10*1000;
3012 select(0, NULL, NULL, NULL, &w);
3013 retry--;
3014 }
3015
Willy Tarreaue91bff22020-09-02 11:11:43 +02003016 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003017 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003018 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003019 if (retry != MAX_START_RETRIES && nb_oldpids) {
3020 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003022 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003023 exit(1);
3024 }
3025
William Lallemand944e6192018-11-21 15:48:31 +01003026 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003027 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003028 /* Note: we don't have to send anything to the old pids because we
3029 * never stopped them. */
3030 exit(1);
3031 }
3032
Willy Tarreaue91bff22020-09-02 11:11:43 +02003033 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003034 * the previous process gave us, we don't need them anymore
3035 */
3036 while (xfer_sock_list != NULL) {
3037 struct xfer_sock_list *tmpxfer = xfer_sock_list->next;
3038 close(xfer_sock_list->fd);
3039 free(xfer_sock_list->iface);
3040 free(xfer_sock_list->namespace);
3041 free(xfer_sock_list);
3042 xfer_sock_list = tmpxfer;
3043 }
Willy Tarreaudd815982007-10-16 12:25:14 +02003044
Willy Tarreaubaaee002006-06-26 02:48:02 +02003045 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003046 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3047 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003048
Willy Tarreaubaaee002006-06-26 02:48:02 +02003049 /* MODE_QUIET can inhibit alerts and warnings below this line */
3050
PiBa-NL149a81a2017-12-25 21:03:31 +01003051 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3052 /* either stdin/out/err are already closed or should stay as they are. */
3053 if ((global.mode & MODE_DAEMON)) {
3054 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3055 global.mode &= ~MODE_VERBOSE;
3056 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3057 }
3058 } else {
3059 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3060 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003061 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003062 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 }
3064
3065 /* open log & pid files before the chroot */
William Lallemand80293002017-11-06 11:00:03 +01003066 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067 unlink(global.pidfile);
3068 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3069 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003070 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 if (nb_oldpids)
3072 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003073 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 exit(1);
3075 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003076 }
3077
Willy Tarreaub38651a2007-03-24 17:24:39 +01003078 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003079 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3080 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003081 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003082 exit(1);
3083 }
3084
Jackie Tapia749f74c2020-07-22 18:59:40 -05003085 /* If the user is not root, we'll still let them try the configuration
3086 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003087 */
3088 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003089 ha_warning("[%s.main()] Some options which require full privileges"
3090 " might not work well.\n"
3091 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003092
William Lallemand095ba4c2017-06-01 17:38:50 +02003093 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3094
3095 /* chroot if needed */
3096 if (global.chroot != NULL) {
3097 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003098 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003099 if (nb_oldpids)
3100 tell_old_pids(SIGTTIN);
3101 protocol_unbind_all();
3102 exit(1);
3103 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003104 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003105 }
3106
William Lallemand944e6192018-11-21 15:48:31 +01003107 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003108 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109
William Lallemand27edc4b2019-05-07 17:49:33 +02003110 /* send a SIGTERM to workers who have a too high reloads number */
3111 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3112 mworker_kill_max_reloads(SIGTERM);
3113
Willy Tarreaubaaee002006-06-26 02:48:02 +02003114 /* Note that any error at this stage will be fatal because we will not
3115 * be able to restart the old pids.
3116 */
3117
William Dauchyf9af9d72019-11-17 15:47:16 +01003118 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3119 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003120
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 /* check ulimits */
3122 limit.rlim_cur = limit.rlim_max = 0;
3123 getrlimit(RLIMIT_NOFILE, &limit);
3124 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003125 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3126 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3127 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3128 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3129 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003130 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003131 }
3132 else
3133 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003134 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003135 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3136 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003137 }
3138
William Lallemand944e6192018-11-21 15:48:31 +01003139 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003140 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003141 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003142 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003143
William Lallemand095ba4c2017-06-01 17:38:50 +02003144 /*
3145 * if daemon + mworker: must fork here to let a master
3146 * process live in background before forking children
3147 */
William Lallemand73b85e72017-06-01 17:38:51 +02003148
3149 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3150 && (global.mode & MODE_MWORKER)
3151 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003152 ret = fork();
3153 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003154 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003155 protocol_unbind_all();
3156 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003157 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003158 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003159 } else /* change the process group ID in the child (master process) */
3160 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003161 }
William Lallemande20b6a62017-06-01 17:38:55 +02003162
William Lallemande20b6a62017-06-01 17:38:55 +02003163
William Lallemanddeed7802017-11-06 11:00:04 +01003164 /* if in master-worker mode, write the PID of the father */
3165 if (global.mode & MODE_MWORKER) {
3166 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003167 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003168 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003169 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003170 }
3171
Willy Tarreaubaaee002006-06-26 02:48:02 +02003172 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003173 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003174 if (global.mode & MODE_MWORKER)
3175 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003176
3177 ret = fork();
3178 if (ret < 0) {
3179 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3180 protocol_unbind_all();
3181 exit(1); /* there has been an error */
3182 }
3183 else if (ret == 0) { /* child breaks here */
Willy Tarreau3c032f22021-07-21 10:17:02 +02003184 /* This one must not be exported, it's internal! */
3185 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003186 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003187 }
3188 else { /* parent here */
3189 in_parent = 1;
3190
William Lallemand944e6192018-11-21 15:48:31 +01003191 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3192 char pidstr[100];
3193 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003194 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003195 }
3196 if (global.mode & MODE_MWORKER) {
3197 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003198
William Lallemand5d71a6b2021-11-09 15:25:31 +01003199 ha_notice("New worker (%d) forked\n", ret);
William Lallemand944e6192018-11-21 15:48:31 +01003200 /* find the right mworker_proc */
3201 list_for_each_entry(child, &proc_list, list) {
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003202 if (child->reloads == 0 && child->options & PROC_O_TYPE_WORKER) {
William Lallemand944e6192018-11-21 15:48:31 +01003203 child->timestamp = now.tv_sec;
3204 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003205 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003206 break;
3207 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003208 }
3209 }
William Lallemand944e6192018-11-21 15:48:31 +01003210 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003211
William Lallemand944e6192018-11-21 15:48:31 +01003212 } else {
3213 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003214 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003215 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003216
3217#ifdef USE_CPU_AFFINITY
Willy Tarreau44ea6312021-06-15 08:57:56 +02003218 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 +02003219
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003220#ifdef __FreeBSD__
Willy Tarreau44ea6312021-06-15 08:57:56 +02003221 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003222 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
David Carlier2d0493a2020-12-02 21:14:51 +00003223#elif defined(__linux__) || defined(__DragonFly__)
Willy Tarreau44ea6312021-06-15 08:57:56 +02003224 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003225 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003226#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003227 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003228#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003229 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003230 if (pidfd >= 0) {
3231 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3232 close(pidfd);
3233 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003234
3235 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003236 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003237
Willy Tarreaud67ff342021-06-15 07:58:09 +02003238 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003239 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
William Lallemandfab0fdc2021-11-09 18:01:22 +01003240 master = 1;
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003241
3242 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3243 (global.mode & MODE_DAEMON)) {
3244 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003245 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3246 stdio_quiet(-1);
3247
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003248 global.mode &= ~MODE_VERBOSE;
3249 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003250 }
3251
William Lallemandfab0fdc2021-11-09 18:01:22 +01003252 if (global.mode & MODE_MWORKER_WAIT) {
3253 /* only the wait mode handles the master CLI */
3254 mworker_loop();
3255 } else {
3256
3257 /* if not in wait mode, reload in wait mode to free the memory */
William Lallemand836bda22021-11-09 18:16:47 +01003258 ha_notice("Loading success.\n");
William Lallemand68836742021-11-10 10:49:06 +01003259 proc_self->failedreloads = 0; /* reset the number of failure */
William Lallemandfab0fdc2021-11-09 18:01:22 +01003260 mworker_reexec_waitmode();
3261 }
William Lallemand1499b9b2017-06-07 15:04:47 +02003262 /* should never get there */
3263 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003264 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003265#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003266 ssl_free_dh();
3267#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003268 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003269 }
3270
William Lallemandcb11fd22017-06-01 17:38:52 +02003271 /* child must never use the atexit function */
3272 atexit_flag = 0;
3273
William Lallemandbc193052018-09-11 10:06:26 +02003274 /* close useless master sockets */
3275 if (global.mode & MODE_MWORKER) {
3276 struct mworker_proc *child, *it;
3277 master = 0;
3278
William Lallemand309dc9a2018-10-26 14:47:45 +02003279 mworker_cli_proxy_stop();
3280
William Lallemandbc193052018-09-11 10:06:26 +02003281 /* free proc struct of other processes */
3282 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003283 /* close the FD of the master side for all
3284 * workers, we don't need to close the worker
3285 * side of other workers since it's done with
3286 * the bind_proc */
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003287 if (child->ipc_fd[0] >= 0)
3288 close(child->ipc_fd[0]);
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003289 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandce83b4a2018-10-26 14:47:30 +02003290 child->reloads == 0) {
3291 /* keep this struct if this is our pid */
3292 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003293 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003294 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003295 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003296 mworker_free_child(child);
3297 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003298 }
3299 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003300
William Lallemande1340412017-12-28 16:09:36 +01003301 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3302 devnullfd = open("/dev/null", O_RDWR, 0);
3303 if (devnullfd < 0) {
3304 ha_alert("Cannot open /dev/null\n");
3305 exit(EXIT_FAILURE);
3306 }
3307 }
3308
William Lallemand095ba4c2017-06-01 17:38:50 +02003309 /* Must chroot and setgid/setuid in the children */
3310 /* chroot if needed */
3311 if (global.chroot != NULL) {
3312 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003313 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003314 if (nb_oldpids)
3315 tell_old_pids(SIGTTIN);
3316 protocol_unbind_all();
3317 exit(1);
3318 }
3319 }
3320
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003321 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003322 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003323
William Lallemand7f80eb22017-05-26 18:19:55 +02003324 /* pass through every cli socket, and check if it's bound to
3325 * the current process and if it exposes listeners sockets.
3326 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3327 * */
3328
Willy Tarreau4975d142021-03-13 11:00:33 +01003329 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003330 struct bind_conf *bind_conf;
3331
Willy Tarreau4975d142021-03-13 11:00:33 +01003332 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003333 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003334 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3335 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003336 }
3337 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003338 }
3339
William Lallemand2e8fad92018-11-13 16:18:23 +01003340 /*
3341 * This is only done in daemon mode because we might want the
3342 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3343 * we should now close the 3 first FDs to ensure that we can
3344 * detach from the TTY. We MUST NOT do it in other cases since
3345 * it would have already be done, and 0-2 would have been
3346 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003348 if ((global.mode & MODE_DAEMON) &&
3349 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003351 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003352 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003353 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3354 }
3355 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003356 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3357 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003358 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 }
3360
William Dauchye039f262019-11-17 15:47:15 +01003361 /* try our best to re-enable core dumps depending on system capabilities.
3362 * What is addressed here :
3363 * - remove file size limits
3364 * - remove core size limits
3365 * - mark the process dumpable again if it lost it due to user/group
3366 */
3367 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3368 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3369
3370#if defined(RLIMIT_FSIZE)
3371 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3372 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3373 ha_alert("[%s.main()] Failed to set the raise the maximum "
3374 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003375 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003376 }
3377 else
3378 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003379 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003380 }
3381#endif
3382
3383#if defined(RLIMIT_CORE)
3384 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3385 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3386 ha_alert("[%s.main()] Failed to set the raise the core "
3387 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003388 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003389 }
3390 else
3391 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003392 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003393 }
3394#endif
3395
3396#if defined(USE_PRCTL)
3397 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3398 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3399 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003400#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003401 {
3402 int traceable = PROC_TRACE_CTL_ENABLE;
3403 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3404 ha_warning("[%s.main()] Failed to set the traceable flag, "
3405 "no core will be dumped.\n", argv[0]);
3406 }
William Dauchye039f262019-11-17 15:47:15 +01003407#endif
3408 }
3409
Christopher Faulete3a5e352017-10-24 13:53:54 +02003410 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003411 reset_usermsgs_ctx();
3412
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003413 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003414 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003415
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003416 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003417 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003418
3419 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003420 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003421
3422 /* wait for all threads to terminate */
3423 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003424
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003425 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003426}
3427
Willy Tarreaubaaee002006-06-26 02:48:02 +02003428/*
3429 * Local variables:
3430 * c-indent-level: 8
3431 * c-basic-offset: 8
3432 * End:
3433 */