blob: ba91d34fe1707f33d0cabebdddbcd35e847ebe9a [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 Tarreau654726d2021-12-28 15:43:11 +0100600#if defined(HA_HAVE_DUMP_LIBS)
601 " -dL dumps loaded object files after config checks\n"
602#endif
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100603 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100604 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200605 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200606 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200607 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200608 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200609 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100611 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 exit(1);
613}
614
615
616
617/*********************************************************************/
618/* more specific functions ***************************************/
619/*********************************************************************/
620
William Lallemand73b85e72017-06-01 17:38:51 +0200621/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
622 * pids the signal was correctly delivered to.
623 */
William Lallemande25473c2019-04-01 11:29:56 +0200624int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200625{
626 int p;
627 int ret = 0;
628 for (p = 0; p < nb_oldpids; p++)
629 if (kill(oldpids[p], sig) == 0)
630 ret++;
631 return ret;
632}
633
William Lallemand75ea0a02017-11-15 19:02:58 +0100634/*
William Lallemand73b85e72017-06-01 17:38:51 +0200635 * remove a pid forom the olpid array and decrease nb_oldpids
636 * return 1 pid was found otherwise return 0
637 */
638
639int delete_oldpid(int pid)
640{
641 int i;
642
643 for (i = 0; i < nb_oldpids; i++) {
644 if (oldpids[i] == pid) {
645 oldpids[i] = oldpids[nb_oldpids - 1];
646 oldpids[nb_oldpids - 1] = 0;
647 nb_oldpids--;
648 return 1;
649 }
650 }
651 return 0;
652}
653
William Lallemand85b0bd92017-06-01 17:38:53 +0200654
William Lallemand73b85e72017-06-01 17:38:51 +0200655/*
656 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800657 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200658 */
William Lallemandfab0fdc2021-11-09 18:01:22 +0100659static void mworker_reexec()
William Lallemand73b85e72017-06-01 17:38:51 +0200660{
William Lallemand00417412020-06-05 14:08:41 +0200661 char **next_argv = NULL;
662 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200663 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200664 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200665 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100666 struct rlimit limit;
William Lallemand2be557f2021-11-24 18:45:37 +0100667 struct mworker_proc *current_child = NULL;
William Lallemand73b85e72017-06-01 17:38:51 +0200668
669 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100670#if defined(USE_SYSTEMD)
671 if (global.tune.options & GTUNE_USE_SYSTEMD)
672 sd_notify(0, "RELOADING=1");
673#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200674 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
675
William Lallemandbc193052018-09-11 10:06:26 +0200676 mworker_proc_list_to_env(); /* put the children description in the env */
677
William Lallemandc4810b82021-11-18 10:51:30 +0100678 /* ensure that we close correctly every listeners before reexecuting */
679 mworker_cleanlisteners();
680
William Lallemand7c756a82018-11-26 11:53:40 +0100681 /* during the reload we must ensure that every FDs that can't be
682 * reuse (ie those that are not referenced in the proc_list)
683 * are closed or they will leak. */
684
685 /* close the listeners FD */
686 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200687
William Lallemand67e371e2021-11-25 10:03:44 +0100688 if (fdtab)
689 deinit_pollers();
William Lallemandefd95472021-11-26 14:43:57 +0100690
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500691#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200692 /* close random device FDs */
693 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100694#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100695
Willy Tarreau8dca1952019-03-01 10:21:55 +0100696 /* restore the initial FD limits */
697 limit.rlim_cur = rlim_fd_cur_at_boot;
698 limit.rlim_max = rlim_fd_max_at_boot;
699 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
700 getrlimit(RLIMIT_NOFILE, &limit);
701 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
702 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
703 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
704 }
705
William Lallemand73b85e72017-06-01 17:38:51 +0200706 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200707 while (old_argv[old_argc])
708 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200709
William Lallemand85b0bd92017-06-01 17:38:53 +0200710 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200711 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200712 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200713 if (next_argv == NULL)
714 goto alloc_error;
715
William Lallemand00417412020-06-05 14:08:41 +0200716 /* copy the program name */
717 next_argv[next_argc++] = old_argv[0];
718
719 /* insert the new options just after argv[0] in case we have a -- */
720
William Lallemandbefab9e2021-11-25 00:49:19 +0100721 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
722 /* add -sf <PID>* to argv */
723 if (mworker_child_nb() > 0) {
724 struct mworker_proc *child;
William Lallemand3f128872019-04-01 11:29:59 +0200725
William Lallemandbefab9e2021-11-25 00:49:19 +0100726 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200727
William Lallemandbefab9e2021-11-25 00:49:19 +0100728 list_for_each_entry(child, &proc_list, list) {
729 if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
730 current_child = child;
William Lallemand2be557f2021-11-24 18:45:37 +0100731
William Lallemandbefab9e2021-11-25 00:49:19 +0100732 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
733 continue;
734 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
735 goto alloc_error;
736 msg = NULL;
737 }
William Lallemand73b85e72017-06-01 17:38:51 +0200738 }
William Lallemand2be557f2021-11-24 18:45:37 +0100739
740 if (current_child) {
741 /* add the -x option with the socketpair of the current worker */
742 next_argv[next_argc++] = "-x";
743 if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
744 goto alloc_error;
745 msg = NULL;
746 }
William Lallemand85b0bd92017-06-01 17:38:53 +0200747 }
748
William Lallemand00417412020-06-05 14:08:41 +0200749 /* copy the previous options */
750 for (i = 1; i < old_argc; i++)
751 next_argv[next_argc++] = old_argv[i];
752
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200753 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100754 execvp(next_argv[0], next_argv);
Christopher Faulet767a84b2017-11-24 16:50:31 +0100755 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100756 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100757 return;
758
William Lallemand73b85e72017-06-01 17:38:51 +0200759alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100760 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800761 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200762 return;
763}
764
William Lallemandfab0fdc2021-11-09 18:01:22 +0100765/* reexec haproxy in waitmode */
766static void mworker_reexec_waitmode()
767{
768 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
769 mworker_reexec();
770}
771
772/* reload haproxy and emit a warning */
773void mworker_reload()
774{
William Lallemandad221f42021-11-09 18:43:59 +0100775 struct mworker_proc *child;
William Lallemandefd95472021-11-26 14:43:57 +0100776 struct per_thread_deinit_fct *ptdf;
William Lallemandad221f42021-11-09 18:43:59 +0100777
William Lallemand836bda22021-11-09 18:16:47 +0100778 ha_notice("Reloading HAProxy\n");
William Lallemandad221f42021-11-09 18:43:59 +0100779
William Lallemandefd95472021-11-26 14:43:57 +0100780 /* close the poller FD and the thread waker pipe FD */
781 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
782 ptdf->fct();
783
William Lallemandad221f42021-11-09 18:43:59 +0100784 /* increment the number of reloads */
785 list_for_each_entry(child, &proc_list, list) {
786 child->reloads++;
787 }
788
William Lallemandfab0fdc2021-11-09 18:01:22 +0100789 mworker_reexec();
790}
791
William Lallemandb3f2be32018-09-11 10:06:18 +0200792static void mworker_loop()
793{
794
795#if defined(USE_SYSTEMD)
796 if (global.tune.options & GTUNE_USE_SYSTEMD)
797 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
798#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200799 /* Busy polling makes no sense in the master :-) */
800 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200801
William Lallemandbc193052018-09-11 10:06:26 +0200802
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100803 signal_unregister(SIGTTIN);
804 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100805 signal_unregister(SIGUSR1);
806 signal_unregister(SIGHUP);
807 signal_unregister(SIGQUIT);
808
William Lallemandb3f2be32018-09-11 10:06:18 +0200809 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
810 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100811 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
812 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200813 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
814 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
815 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
816 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
817
818 mworker_unblock_signals();
William Lallemand27f3fa52018-12-06 14:05:20 +0100819 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200820
William Lallemandbc193052018-09-11 10:06:26 +0200821 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
822 some SIGCHLD were lost */
823
William Lallemandb3f2be32018-09-11 10:06:18 +0200824 global.nbthread = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200825
William Lallemand2672eb92018-12-14 15:52:39 +0100826#ifdef USE_THREAD
827 tid_bit = 1;
828 all_threads_mask = 1;
829#endif
830
William Lallemandb3f2be32018-09-11 10:06:18 +0200831 jobs++; /* this is the "master" job, we want to take care of the
832 signals even if there is no listener so the poll loop don't
833 leave */
834
835 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200836 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200837}
William Lallemandcb11fd22017-06-01 17:38:52 +0200838
839/*
840 * Reexec the process in failure mode, instead of exiting
841 */
842void reexec_on_failure()
843{
William Lallemand68836742021-11-10 10:49:06 +0100844 struct mworker_proc *child;
845
William Lallemandcb11fd22017-06-01 17:38:52 +0200846 if (!atexit_flag)
847 return;
William Lallemand68836742021-11-10 10:49:06 +0100848
849 /* get the info of the children in the env */
850 if (mworker_env_to_proc_list() < 0) {
851 exit(EXIT_FAILURE);
852 }
853
854 /* increment the number of failed reloads */
855 list_for_each_entry(child, &proc_list, list) {
856 child->failedreloads++;
857 }
858
William Lallemandfab0fdc2021-11-09 18:01:22 +0100859 usermsgs_clr(NULL);
William Lallemand836bda22021-11-09 18:16:47 +0100860 ha_warning("Loading failure!\n");
William Lallemandfab0fdc2021-11-09 18:01:22 +0100861 mworker_reexec_waitmode();
William Lallemandcb11fd22017-06-01 17:38:52 +0200862}
William Lallemand73b85e72017-06-01 17:38:51 +0200863
864
865/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200866 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
867 * a signal zero to all subscribers. This means that it's as easy as
868 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200869 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100870static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200871{
872 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200873 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100874 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200875}
876
877/*
878 * upon SIGTTOU, we pause everything
879 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100880static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200881{
Willy Tarreau775e0012020-09-24 16:36:26 +0200882 if (protocol_pause_all() & ERR_FATAL) {
883 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200884 ha_warning("%s", msg);
885 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200886 soft_stop();
887 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100888 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200889}
890
891/*
892 * upon SIGTTIN, let's have a soft stop.
893 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100894static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895{
Willy Tarreau775e0012020-09-24 16:36:26 +0200896 if (protocol_resume_all() & ERR_FATAL) {
897 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 +0200898 ha_warning("%s", msg);
899 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200900 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200901}
902
903/*
904 * this function dumps every server's state when the process receives SIGHUP.
905 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100906static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200907{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100908 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200909
Christopher Faulet767a84b2017-11-24 16:50:31 +0100910 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200911 while (p) {
912 struct server *s = p->srv;
913
914 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
915 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100916 chunk_printf(&trash,
917 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
918 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200919 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200920 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200921 ha_warning("%s\n", trash.area);
922 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 s = s->next;
924 }
925
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200926 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
927 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100928 chunk_printf(&trash,
929 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
930 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200931 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 +0200932 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100933 chunk_printf(&trash,
934 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
935 p->id,
936 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200937 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 +0200938 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100939 chunk_printf(&trash,
940 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
941 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
942 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200943 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 +0200944 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200945 ha_warning("%s\n", trash.area);
946 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947
948 p = p->next;
949 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950}
951
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100952static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200953{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200954 /* dump memory usage then free everything possible */
955 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100956 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957}
958
William Lallemande1340412017-12-28 16:09:36 +0100959/*
960 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
961 * If <fd> < 0, it opens /dev/null and use it to dup
962 *
963 * In the case of chrooting, you have to open /dev/null before the chroot, and
964 * pass the <fd> to this function
965 */
966static void stdio_quiet(int fd)
967{
968 if (fd < 0)
969 fd = open("/dev/null", O_RDWR, 0);
970
971 if (fd > -1) {
972 fclose(stdin);
973 fclose(stdout);
974 fclose(stderr);
975
976 dup2(fd, 0);
977 dup2(fd, 1);
978 dup2(fd, 2);
979 if (fd > 2)
980 close(fd);
981 return;
982 }
983
984 ha_alert("Cannot open /dev/null\n");
985 exit(EXIT_FAILURE);
986}
987
988
Joseph Herlant03420902018-11-15 10:41:50 -0800989/* This function checks if cfg_cfgfiles contains directories.
990 * If it finds one, it adds all the files (and only files) it contains
991 * in cfg_cfgfiles in place of the directory (and removes the directory).
992 * It adds the files in lexical order.
993 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200994 * It doesn't add files with name starting with '.'
995 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100996static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200997{
998 struct wordlist *wl, *wlb;
999 char *err = NULL;
1000
1001 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1002 struct stat file_stat;
1003 struct dirent **dir_entries = NULL;
1004 int dir_entries_nb;
1005 int dir_entries_it;
1006
1007 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001008 ha_alert("Cannot open configuration file/directory %s : %s\n",
1009 wl->s,
1010 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001011 exit(1);
1012 }
1013
1014 if (!S_ISDIR(file_stat.st_mode))
1015 continue;
1016
1017 /* from this point wl->s is a directory */
1018
1019 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1020 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001021 ha_alert("Cannot open configuration directory %s : %s\n",
1022 wl->s,
1023 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001024 exit(1);
1025 }
1026
1027 /* for each element in the directory wl->s */
1028 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1029 struct dirent *dir_entry = dir_entries[dir_entries_it];
1030 char *filename = NULL;
1031 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1032
1033 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001034 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001035 */
1036 if (dir_entry->d_name[0] == '.' ||
1037 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1038 goto next_dir_entry;
1039
1040 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001041 ha_alert("Cannot load configuration files %s : out of memory.\n",
1042 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001043 exit(1);
1044 }
1045
1046 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001047 ha_alert("Cannot open configuration file %s : %s\n",
1048 wl->s,
1049 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001050 exit(1);
1051 }
1052
1053 /* don't add anything else than regular file in cfg_cfgfiles
1054 * this way we avoid loops
1055 */
1056 if (!S_ISREG(file_stat.st_mode))
1057 goto next_dir_entry;
1058
1059 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001060 ha_alert("Cannot load configuration files %s : %s\n",
1061 filename,
1062 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001063 exit(1);
1064 }
1065
1066next_dir_entry:
1067 free(filename);
1068 free(dir_entry);
1069 }
1070
1071 free(dir_entries);
1072
1073 /* remove the current directory (wl) from cfg_cfgfiles */
1074 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001075 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001076 free(wl);
1077 }
1078
1079 free(err);
1080}
1081
Willy Tarreaubaaee002006-06-26 02:48:02 +02001082/*
William Lallemand73b85e72017-06-01 17:38:51 +02001083 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001084 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001085 * Return an allocated copy of argv
1086 */
1087
1088static char **copy_argv(int argc, char **argv)
1089{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001090 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001091
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001092 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001093 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001094 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001095 return NULL;
1096 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001097 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001098
William Lallemanddf6c5a82020-06-04 17:40:23 +02001099 /* first copy argv[0] */
1100 *newargv++ = *argv++;
1101 argc--;
1102
1103 while (argc > 0) {
1104 if (**argv != '-') {
1105 /* non options are copied but will fail in the argument parser */
1106 *newargv++ = *argv++;
1107 argc--;
1108
1109 } else {
1110 char *flag;
1111
1112 flag = *argv + 1;
1113
1114 if (flag[0] == '-' && flag[1] == 0) {
1115 /* "--\0" copy every arguments till the end of argv */
1116 *newargv++ = *argv++;
1117 argc--;
1118
1119 while (argc > 0) {
1120 *newargv++ = *argv++;
1121 argc--;
1122 }
1123 } else {
1124 switch (*flag) {
1125 case 's':
1126 /* -sf / -st and their parameters are ignored */
1127 if (flag[1] == 'f' || flag[1] == 't') {
1128 argc--;
1129 argv++;
1130 /* The list can't contain a negative value since the only
1131 way to know the end of this list is by looking for the
1132 next option or the end of the options */
1133 while (argc > 0 && argv[0][0] != '-') {
1134 argc--;
1135 argv++;
1136 }
William Lallemand398da622020-09-02 16:12:23 +02001137 } else {
1138 argc--;
1139 argv++;
1140
William Lallemanddf6c5a82020-06-04 17:40:23 +02001141 }
1142 break;
1143
1144 case 'x':
1145 /* this option and its parameter are ignored */
1146 argc--;
1147 argv++;
1148 if (argc > 0) {
1149 argc--;
1150 argv++;
1151 }
1152 break;
1153
1154 case 'C':
1155 case 'n':
1156 case 'm':
1157 case 'N':
1158 case 'L':
1159 case 'f':
1160 case 'p':
1161 case 'S':
1162 /* these options have only 1 parameter which must be copied and can start with a '-' */
1163 *newargv++ = *argv++;
1164 argc--;
1165 if (argc == 0)
1166 goto error;
1167 *newargv++ = *argv++;
1168 argc--;
1169 break;
1170 default:
1171 /* for other options just copy them without parameters, this is also done
1172 * for options like "--foo", but this will fail in the argument parser.
1173 * */
1174 *newargv++ = *argv++;
1175 argc--;
1176 break;
1177 }
William Lallemand73b85e72017-06-01 17:38:51 +02001178 }
1179 }
William Lallemand73b85e72017-06-01 17:38:51 +02001180 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001181
William Lallemanddf6c5a82020-06-04 17:40:23 +02001182 return retargv;
1183
1184error:
1185 free(retargv);
1186 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001187}
1188
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001189
1190/* Performs basic random seed initialization. The main issue with this is that
1191 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1192 * which means that there will only be 4 billion possible random sequences once
1193 * srandom() is called, regardless of the internal state. Not calling it is
1194 * even worse as we'll always produce the same randoms sequences. What we do
1195 * here is to create an initial sequence from various entropy sources, hash it
1196 * using SHA1 and keep the resulting 160 bits available globally.
1197 *
1198 * We initialize the current process with the first 32 bits before starting the
1199 * polling loop, where all this will be changed to have process specific and
1200 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001201 *
1202 * Before starting threads, it's still possible to call random() as srandom()
1203 * is initialized from this, but after threads and/or processes are started,
1204 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001205 */
1206static void ha_random_boot(char *const *argv)
1207{
1208 unsigned char message[256];
1209 unsigned char *m = message;
1210 struct timeval tv;
1211 blk_SHA_CTX ctx;
1212 unsigned long l;
1213 int fd;
1214 int i;
1215
1216 /* start with current time as pseudo-random seed */
1217 gettimeofday(&tv, NULL);
1218 write_u32(m, tv.tv_sec); m += 4;
1219 write_u32(m, tv.tv_usec); m += 4;
1220
1221 /* PID and PPID add some OS-based randomness */
1222 write_u16(m, getpid()); m += 2;
1223 write_u16(m, getppid()); m += 2;
1224
1225 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1226 fd = open("/dev/urandom", O_RDONLY);
1227 if (fd >= 0) {
1228 i = read(fd, m, 20);
1229 if (i > 0)
1230 m += i;
1231 close(fd);
1232 }
1233
1234 /* take up to 160 bits bytes from openssl (non-blocking) */
1235#ifdef USE_OPENSSL
1236 if (RAND_bytes(m, 20) == 1)
1237 m += 20;
1238#endif
1239
1240 /* take 160 bits from existing random in case it was already initialized */
1241 for (i = 0; i < 5; i++) {
1242 write_u32(m, random());
1243 m += 4;
1244 }
1245
1246 /* stack address (benefit form operating system's ASLR) */
1247 l = (unsigned long)&m;
1248 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1249
1250 /* argv address (benefit form operating system's ASLR) */
1251 l = (unsigned long)&argv;
1252 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1253
1254 /* use tv_usec again after all the operations above */
1255 gettimeofday(&tv, NULL);
1256 write_u32(m, tv.tv_usec); m += 4;
1257
1258 /*
1259 * At this point, ~84-92 bytes have been used
1260 */
1261
1262 /* finish with the hostname */
1263 strncpy((char *)m, hostname, message + sizeof(message) - m);
1264 m += strlen(hostname);
1265
1266 /* total message length */
1267 l = m - message;
1268
1269 memset(&ctx, 0, sizeof(ctx));
1270 blk_SHA1_Init(&ctx);
1271 blk_SHA1_Update(&ctx, message, l);
1272 blk_SHA1_Final(boot_seed, &ctx);
1273
1274 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001275 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001276}
1277
Willy Tarreau5a023f02019-03-01 14:19:31 +01001278/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1279 * setting, and returns it. It may return -1 meaning "unlimited" if some
1280 * unlimited proxies have been found and the global.maxconn value is not yet
1281 * set. It may also return a value greater than maxconn if it's not yet set.
1282 * Note that a value of zero means there is no need for pipes. -1 is never
1283 * returned if global.maxconn is valid.
1284 */
1285static int compute_ideal_maxpipes()
1286{
1287 struct proxy *cur;
1288 int nbfe = 0, nbbe = 0;
1289 int unlimited = 0;
1290 int pipes;
1291 int max;
1292
1293 for (cur = proxies_list; cur; cur = cur->next) {
1294 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1295 if (cur->cap & PR_CAP_FE) {
1296 max = cur->maxconn;
1297 nbfe += max;
1298 if (!max) {
1299 unlimited = 1;
1300 break;
1301 }
1302 }
1303 if (cur->cap & PR_CAP_BE) {
1304 max = cur->fullconn ? cur->fullconn : global.maxconn;
1305 nbbe += max;
1306 if (!max) {
1307 unlimited = 1;
1308 break;
1309 }
1310 }
1311 }
1312 }
1313
1314 pipes = MAX(nbfe, nbbe);
1315 if (global.maxconn) {
1316 if (pipes > global.maxconn || unlimited)
1317 pipes = global.maxconn;
1318 } else if (unlimited) {
1319 pipes = -1;
1320 }
1321
1322 return pipes >= 4 ? pipes / 4 : pipes;
1323}
1324
Willy Tarreauac350932019-03-01 15:43:14 +01001325/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1326 * rlimits and computes an ideal maxconn. It's meant to be called only when
1327 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001328 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1329 * default 100) is returned as it is expected that it will even run on tight
1330 * environments, and will maintain compatibility with previous packages that
1331 * used to rely on this value as the default one. The system will emit a
1332 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001333 */
1334static int compute_ideal_maxconn()
1335{
1336 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1337 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1338 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001339 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001340 int maxconn;
1341
1342 /* we have to take into account these elements :
1343 * - number of engine_fds, which inflates the number of FD needed per
1344 * connection by this number.
1345 * - number of pipes per connection on average : for the unlimited
1346 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1347 * fixed value of 2*pipes.
1348 * - two FDs per connection
1349 */
1350
1351 /* subtract listeners and checks */
1352 remain -= global.maxsock;
1353
Willy Tarreau3f200852019-03-14 19:13:17 +01001354 /* one epoll_fd/kqueue_fd per thread */
1355 remain -= global.nbthread;
1356
1357 /* one wake-up pipe (2 fd) per thread */
1358 remain -= 2 * global.nbthread;
1359
Willy Tarreauac350932019-03-01 15:43:14 +01001360 /* Fixed pipes values : we only subtract them if they're not larger
1361 * than the remaining FDs because pipes are optional.
1362 */
1363 if (pipes >= 0 && pipes * 2 < remain)
1364 remain -= pipes * 2;
1365
1366 if (pipes < 0) {
1367 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1368 * = maxconn * (2 + 0.5 + engine_fds)
1369 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1370 */
1371 maxconn = 2 * remain / (5 + 2 * engine_fds);
1372 } else {
1373 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1374 * = maxconn * (2 + engine_fds)
1375 */
1376 maxconn = remain / (2 + engine_fds);
1377 }
1378
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001379 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001380}
1381
Willy Tarreaua409f302020-03-10 17:08:53 +01001382/* computes the estimated maxsock value for the given maxconn based on the
1383 * possibly set global.maxpipes and existing partial global.maxsock. It may
1384 * temporarily change global.maxconn for the time needed to propagate the
1385 * computations, and will reset it.
1386 */
1387static int compute_ideal_maxsock(int maxconn)
1388{
1389 int maxpipes = global.maxpipes;
1390 int maxsock = global.maxsock;
1391
1392
1393 if (!maxpipes) {
1394 int old_maxconn = global.maxconn;
1395
1396 global.maxconn = maxconn;
1397 maxpipes = compute_ideal_maxpipes();
1398 global.maxconn = old_maxconn;
1399 }
1400
1401 maxsock += maxconn * 2; /* each connection needs two sockets */
1402 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1403 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1404 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1405
1406 /* compute fd used by async engines */
1407 if (global.ssl_used_async_engines) {
1408 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1409
1410 maxsock += maxconn * sides * global.ssl_used_async_engines;
1411 }
1412 return maxsock;
1413}
1414
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001415/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001416 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1417 * value is accepted, non-zero otherwise. This is used to determine if an
1418 * automatic limit may be applied or not. When it is not, the caller knows that
1419 * the highest we can do is the rlim_max at boot. In case of error, we return
1420 * that the setting is possible, so that we defer the error processing to the
1421 * final stage in charge of enforcing this.
1422 */
1423static int check_if_maxsock_permitted(int maxsock)
1424{
1425 struct rlimit orig_limit, test_limit;
1426 int ret;
1427
1428 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1429 return 1;
1430
1431 /* don't go further if we can't even set to what we have */
1432 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1433 return 1;
1434
1435 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1436 test_limit.rlim_cur = test_limit.rlim_max;
1437 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1438
1439 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1440 return 1;
1441
1442 return ret == 0;
1443}
1444
Amaury Denoyelle484454d2021-05-05 16:18:45 +02001445void mark_tainted(const enum tainted_flags flag)
1446{
1447 HA_ATOMIC_OR(&tainted, flag);
1448}
1449
1450unsigned int get_tainted()
1451{
1452 int tainted_state;
1453 HA_ATOMIC_STORE(&tainted_state, tainted);
1454 return tainted_state;
1455}
Willy Tarreau304e17e2020-03-10 17:54:54 +01001456
William Lallemand73b85e72017-06-01 17:38:51 +02001457/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02001458 * This function initializes all the necessary variables. It only returns
1459 * if everything is OK. If something fails, it exits.
1460 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001461static void init(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462{
Willy Tarreaubaaee002006-06-26 02:48:02 +02001463 int arg_mode = 0; /* MODE_DEBUG, ... */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001464 char *tmp;
1465 char *cfg_pidfile = NULL;
Willy Tarreau058e9072009-07-20 09:30:05 +02001466 int err_code = 0;
Maxime de Roucy0f503922016-05-13 23:52:55 +02001467 char *err_msg = NULL;
Willy Tarreau477ecd82010-01-03 21:12:30 +01001468 struct wordlist *wl;
Kevinm48936af2010-12-22 16:08:21 +00001469 char *progname;
Willy Tarreau576132e2011-09-10 19:26:56 +02001470 char *change_dir = NULL;
Christopher Fauletd7c91962015-04-30 11:48:27 +02001471 struct proxy *px;
Willy Tarreaue6945732016-12-21 19:57:00 +01001472 struct post_check_fct *pcf;
Willy Tarreauac350932019-03-01 15:43:14 +01001473 int ideal_maxconn;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001474 char *check_condition = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001475
Christopher Faulete3a5e352017-10-24 13:53:54 +02001476 global.mode = MODE_STARTING;
William Lallemand00417412020-06-05 14:08:41 +02001477 old_argv = copy_argv(argc, argv);
1478 if (!old_argv) {
William Lallemanddf6c5a82020-06-04 17:40:23 +02001479 ha_alert("failed to copy argv.\n");
1480 exit(1);
1481 }
William Lallemand73b85e72017-06-01 17:38:51 +02001482
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001483 if (!init_trash_buffers(1)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001484 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet748919a2017-07-26 14:59:46 +02001485 exit(1);
1486 }
David du Colombier7af46052012-05-16 14:16:48 +02001487
Emeric Brun2b920a12010-09-23 18:30:22 +02001488 /* NB: POSIX does not make it mandatory for gethostname() to NULL-terminate
1489 * the string in case of truncation, and at least FreeBSD appears not to do
1490 * it.
1491 */
1492 memset(hostname, 0, sizeof(hostname));
1493 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001494
1495 if ((localpeer = strdup(hostname)) == NULL) {
1496 ha_alert("Cannot allocate memory for local peer.\n");
1497 exit(EXIT_FAILURE);
1498 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001499 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Emeric Brun2b920a12010-09-23 18:30:22 +02001500
William Lallemand24c928c2020-01-14 17:58:18 +01001501 /* we were in mworker mode, we should restart in mworker mode */
1502 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1503 global.mode |= MODE_MWORKER;
1504
Willy Tarreaubaaee002006-06-26 02:48:02 +02001505 /*
1506 * Initialize the previously static variables.
1507 */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001508
Willy Tarreau173d9952018-01-26 21:48:23 +01001509 totalconn = actconn = listeners = stopping = 0;
Cyril Bonté203ec5a2017-03-23 22:44:13 +01001510 killed = 0;
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001511
Willy Tarreaubaaee002006-06-26 02:48:02 +02001512
1513#ifdef HAPROXY_MEMMAX
Willy Tarreau70060452015-12-14 12:46:07 +01001514 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001515#endif
1516
Benoit GARNIERb413c2a2016-03-27 11:08:03 +02001517 tzset();
Willy Tarreau55542642021-10-08 09:33:24 +02001518 clock_init_process_date();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001519 start_date = now;
1520
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001521 ha_random_boot(argv);
Willy Tarreau84310e22014-02-14 11:59:04 +01001522
Willy Tarreau8ed669b2013-01-11 15:49:37 +01001523 if (init_acl() != 0)
1524 exit(1);
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001525
Amaury Denoyellec593bcd2021-05-19 15:35:29 +02001526#ifdef USE_OPENSSL
1527 /* Initialize the random generator.
1528 * Must be called before chroot for access to /dev/urandom
1529 */
1530 if (!ssl_initialize_random()) {
1531 ha_alert("OpenSSL random data generator initialization failed.\n");
1532 exit(1);
1533 }
1534#endif
1535
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001536 /* Initialise lua. */
1537 hlua_init();
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001538
Christopher Fauletff2613e2016-11-09 11:36:17 +01001539 /* Initialize process vars */
Willy Tarreaub7bfcb32021-08-31 08:13:25 +02001540 vars_init_head(&proc_vars, SCOPE_PROC);
Christopher Fauletff2613e2016-11-09 11:36:17 +01001541
Willy Tarreau43b78992009-01-25 15:42:27 +01001542 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001543#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001544 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001545#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001546#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001547 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001548#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001549#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001550 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001551#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001552#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001553 global.tune.options |= GTUNE_USE_EVPORTS;
1554#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001555#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001556 global.tune.options |= GTUNE_USE_SPLICE;
1557#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001558#if defined(USE_GETADDRINFO)
1559 global.tune.options |= GTUNE_USE_GAI;
1560#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001561#if defined(SO_REUSEPORT)
1562 global.tune.options |= GTUNE_USE_REUSEPORT;
1563#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001564#ifdef USE_THREAD
1565 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1566#endif
William Dauchya5194602020-03-28 19:29:58 +01001567 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568
1569 pid = getpid();
1570 progname = *argv;
1571 while ((tmp = strchr(progname, '/')) != NULL)
1572 progname = tmp + 1;
1573
Kevinm48936af2010-12-22 16:08:21 +00001574 /* the process name is used for the logs only */
Eric Salama7cea6062020-10-02 11:58:19 +02001575 chunk_initlen(&global.log_tag, strdup(progname), strlen(progname), strlen(progname));
1576 if (b_orig(&global.log_tag) == NULL) {
1577 chunk_destroy(&global.log_tag);
1578 ha_alert("Cannot allocate memory for log_tag.\n");
1579 exit(EXIT_FAILURE);
1580 }
Kevinm48936af2010-12-22 16:08:21 +00001581
Willy Tarreaubaaee002006-06-26 02:48:02 +02001582 argc--; argv++;
1583 while (argc > 0) {
1584 char *flag;
1585
1586 if (**argv == '-') {
1587 flag = *argv+1;
1588
1589 /* 1 arg */
1590 if (*flag == 'v') {
1591 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001592 if (flag[1] == 'v') /* -vv */
1593 display_build_opts();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594 exit(0);
1595 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001596#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001598 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001599#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001600#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001602 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001604#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001605 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001606 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001607#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001608#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001609 else if (*flag == 'd' && flag[1] == 'v')
1610 global.tune.options &= ~GTUNE_USE_EVPORTS;
1611#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001612#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001613 else if (*flag == 'd' && flag[1] == 'S')
1614 global.tune.options &= ~GTUNE_USE_SPLICE;
1615#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001616#if defined(USE_GETADDRINFO)
1617 else if (*flag == 'd' && flag[1] == 'G')
1618 global.tune.options &= ~GTUNE_USE_GAI;
1619#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001620#if defined(SO_REUSEPORT)
1621 else if (*flag == 'd' && flag[1] == 'R')
1622 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1623#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001624 else if (*flag == 'd' && flag[1] == 'V')
1625 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001626 else if (*flag == 'V')
1627 arg_mode |= MODE_VERBOSE;
1628 else if (*flag == 'd' && flag[1] == 'b')
1629 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001630 else if (*flag == 'd' && flag[1] == 'D')
1631 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001632 else if (*flag == 'd' && flag[1] == 'W')
1633 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreau6e064432012-05-08 15:40:42 +02001634 else if (*flag == 'd' && flag[1] == 'M')
1635 mem_poison_byte = flag[2] ? strtol(flag + 2, NULL, 0) : 'P';
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001636 else if (*flag == 'd' && flag[1] == 'r')
1637 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreau654726d2021-12-28 15:43:11 +01001638#if defined(HA_HAVE_DUMP_LIBS)
1639 else if (*flag == 'd' && flag[1] == 'L')
1640 arg_mode |= MODE_DUMP_LIBS;
1641#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001642 else if (*flag == 'd')
1643 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001644 else if (*flag == 'c' && flag[1] == 'c') {
1645 arg_mode |= MODE_CHECK_CONDITION;
1646 argv++;
1647 argc--;
1648 check_condition = *argv;
1649 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001650 else if (*flag == 'c')
1651 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001652 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001653 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001654 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001655 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001656#if defined(USE_SYSTEMD)
1657 global.tune.options |= GTUNE_USE_SYSTEMD;
1658#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001659 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 +01001660 usage(progname);
1661#endif
1662 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001663 else if (*flag == 'W')
1664 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001665 else if (*flag == 'q')
1666 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001667 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001668 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001669 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001670 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001671 }
William Lallemand4fc09692017-06-19 16:37:19 +02001672 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001673 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001674 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001675
Olivier Houchardf73629d2017-04-05 22:33:04 +02001676 argv++;
1677 argc--;
1678 }
William Lallemande7361152018-10-26 14:47:36 +02001679 else if (*flag == 'S') {
1680 struct wordlist *c;
1681
William Lallemanda6b32492020-06-04 23:49:20 +02001682 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001683 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1684 usage(progname);
1685 }
1686 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1687 ha_alert("Cannot allocate memory\n");
1688 exit(EXIT_FAILURE);
1689 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001690 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001691
1692 argv++;
1693 argc--;
1694 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001695 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1696 /* list of pids to finish ('f') or terminate ('t') */
1697
1698 if (flag[1] == 'f')
1699 oldpids_sig = SIGUSR1; /* finish then exit */
1700 else
1701 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001702 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001703 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001704 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1705 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001706 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001707 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001708 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001709 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001710 errno = 0;
1711 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1712 if (errno) {
1713 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1714 flag,
1715 *argv, strerror(errno));
1716 exit(1);
1717 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001718 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001719 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001720 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1721 flag, endptr);
1722 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001723 }
Chris Lane236062f2018-02-05 23:15:44 +00001724 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001725 if (oldpids[nb_oldpids] <= 0)
1726 usage(progname);
1727 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 }
1729 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001730 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1731 /* now that's a cfgfile list */
1732 argv++; argc--;
1733 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001734 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001735 ha_alert("Cannot load configuration file/directory %s : %s\n",
1736 *argv,
1737 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001738 exit(1);
1739 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001740 argv++; argc--;
1741 }
1742 break;
1743 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001744 else { /* >=2 args */
1745 argv++; argc--;
1746 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001747 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001748
1749 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001750 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001751 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001752 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001753 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001754 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001755 free(localpeer);
1756 if ((localpeer = strdup(*argv)) == NULL) {
1757 ha_alert("Cannot allocate memory for local peer.\n");
1758 exit(EXIT_FAILURE);
1759 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001760 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001761 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001762 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001763 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001764 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001765 ha_alert("Cannot load configuration file/directory %s : %s\n",
1766 *argv,
1767 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001768 exit(1);
1769 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001770 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001771 case 'p' : cfg_pidfile = *argv; break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001772 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773 }
1774 }
1775 }
1776 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001777 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 argv++; argc--;
1779 }
1780
Christopher Faulete3a5e352017-10-24 13:53:54 +02001781 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001782 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Willy Tarreau654726d2021-12-28 15:43:11 +01001783 | MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001784
William Lallemand944e6192018-11-21 15:48:31 +01001785 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001786 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001787 global.mode |= MODE_MWORKER_WAIT;
1788 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001789 }
1790
Willy Tarreau26146192021-07-21 10:01:36 +02001791 if ((global.mode & (MODE_MWORKER | MODE_CHECK | MODE_CHECK_CONDITION)) == MODE_MWORKER &&
1792 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001793 atexit_flag = 1;
1794 atexit(reexec_on_failure);
1795 }
1796
Willy Tarreau576132e2011-09-10 19:26:56 +02001797 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001798 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001799 exit(1);
1800 }
1801
Willy Tarreaubaaee002006-06-26 02:48:02 +02001802 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001803
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001804#ifdef USE_CPU_AFFINITY
1805 {
1806 int i;
Willy Tarreau44ea6312021-06-15 08:57:56 +02001807 ha_cpuset_zero(&cpu_map.proc);
1808 ha_cpuset_zero(&cpu_map.proc_t1);
Willy Tarreau26f42a02021-05-14 08:26:38 +02001809 for (i = 0; i < MAX_THREADS; ++i) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02001810 ha_cpuset_zero(&cpu_map.thread[i]);
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001811 }
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001812 }
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001813#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001814
Amaury Denoyelle11124302021-06-04 18:22:08 +02001815 usermsgs_clr("config");
1816
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001817 if (global.mode & MODE_CHECK_CONDITION) {
1818 int result;
1819
1820 uint32_t err;
1821 const char *errptr;
1822 char *errmsg = NULL;
1823
1824 char *args[MAX_LINE_ARGS+1];
1825 int arg = sizeof(args) / sizeof(*args);
1826 size_t outlen = strlen(check_condition) + 1;
Willy Tarreauc8194c32021-07-16 16:38:58 +02001827 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001828
1829 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02001830 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001831 &errptr);
1832
1833 if (err & PARSE_ERR_QUOTE) {
1834 ha_alert("Syntax Error in condition: Unmatched quote.\n");
1835 exit(2);
1836 }
1837
1838 if (err & PARSE_ERR_HEX) {
1839 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
1840 exit(2);
1841 }
1842
1843 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
1844 ha_alert("Error in condition: Line too long.\n");
1845 exit(2);
1846 }
1847
Willy Tarreauc8194c32021-07-16 16:38:58 +02001848 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001849 ha_alert("Error in condition: Too many words.\n");
1850 exit(2);
1851 }
1852
1853 if (err) {
1854 ha_alert("Unhandled error in condition, please report this to the developers.\n");
1855 exit(2);
1856 }
1857
Willy Tarreauc8194c32021-07-16 16:38:58 +02001858 /* remerge all words into a single expression */
1859 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
1860 ;
1861
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001862 result = cfg_eval_condition(args, &errmsg, &errptr);
1863
1864 if (result < 0) {
1865 if (errmsg)
1866 ha_alert("Failed to evaluate condition: %s\n", errmsg);
1867
1868 exit(2);
1869 }
1870
1871 exit(result ? 0 : 1);
1872 }
1873
William Lallemand944e6192018-11-21 15:48:31 +01001874 /* in wait mode, we don't try to read the configuration files */
1875 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001876 char *env_cfgfiles = NULL;
1877 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001878
William Lallemand944e6192018-11-21 15:48:31 +01001879 /* handle cfgfiles that are actually directories */
1880 cfgfiles_expand_directories();
1881
1882 if (LIST_ISEMPTY(&cfg_cfgfiles))
1883 usage(progname);
1884
1885
1886 list_for_each_entry(wl, &cfg_cfgfiles, list) {
1887 int ret;
1888
Christopher Faulet4e366822021-01-12 18:57:38 +01001889 if (env_err == 0) {
1890 if (!memprintf(&env_cfgfiles, "%s%s%s",
1891 (env_cfgfiles ? env_cfgfiles : ""),
1892 (env_cfgfiles ? ";" : ""), wl->s))
1893 env_err = 1;
1894 }
William Lallemand7b302d82019-05-20 11:15:37 +02001895
William Lallemand944e6192018-11-21 15:48:31 +01001896 ret = readcfgfile(wl->s);
1897 if (ret == -1) {
1898 ha_alert("Could not open configuration file %s : %s\n",
1899 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01001900 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001901 exit(1);
1902 }
1903 if (ret & (ERR_ABORT|ERR_FATAL))
1904 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
1905 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01001906 if (err_code & ERR_ABORT) {
1907 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001908 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01001909 }
Willy Tarreauc4382422009-12-06 13:10:44 +01001910 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001911
William Lallemand944e6192018-11-21 15:48:31 +01001912 /* do not try to resolve arguments nor to spot inconsistencies when
1913 * the configuration contains fatal errors caused by files not found
1914 * or failed memory allocations.
1915 */
1916 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1917 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01001918 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001919 exit(1);
1920 }
Christopher Faulet4e366822021-01-12 18:57:38 +01001921 if (env_err) {
1922 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
1923 exit(1);
1924 }
1925 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
1926 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02001927
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02001928 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001929 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01001930 struct mworker_proc *tmproc;
1931
William Lallemand482f9a92019-04-12 16:15:00 +02001932 setenv("HAPROXY_MWORKER", "1", 1);
1933
William Lallemand16dd1b32018-11-19 18:46:18 +01001934 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
1935
William Lallemandf3a86832019-04-01 11:29:58 +02001936 tmproc = calloc(1, sizeof(*tmproc));
William Lallemand16dd1b32018-11-19 18:46:18 +01001937 if (!tmproc) {
1938 ha_alert("Cannot allocate process structures.\n");
1939 exit(EXIT_FAILURE);
1940 }
William Lallemand8f7069a2019-04-12 16:09:23 +02001941 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand68836742021-11-10 10:49:06 +01001942 tmproc->failedreloads = 0;
William Lallemand16dd1b32018-11-19 18:46:18 +01001943 tmproc->reloads = 0;
William Lallemand16dd1b32018-11-19 18:46:18 +01001944 tmproc->pid = pid;
1945 tmproc->timestamp = start_date.tv_sec;
1946 tmproc->ipc_fd[0] = -1;
1947 tmproc->ipc_fd[1] = -1;
1948
1949 proc_self = tmproc;
1950
Willy Tarreau2b718102021-04-21 07:32:39 +02001951 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01001952 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001953
Willy Tarreau6185a032021-06-15 08:02:06 +02001954 tmproc = calloc(1, sizeof(*tmproc));
1955 if (!tmproc) {
1956 ha_alert("Cannot allocate process structures.\n");
1957 exit(EXIT_FAILURE);
1958 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001959
Willy Tarreau6185a032021-06-15 08:02:06 +02001960 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
1961 tmproc->pid = -1;
William Lallemand68836742021-11-10 10:49:06 +01001962 tmproc->failedreloads = 0;
Willy Tarreau6185a032021-06-15 08:02:06 +02001963 tmproc->reloads = 0;
1964 tmproc->timestamp = -1;
Willy Tarreau6185a032021-06-15 08:02:06 +02001965 tmproc->ipc_fd[0] = -1;
1966 tmproc->ipc_fd[1] = -1;
William Lallemandce83b4a2018-10-26 14:47:30 +02001967
Willy Tarreau6185a032021-06-15 08:02:06 +02001968 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
1969 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02001970 }
Willy Tarreau6185a032021-06-15 08:02:06 +02001971
1972 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01001973 }
1974 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
1975 struct wordlist *it, *c;
1976
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02001977 /* get the info of the children in the env */
1978 if (mworker_env_to_proc_list() < 0) {
1979 exit(EXIT_FAILURE);
1980 }
William Lallemande7361152018-10-26 14:47:36 +02001981
William Lallemand550db6d2018-11-06 17:37:12 +01001982 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02001983
William Lallemand550db6d2018-11-06 17:37:12 +01001984 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02001985 ha_alert("Can't create the master's CLI.\n");
1986 exit(EXIT_FAILURE);
1987 }
William Lallemande7361152018-10-26 14:47:36 +02001988
William Lallemand550db6d2018-11-06 17:37:12 +01001989 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
1990
1991 if (mworker_cli_proxy_new_listener(c->s) < 0) {
1992 ha_alert("Can't create the master's CLI.\n");
1993 exit(EXIT_FAILURE);
1994 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001995 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01001996 free(c->s);
1997 free(c);
1998 }
1999 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002000 }
2001
Eric Salama5ba83352021-03-16 15:11:17 +01002002 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
2003 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
2004 }
2005
Christopher Faulet27c8d202021-10-13 09:50:53 +02002006 /* destroy unreferenced defaults proxies */
2007 proxy_destroy_all_unref_defaults();
2008
Willy Tarreaue90904d2021-02-12 14:08:31 +01002009
Willy Tarreaubb925012009-07-23 13:36:36 +02002010 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02002011 for (px = proxies_list; px; px = px->next) {
2012 struct server *srv;
2013 struct post_proxy_check_fct *ppcf;
2014 struct post_server_check_fct *pscf;
2015
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002016 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002017 continue;
2018
Christopher Fauletc1692962019-08-12 09:51:07 +02002019 list_for_each_entry(pscf, &post_server_check_list, list) {
2020 for (srv = px->srv; srv; srv = srv->next)
2021 err_code |= pscf->fct(srv);
2022 }
2023 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2024 err_code |= ppcf->fct(px);
2025 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002026 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002027 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002028 exit(1);
2029 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002030
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002031 err_code |= pattern_finalize_config();
2032 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2033 ha_alert("Failed to finalize pattern config.\n");
2034 exit(1);
2035 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002036
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002037 if (global.rlimit_memmax_all)
2038 global.rlimit_memmax = global.rlimit_memmax_all;
2039
Willy Tarreaue5733232019-05-22 19:24:06 +02002040#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002041 err_code |= netns_init();
2042 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002043 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002044 exit(1);
2045 }
2046#endif
2047
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002048 /* Apply server states */
2049 apply_server_state();
2050
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002051 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002052 srv_compute_all_admin_states(px);
2053
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002054 /* Apply servers' configured address */
2055 err_code |= srv_init_addr();
2056 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002057 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002058 exit(1);
2059 }
2060
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002061 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2062 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2063 exit(1);
2064 }
2065
Willy Tarreau654726d2021-12-28 15:43:11 +01002066#if defined(HA_HAVE_DUMP_LIBS)
2067 if (global.mode & MODE_DUMP_LIBS) {
2068 qfprintf(stdout, "List of loaded object files:\n");
2069 chunk_reset(&trash);
2070 if (dump_libs(&trash, 0))
2071 printf("%s", trash.area);
2072 }
2073#endif
2074
Willy Tarreaubaaee002006-06-26 02:48:02 +02002075 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002076 struct peers *pr;
2077 struct proxy *px;
2078
Willy Tarreaubebd2122020-04-15 16:06:11 +02002079 if (warned & WARN_ANY)
2080 qfprintf(stdout, "Warnings were found.\n");
2081
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002082 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002083 if (pr->peers_fe)
2084 break;
2085
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002086 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002087 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002088 break;
2089
Emeric Brunbc5c8212021-08-13 09:32:50 +02002090 if (!px) {
2091 /* We may only have log-forward section */
2092 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002093 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002094 break;
2095 }
2096
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002097 if (pr || px) {
2098 /* At least one peer or one listener has been found */
2099 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002100 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002101 }
2102 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2103 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002104 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002105
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002106 if (global.mode & MODE_DIAG) {
2107 cfg_run_diagnostics();
2108 }
2109
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002110 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002111 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002112
Willy Tarreaue6945732016-12-21 19:57:00 +01002113 list_for_each_entry(pcf, &post_check_list, list) {
2114 err_code |= pcf->fct();
2115 if (err_code & (ERR_ABORT|ERR_FATAL))
2116 exit(1);
2117 }
2118
Willy Tarreaubaaee002006-06-26 02:48:02 +02002119 if (cfg_maxconn > 0)
2120 global.maxconn = cfg_maxconn;
2121
Willy Tarreau4975d142021-03-13 11:00:33 +01002122 if (global.cli_fe)
2123 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002124
2125 if (cfg_peers) {
2126 /* peers also need to bypass global maxconn */
2127 struct peers *p = cfg_peers;
2128
2129 for (p = cfg_peers; p; p = p->next)
2130 if (p->peers_fe)
2131 global.maxsock += p->peers_fe->maxconn;
2132 }
2133
Willy Tarreaubaaee002006-06-26 02:48:02 +02002134 if (cfg_pidfile) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002135 free(global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002136 global.pidfile = strdup(cfg_pidfile);
2137 }
2138
Willy Tarreaud0256482015-01-15 21:45:22 +01002139 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002140 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2141 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2142 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2143 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002144 *
2145 * If memmax is set, then it depends on which values are set. If
2146 * maxsslconn is set, we use memmax to determine how many cleartext
2147 * connections may be added, and set maxconn to the sum of the two.
2148 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2149 * the remaining amount of memory between memmax and the cleartext
2150 * connections. If neither are set, then it is considered that all
2151 * connections are SSL-capable, and maxconn is computed based on this,
2152 * then maxsslconn accordingly. We need to know if SSL is used on the
2153 * frontends, backends, or both, because when it's used on both sides,
2154 * we need twice the value for maxsslconn, but we only count the
2155 * handshake once since it is not performed on the two sides at the
2156 * same time (frontend-side is terminated before backend-side begins).
2157 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002158 * ssl_handshake_cost during its initialization. In any case, if
2159 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2160 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002161 */
Willy Tarreauac350932019-03-01 15:43:14 +01002162 ideal_maxconn = compute_ideal_maxconn();
2163
Willy Tarreaud0256482015-01-15 21:45:22 +01002164 if (!global.rlimit_memmax) {
2165 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002166 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002167 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2168 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2169 }
2170 }
2171#ifdef USE_OPENSSL
2172 else if (!global.maxconn && !global.maxsslconn &&
2173 (global.ssl_used_frontend || global.ssl_used_backend)) {
2174 /* memmax is set, compute everything automatically. Here we want
2175 * to ensure that all SSL connections will be served. We take
2176 * care of the number of sides where SSL is used, and consider
2177 * the worst case : SSL used on both sides and doing a handshake
2178 * simultaneously. Note that we can't have more than maxconn
2179 * handshakes at a time by definition, so for the worst case of
2180 * two SSL conns per connection, we count a single handshake.
2181 */
2182 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2183 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002184 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002185
2186 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2187 mem -= global.maxzlibmem;
2188 mem = mem * MEM_USABLE_RATIO;
2189
Willy Tarreau304e17e2020-03-10 17:54:54 +01002190 /* Principle: we test once to set maxconn according to the free
2191 * memory. If it results in values the system rejects, we try a
2192 * second time by respecting rlim_fd_max. If it fails again, we
2193 * go back to the initial value and will let the final code
2194 * dealing with rlimit report the error. That's up to 3 attempts.
2195 */
2196 do {
2197 global.maxconn = mem /
2198 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2199 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2200 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002201
Willy Tarreau304e17e2020-03-10 17:54:54 +01002202 if (retried == 1)
2203 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2204 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002205#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002206 if (global.maxconn > SYSTEM_MAXCONN)
2207 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002208#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002209 global.maxsslconn = sides * global.maxconn;
2210
2211 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2212 break;
2213 } while (retried++ < 2);
2214
Willy Tarreaud0256482015-01-15 21:45:22 +01002215 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2216 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2217 global.maxconn, global.maxsslconn);
2218 }
2219 else if (!global.maxsslconn &&
2220 (global.ssl_used_frontend || global.ssl_used_backend)) {
2221 /* memmax and maxconn are known, compute maxsslconn automatically.
2222 * maxsslconn being forced, we don't know how many of it will be
2223 * on each side if both sides are being used. The worst case is
2224 * when all connections use only one SSL instance because
2225 * handshakes may be on two sides at the same time.
2226 */
2227 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2228 int64_t mem = global.rlimit_memmax * 1048576ULL;
2229 int64_t sslmem;
2230
2231 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2232 mem -= global.maxzlibmem;
2233 mem = mem * MEM_USABLE_RATIO;
2234
Willy Tarreau87b09662015-04-03 00:22:06 +02002235 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002236 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2237 global.maxsslconn = round_2dig(global.maxsslconn);
2238
2239 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002240 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2241 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2242 "without SSL is %d, but %d was found and SSL is in use.\n",
2243 global.rlimit_memmax,
2244 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2245 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002246 exit(1);
2247 }
2248
2249 if (global.maxsslconn > sides * global.maxconn)
2250 global.maxsslconn = sides * global.maxconn;
2251
2252 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2253 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2254 }
2255#endif
2256 else if (!global.maxconn) {
2257 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2258 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2259 int64_t mem = global.rlimit_memmax * 1048576ULL;
2260 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002261 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002262
2263 if (global.ssl_used_frontend || global.ssl_used_backend)
2264 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2265
2266 mem -= global.maxzlibmem;
2267 mem = mem * MEM_USABLE_RATIO;
2268
2269 clearmem = mem;
2270 if (sides)
2271 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2272
Willy Tarreau304e17e2020-03-10 17:54:54 +01002273 /* Principle: we test once to set maxconn according to the free
2274 * memory. If it results in values the system rejects, we try a
2275 * second time by respecting rlim_fd_max. If it fails again, we
2276 * go back to the initial value and will let the final code
2277 * dealing with rlimit report the error. That's up to 3 attempts.
2278 */
2279 do {
2280 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2281 if (retried == 1)
2282 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2283 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002284#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002285 if (global.maxconn > SYSTEM_MAXCONN)
2286 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002287#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002288
Willy Tarreau304e17e2020-03-10 17:54:54 +01002289 if (clearmem <= 0 || !global.maxconn) {
2290 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2291 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2292 "is %d, but %d was found.\n",
2293 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002294 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002295 global.maxsslconn);
2296 exit(1);
2297 }
2298
2299 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2300 break;
2301 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002302
2303 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2304 if (sides && global.maxsslconn > sides * global.maxconn) {
2305 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2306 "to be limited to %d. Better reduce global.maxsslconn to get more "
2307 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2308 }
2309 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2310 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002311 }
2312
Willy Tarreaua409f302020-03-10 17:08:53 +01002313 global.maxsock = compute_ideal_maxsock(global.maxconn);
2314 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002315 if (!global.maxpipes)
2316 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002317
Olivier Houchard88698d92019-04-16 19:07:22 +02002318 /* update connection pool thresholds */
2319 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2320 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2321
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002322 proxy_adjust_all_maxconn();
2323
Willy Tarreau1db37712007-06-03 17:16:49 +02002324 if (global.tune.maxpollevents <= 0)
2325 global.tune.maxpollevents = MAX_POLL_EVENTS;
2326
Willy Tarreau060a7612021-03-10 11:06:26 +01002327 if (global.tune.runqueue_depth <= 0) {
2328 /* tests on various thread counts from 1 to 64 have shown an
2329 * optimal queue depth following roughly 1/sqrt(threads).
2330 */
2331 int s = my_flsl(global.nbthread);
2332 s += (global.nbthread / s); // roughly twice the sqrt.
2333 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2334 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002335
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002336 if (global.tune.recv_enough == 0)
2337 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2338
Willy Tarreau27a674e2009-08-17 07:23:33 +02002339 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2340 global.tune.maxrewrite = global.tune.bufsize / 2;
2341
Amaury Denoyelle11124302021-06-04 18:22:08 +02002342 usermsgs_clr(NULL);
2343
Willy Tarreaubaaee002006-06-26 02:48:02 +02002344 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2345 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002346 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002347 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2348 }
2349
William Lallemand095ba4c2017-06-01 17:38:50 +02002350 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002351 /* command line daemon mode inhibits foreground and debug modes mode */
2352 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002353 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002354 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002355
2356 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002357
William Lallemand095ba4c2017-06-01 17:38:50 +02002358 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002359 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002360 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002361 }
2362
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002363 if (global.nbthread < 1)
2364 global.nbthread = 1;
2365
Christopher Faulet3ef26392017-08-29 16:46:57 +02002366 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002367 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002368 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002369 exit(1);
2370 }
2371
Christopher Faulet96d44832017-11-14 22:02:30 +01002372 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002373 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002374 exit(1);
2375 }
2376
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002377 /*
2378 * Note: we could register external pollers here.
2379 * Built-in pollers have been registered before main().
2380 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002381
Willy Tarreau43b78992009-01-25 15:42:27 +01002382 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002383 disable_poller("kqueue");
2384
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002385 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2386 disable_poller("evports");
2387
Willy Tarreau43b78992009-01-25 15:42:27 +01002388 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002389 disable_poller("epoll");
2390
Willy Tarreau43b78992009-01-25 15:42:27 +01002391 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002392 disable_poller("poll");
2393
Willy Tarreau43b78992009-01-25 15:42:27 +01002394 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002395 disable_poller("select");
2396
2397 /* Note: we could disable any poller by name here */
2398
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002399 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002400 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002401 fprintf(stderr, "\n");
2402 list_filters(stderr);
2403 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002404
Willy Tarreau4f60f162007-04-08 16:39:58 +02002405 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002406 ha_alert("No polling mechanism available.\n"
2407 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2408 " is too low on this platform to support maxconn and the number of listeners\n"
2409 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2410 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2411 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2412 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2413 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2414 " check build settings using 'haproxy -vv'.\n\n",
2415 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002416 exit(1);
2417 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002418 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2419 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002420 }
2421
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002422 if (!global.node)
2423 global.node = strdup(hostname);
2424
Willy Tarreau02b092f2020-10-07 18:36:54 +02002425 /* stop disabled proxies */
2426 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002427 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002428 stop_proxy(px);
2429 }
2430
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002431 if (!hlua_post_init())
2432 exit(1);
Thomas Holmes6abded42015-05-12 16:23:58 +01002433
Maxime de Roucy0f503922016-05-13 23:52:55 +02002434 free(err_msg);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002435}
2436
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002437void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002438{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002439 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002440 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002441 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002442 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002443 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002444 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002445 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002446 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002447 struct per_thread_init_fct *tif, *tifb;
2448 struct per_thread_deinit_fct *tdf, *tdfb;
2449 struct per_thread_alloc_fct *taf, *tafb;
2450 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002451 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002452 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002453 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002454 int cur_fd;
2455
2456 /* At this point the listeners state is weird:
2457 * - most listeners are still bound and referenced in their protocol
2458 * - some might be zombies that are not in their proto anymore, but
2459 * still appear in their proxy's listeners with a valid FD.
2460 * - some might be stopped and still appear in their proxy as FD #-1
2461 * - among all of them, some might be inherited hence shared and we're
2462 * not allowed to pause them or whatever, we must just close them.
2463 * - finally some are not listeners (pipes, logs, stdout, etc) and
2464 * must be left intact.
2465 *
2466 * The safe way to proceed is to unbind (and close) whatever is not yet
2467 * unbound so that no more receiver/listener remains alive. Then close
2468 * remaining listener FDs, which correspond to zombie listeners (those
2469 * belonging to disabled proxies that were in another process).
2470 * objt_listener() would be cleaner here but not converted yet.
2471 */
2472 protocol_unbind_all();
2473
2474 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002475 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002476 continue;
2477
Willy Tarreaua74cb382020-10-15 21:29:49 +02002478 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002479 struct listener *l = fdtab[cur_fd].owner;
2480
2481 BUG_ON(l->state != LI_INIT);
2482 unbind_listener(l);
2483 }
2484 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002485
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002486 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002487 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002488 /* build a list of unique uri_auths */
2489 if (!ua)
2490 ua = p->uri_auth;
2491 else {
2492 /* check if p->uri_auth is unique */
2493 for (uap = ua; uap; uap=uap->next)
2494 if (uap == p->uri_auth)
2495 break;
2496
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002497 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002498 /* add it, if it is */
2499 p->uri_auth->next = ua;
2500 ua = p->uri_auth;
2501 }
William Lallemand0f99e342011-10-12 17:50:54 +02002502 }
2503
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002504 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002505 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002506 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002507 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002508
Christopher Faulet27c8d202021-10-13 09:50:53 +02002509 /* destroy all referenced defaults proxies */
2510 proxy_destroy_all_unref_defaults();
2511
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002512 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002513 struct stat_scope *scope, *scopep;
2514
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002515 uap = ua;
2516 ua = ua->next;
2517
Willy Tarreaua534fea2008-08-03 12:19:50 +02002518 free(uap->uri_prefix);
2519 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002520 free(uap->node);
2521 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002522
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002523 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002524 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002525
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002526 scope = uap->scope;
2527 while (scope) {
2528 scopep = scope;
2529 scope = scope->next;
2530
2531 free(scopep->px_id);
2532 free(scopep);
2533 }
2534
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002535 free(uap);
2536 }
2537
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002538 userlist_free(userlist);
2539
David Carlier834cb2e2015-09-25 12:02:25 +01002540 cfg_unregister_sections();
2541
Christopher Faulet0132d062017-07-26 15:33:35 +02002542 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002543
Willy Tarreau05554e62016-12-21 20:46:26 +01002544 list_for_each_entry(pdf, &post_deinit_list, list)
2545 pdf->fct();
2546
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002547 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002548 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002549 ha_free(&global.chroot);
2550 ha_free(&global.pidfile);
2551 ha_free(&global.node);
2552 ha_free(&global.desc);
2553 ha_free(&oldpids);
2554 ha_free(&old_argv);
2555 ha_free(&localpeer);
2556 ha_free(&global.server_state_base);
2557 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002558 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002559 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002560
William Lallemand0f99e342011-10-12 17:50:54 +02002561 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002562 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002563 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002564 free(log);
2565 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002566 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002567 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002568 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002569 free(wl);
2570 }
2571
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002572 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2573 if (bol->must_free)
2574 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002575 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002576 free(bol);
2577 }
2578
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002579 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002580 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002581 free(pxdf);
2582 }
2583
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002584 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002585 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002586 free(pdf);
2587 }
2588
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002589 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002590 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002591 free(srvdf);
2592 }
2593
Tim Duesterhusfc854942020-09-10 19:46:42 +02002594 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002595 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002596 free(pcf);
2597 }
2598
Tim Duesterhus34bef072020-07-04 11:49:50 +02002599 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002600 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002601 free(pscf);
2602 }
2603
Tim Duesterhus53508d62020-09-10 19:46:40 +02002604 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002605 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002606 free(ppcf);
2607 }
2608
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002609 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002610 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002611 free(tif);
2612 }
2613
2614 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002615 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002616 free(tdf);
2617 }
2618
2619 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002620 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002621 free(taf);
2622 }
2623
2624 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002625 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002626 free(tff);
2627 }
2628
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002629 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002630 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002631 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632} /* end deinit() */
2633
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002634__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002635{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002636 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002637 deinit();
2638 exit(status);
2639}
William Lallemand72160322018-11-06 17:37:16 +01002640
Willy Tarreau918ff602011-07-25 16:33:49 +02002641/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002642void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002643{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002644 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002645
Willy Tarreau55542642021-10-08 09:33:24 +02002646 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002647 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002648 wake_expired_tasks();
2649
William Lallemand1aab50b2018-06-07 09:46:01 +02002650 /* check if we caught some signals and process them in the
2651 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002652 if (signal_queue_len && tid == 0) {
2653 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002654 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002655 }
2656
2657 /* Process a few tasks */
2658 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002659
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002660 /* also stop if we failed to cleanly stop all tasks */
2661 if (killed > 1)
2662 break;
2663
Willy Tarreau10146c92015-04-13 20:44:19 +02002664 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002665 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002666 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002667 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002668 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002669 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2670 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002671 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002672 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002673 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002674 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002675 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002676 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002677
Willy Tarreau4f46a352020-03-23 09:27:28 +01002678 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002679 int i;
2680
2681 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002682 /* stop muxes before acknowledging stopping */
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002683 if (!(stopping_thread_mask & tid_bit)) {
2684 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2685 wake = 1;
2686 }
2687
Willy Tarreau1db42732021-04-06 11:44:07 +02002688 if (_HA_ATOMIC_OR_FETCH(&stopping_thread_mask, tid_bit) == tid_bit) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002689 /* notify all threads that stopping was just set */
2690 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002691 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002692 wake_thread(i);
2693 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002694 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002695
2696 /* stop when there's nothing left to do */
2697 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002698 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2699 /* wake all threads waiting on jobs==0 */
2700 for (i = 0; i < global.nbthread; i++)
2701 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2702 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002703 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002704 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002705 }
2706
Willy Tarreauc49ba522019-12-11 08:12:23 +01002707 /* If we have to sleep, measure how long */
2708 next = wake ? TICK_ETERNITY : next_timer_expiry();
2709
Willy Tarreau58b458d2008-06-29 22:40:23 +02002710 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002711 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002712
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002713 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002714 }
2715}
2716
Christopher Faulet1d17c102017-08-29 15:38:48 +02002717static void *run_thread_poll_loop(void *data)
2718{
Willy Tarreau082b6282019-05-22 14:42:12 +02002719 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002720 struct per_thread_init_fct *ptif;
2721 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002722 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002723 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002724 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2725 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002726
Willy Tarreau43ab05b2021-09-28 09:43:11 +02002727 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02002728 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02002729 clock_set_local_source();
Willy Tarreau91e6df02019-05-03 17:21:18 +02002730
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002731 /* Now, initialize one thread init at a time. This is better since
2732 * some init code is a bit tricky and may release global resources
2733 * after reallocating them locally. This will also ensure there is
2734 * no race on file descriptors allocation.
2735 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002736#ifdef USE_THREAD
2737 pthread_mutex_lock(&init_mutex);
2738#endif
2739 /* The first thread must set the number of threads left */
2740 if (!init_left)
2741 init_left = global.nbthread;
2742 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002743
Willy Tarreau55542642021-10-08 09:33:24 +02002744 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002745
Willy Tarreau082b6282019-05-22 14:42:12 +02002746 /* per-thread alloc calls performed here are not allowed to snoop on
2747 * other threads, so they are free to initialize at their own rhythm
2748 * as long as they act as if they were alone. None of them may rely
2749 * on resources initialized by the other ones.
2750 */
2751 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2752 if (!ptaf->fct()) {
2753 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002754#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002755 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002756#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02002757 exit(1);
2758 }
2759 }
2760
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002761 /* per-thread init calls performed here are not allowed to snoop on
2762 * other threads, so they are free to initialize at their own rhythm
2763 * as long as they act as if they were alone.
2764 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002765 list_for_each_entry(ptif, &per_thread_init_list, list) {
2766 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002767 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002768#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002769 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002770#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002771 exit(1);
2772 }
2773 }
2774
Willy Tarreau71092822019-06-10 09:51:04 +02002775 /* enabling protocols will result in fd_insert() calls to be performed,
2776 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002777 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002778 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002779 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002780 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002781
Willy Tarreau34a150c2019-06-11 09:16:41 +02002782#ifdef USE_THREAD
2783 pthread_cond_broadcast(&init_cond);
2784 pthread_mutex_unlock(&init_mutex);
2785
2786 /* now wait for other threads to finish starting */
2787 pthread_mutex_lock(&init_mutex);
2788 while (init_left)
2789 pthread_cond_wait(&init_cond, &init_mutex);
2790 pthread_mutex_unlock(&init_mutex);
2791#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002792
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002793#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2794 /* Let's refrain from using setuid executables. This way the impact of
2795 * an eventual vulnerability in a library remains limited. It may
2796 * impact external checks but who cares about them anyway ? In the
2797 * worst case it's possible to disable the option. Obviously we do this
2798 * in workers only. We can't hard-fail on this one as it really is
2799 * implementation dependent though we're interested in feedback, hence
2800 * the warning.
2801 */
2802 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2803 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002804 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 +01002805 ha_warning("Failed to disable setuid, please report to developers with detailed "
2806 "information about your operating system. You can silence this warning "
2807 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2808 }
2809 }
2810#endif
2811
Willy Tarreaud96f1122019-12-03 07:07:36 +01002812#if defined(RLIMIT_NPROC)
2813 /* all threads have started, it's now time to prevent any new thread
2814 * or process from starting. Obviously we do this in workers only. We
2815 * can't hard-fail on this one as it really is implementation dependent
2816 * though we're interested in feedback, hence the warning.
2817 */
2818 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2819 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2820 static int warn_fail;
2821
Willy Tarreau18515722021-04-06 11:57:41 +02002822 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002823 ha_warning("Failed to disable forks, please report to developers with detailed "
2824 "information about your operating system. You can silence this warning "
2825 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2826 }
2827 }
2828#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002829 run_poll_loop();
2830
2831 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2832 ptdf->fct();
2833
Willy Tarreau082b6282019-05-22 14:42:12 +02002834 list_for_each_entry(ptff, &per_thread_free_list, list)
2835 ptff->fct();
2836
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002837#ifdef USE_THREAD
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002838 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002839 if (tid > 0)
2840 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002841#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002842 return NULL;
2843}
Christopher Faulet1d17c102017-08-29 15:38:48 +02002844
William Dauchyf9af9d72019-11-17 15:47:16 +01002845/* set uid/gid depending on global settings */
2846static void set_identity(const char *program_name)
2847{
2848 if (global.gid) {
2849 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
2850 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
2851 " without 'uid'/'user' is generally useless.\n", program_name);
2852
2853 if (setgid(global.gid) == -1) {
2854 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
2855 protocol_unbind_all();
2856 exit(1);
2857 }
2858 }
2859
2860 if (global.uid && setuid(global.uid) == -1) {
2861 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
2862 protocol_unbind_all();
2863 exit(1);
2864 }
2865}
2866
Willy Tarreaubaaee002006-06-26 02:48:02 +02002867int main(int argc, char **argv)
2868{
2869 int err, retry;
2870 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02002871 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02002872 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
2873
2874 /* Catch forced CFLAGS that miss 2-complement integer overflow */
2875 if (intovf + 0x7FFFFFFF >= intovf) {
2876 fprintf(stderr,
2877 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
2878 "The source code was miscompiled by the compiler, which usually indicates that\n"
2879 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
2880 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
2881 "and INSTALL files to decide on the best way to pass your local build options.\n"
2882 "\nBuild options :"
2883#ifdef BUILD_TARGET
2884 "\n TARGET = " BUILD_TARGET
2885#endif
2886#ifdef BUILD_CPU
2887 "\n CPU = " BUILD_CPU
2888#endif
2889#ifdef BUILD_CC
2890 "\n CC = " BUILD_CC
2891#endif
2892#ifdef BUILD_CFLAGS
2893 "\n CFLAGS = " BUILD_CFLAGS
2894#endif
2895#ifdef BUILD_OPTIONS
2896 "\n OPTIONS = " BUILD_OPTIONS
2897#endif
2898#ifdef BUILD_DEBUG
2899 "\n DEBUG = " BUILD_DEBUG
2900#endif
2901 "\n\n");
2902 return 1;
2903 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904
Olivier Houchard5fa300d2018-02-03 15:15:21 +01002905 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01002906
Willy Tarreaubf696402019-03-01 10:09:28 +01002907 /* take a copy of initial limits before we possibly change them */
2908 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02002909
2910 if (limit.rlim_max == RLIM_INFINITY)
2911 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01002912 rlim_fd_cur_at_boot = limit.rlim_cur;
2913 rlim_fd_max_at_boot = limit.rlim_max;
2914
Willy Tarreau5794fb02018-11-25 18:43:29 +01002915 /* process all initcalls in order of potential dependency */
2916 RUN_INITCALLS(STG_PREPARE);
2917 RUN_INITCALLS(STG_LOCK);
2918 RUN_INITCALLS(STG_ALLOC);
2919 RUN_INITCALLS(STG_POOL);
2920 RUN_INITCALLS(STG_REGISTER);
2921 RUN_INITCALLS(STG_INIT);
2922
Emeric Bruncf20bf12010-10-22 16:06:11 +02002923 init(argc, argv);
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002924 signal_register_fct(SIGQUIT, dump, SIGQUIT);
2925 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
2926 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02002927 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002928
Willy Tarreaue437c442010-03-17 18:02:46 +01002929 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
2930 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
2931 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002932 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002933 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002934
Willy Tarreaudc23a922011-02-16 11:10:36 +01002935 /* ulimits */
2936 if (!global.rlimit_nofile)
2937 global.rlimit_nofile = global.maxsock;
2938
2939 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01002940 limit.rlim_cur = global.rlimit_nofile;
2941 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
2942
Willy Tarreaudc23a922011-02-16 11:10:36 +01002943 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02002944 getrlimit(RLIMIT_NOFILE, &limit);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002945 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2946 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
2947 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002948 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002949 }
2950 else {
2951 /* try to set it to the max possible at least */
2952 limit.rlim_cur = limit.rlim_max;
2953 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
2954 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02002955
William Dauchya5194602020-03-28 19:29:58 +01002956 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002957 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
2958 global.rlimit_nofile = limit.rlim_cur;
2959 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01002960 }
2961 }
2962
2963 if (global.rlimit_memmax) {
2964 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01002965 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01002966#ifdef RLIMIT_AS
2967 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002968 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2969 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2970 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002971 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002972 }
2973 else
William Dauchya5194602020-03-28 19:29:58 +01002974 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002975 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002976 }
2977#else
2978 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002979 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2980 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2981 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002982 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002983 }
2984 else
William Dauchya5194602020-03-28 19:29:58 +01002985 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002986 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002987 }
2988#endif
2989 }
2990
Olivier Houchardf73629d2017-04-05 22:33:04 +02002991 if (old_unixsocket) {
William Lallemand85b0bd92017-06-01 17:38:53 +02002992 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02002993 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002994 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02002995 if (!(global.mode & MODE_MWORKER))
2996 exit(1);
2997 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02002998 }
2999 }
William Lallemand85b0bd92017-06-01 17:38:53 +02003000
Willy Tarreaubaaee002006-06-26 02:48:02 +02003001 /* We will loop at most 100 times with 10 ms delay each time.
3002 * That's at most 1 second. We only send a signal to old pids
3003 * if we cannot grab at least one port.
3004 */
3005 retry = MAX_START_RETRIES;
3006 err = ERR_NONE;
3007 while (retry >= 0) {
3008 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003009 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003010 /* exit the loop on no error or fatal error */
3011 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003012 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003013 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 break;
3015
3016 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3017 * listening sockets. So on those platforms, it would be wiser to
3018 * simply send SIGUSR1, which will not be undoable.
3019 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003020 if (tell_old_pids(SIGTTOU) == 0) {
3021 /* no need to wait if we can't contact old pids */
3022 retry = 0;
3023 continue;
3024 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003025 /* give some time to old processes to stop listening */
3026 w.tv_sec = 0;
3027 w.tv_usec = 10*1000;
3028 select(0, NULL, NULL, NULL, &w);
3029 retry--;
3030 }
3031
Willy Tarreaue91bff22020-09-02 11:11:43 +02003032 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003033 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003034 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003035 if (retry != MAX_START_RETRIES && nb_oldpids) {
3036 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003037 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003039 exit(1);
3040 }
3041
William Lallemand944e6192018-11-21 15:48:31 +01003042 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003043 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003044 /* Note: we don't have to send anything to the old pids because we
3045 * never stopped them. */
3046 exit(1);
3047 }
3048
Willy Tarreaue91bff22020-09-02 11:11:43 +02003049 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003050 * the previous process gave us, we don't need them anymore
3051 */
3052 while (xfer_sock_list != NULL) {
3053 struct xfer_sock_list *tmpxfer = xfer_sock_list->next;
3054 close(xfer_sock_list->fd);
3055 free(xfer_sock_list->iface);
3056 free(xfer_sock_list->namespace);
3057 free(xfer_sock_list);
3058 xfer_sock_list = tmpxfer;
3059 }
Willy Tarreaudd815982007-10-16 12:25:14 +02003060
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003062 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3063 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003064
Willy Tarreaubaaee002006-06-26 02:48:02 +02003065 /* MODE_QUIET can inhibit alerts and warnings below this line */
3066
PiBa-NL149a81a2017-12-25 21:03:31 +01003067 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3068 /* either stdin/out/err are already closed or should stay as they are. */
3069 if ((global.mode & MODE_DAEMON)) {
3070 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3071 global.mode &= ~MODE_VERBOSE;
3072 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3073 }
3074 } else {
3075 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3076 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003077 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003078 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003079 }
3080
3081 /* open log & pid files before the chroot */
William Lallemand80293002017-11-06 11:00:03 +01003082 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 unlink(global.pidfile);
3084 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3085 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003086 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003087 if (nb_oldpids)
3088 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003089 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003090 exit(1);
3091 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003092 }
3093
Willy Tarreaub38651a2007-03-24 17:24:39 +01003094 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003095 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3096 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003097 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003098 exit(1);
3099 }
3100
Jackie Tapia749f74c2020-07-22 18:59:40 -05003101 /* If the user is not root, we'll still let them try the configuration
3102 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003103 */
3104 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003105 ha_warning("[%s.main()] Some options which require full privileges"
3106 " might not work well.\n"
3107 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003108
William Lallemand095ba4c2017-06-01 17:38:50 +02003109 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3110
3111 /* chroot if needed */
3112 if (global.chroot != NULL) {
3113 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003114 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003115 if (nb_oldpids)
3116 tell_old_pids(SIGTTIN);
3117 protocol_unbind_all();
3118 exit(1);
3119 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003120 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003121 }
3122
William Lallemand944e6192018-11-21 15:48:31 +01003123 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003124 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125
William Lallemand27edc4b2019-05-07 17:49:33 +02003126 /* send a SIGTERM to workers who have a too high reloads number */
3127 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3128 mworker_kill_max_reloads(SIGTERM);
3129
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 /* Note that any error at this stage will be fatal because we will not
3131 * be able to restart the old pids.
3132 */
3133
William Dauchyf9af9d72019-11-17 15:47:16 +01003134 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3135 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003136
Willy Tarreaubaaee002006-06-26 02:48:02 +02003137 /* check ulimits */
3138 limit.rlim_cur = limit.rlim_max = 0;
3139 getrlimit(RLIMIT_NOFILE, &limit);
3140 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003141 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3142 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3143 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3144 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3145 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003146 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003147 }
3148 else
3149 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003150 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003151 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3152 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003153 }
3154
William Lallemand944e6192018-11-21 15:48:31 +01003155 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003156 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003157 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003158 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003159
William Lallemand095ba4c2017-06-01 17:38:50 +02003160 /*
3161 * if daemon + mworker: must fork here to let a master
3162 * process live in background before forking children
3163 */
William Lallemand73b85e72017-06-01 17:38:51 +02003164
3165 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3166 && (global.mode & MODE_MWORKER)
3167 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003168 ret = fork();
3169 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003170 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003171 protocol_unbind_all();
3172 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003173 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003174 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003175 } else /* change the process group ID in the child (master process) */
3176 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003177 }
William Lallemande20b6a62017-06-01 17:38:55 +02003178
William Lallemande20b6a62017-06-01 17:38:55 +02003179
William Lallemanddeed7802017-11-06 11:00:04 +01003180 /* if in master-worker mode, write the PID of the father */
3181 if (global.mode & MODE_MWORKER) {
3182 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003183 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003184 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003185 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003186 }
3187
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003189 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003190 if (global.mode & MODE_MWORKER)
3191 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003192
3193 ret = fork();
3194 if (ret < 0) {
3195 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3196 protocol_unbind_all();
3197 exit(1); /* there has been an error */
3198 }
3199 else if (ret == 0) { /* child breaks here */
Willy Tarreau3c032f22021-07-21 10:17:02 +02003200 /* This one must not be exported, it's internal! */
3201 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003202 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003203 }
3204 else { /* parent here */
3205 in_parent = 1;
3206
William Lallemand944e6192018-11-21 15:48:31 +01003207 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3208 char pidstr[100];
3209 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003210 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003211 }
3212 if (global.mode & MODE_MWORKER) {
3213 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003214
William Lallemand5d71a6b2021-11-09 15:25:31 +01003215 ha_notice("New worker (%d) forked\n", ret);
William Lallemand944e6192018-11-21 15:48:31 +01003216 /* find the right mworker_proc */
3217 list_for_each_entry(child, &proc_list, list) {
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003218 if (child->reloads == 0 && child->options & PROC_O_TYPE_WORKER) {
William Lallemand944e6192018-11-21 15:48:31 +01003219 child->timestamp = now.tv_sec;
3220 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003221 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003222 break;
3223 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003224 }
3225 }
William Lallemand944e6192018-11-21 15:48:31 +01003226 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003227
William Lallemand944e6192018-11-21 15:48:31 +01003228 } else {
3229 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003230 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003231 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003232
3233#ifdef USE_CPU_AFFINITY
Willy Tarreau44ea6312021-06-15 08:57:56 +02003234 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 +02003235
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003236#ifdef __FreeBSD__
Willy Tarreau44ea6312021-06-15 08:57:56 +02003237 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003238 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
David Carlier2d0493a2020-12-02 21:14:51 +00003239#elif defined(__linux__) || defined(__DragonFly__)
Willy Tarreau44ea6312021-06-15 08:57:56 +02003240 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003241 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003242#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003243 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003244#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003245 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003246 if (pidfd >= 0) {
3247 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3248 close(pidfd);
3249 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003250
3251 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003252 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003253
Willy Tarreaud67ff342021-06-15 07:58:09 +02003254 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003255 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
William Lallemandfab0fdc2021-11-09 18:01:22 +01003256 master = 1;
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003257
3258 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3259 (global.mode & MODE_DAEMON)) {
3260 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003261 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3262 stdio_quiet(-1);
3263
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003264 global.mode &= ~MODE_VERBOSE;
3265 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003266 }
3267
William Lallemandfab0fdc2021-11-09 18:01:22 +01003268 if (global.mode & MODE_MWORKER_WAIT) {
3269 /* only the wait mode handles the master CLI */
3270 mworker_loop();
3271 } else {
3272
3273 /* if not in wait mode, reload in wait mode to free the memory */
William Lallemand836bda22021-11-09 18:16:47 +01003274 ha_notice("Loading success.\n");
William Lallemand68836742021-11-10 10:49:06 +01003275 proc_self->failedreloads = 0; /* reset the number of failure */
William Lallemandfab0fdc2021-11-09 18:01:22 +01003276 mworker_reexec_waitmode();
3277 }
William Lallemand1499b9b2017-06-07 15:04:47 +02003278 /* should never get there */
3279 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003280 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003281#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003282 ssl_free_dh();
3283#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003284 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003285 }
3286
William Lallemandcb11fd22017-06-01 17:38:52 +02003287 /* child must never use the atexit function */
3288 atexit_flag = 0;
3289
William Lallemandbc193052018-09-11 10:06:26 +02003290 /* close useless master sockets */
3291 if (global.mode & MODE_MWORKER) {
3292 struct mworker_proc *child, *it;
3293 master = 0;
3294
William Lallemand309dc9a2018-10-26 14:47:45 +02003295 mworker_cli_proxy_stop();
3296
William Lallemandbc193052018-09-11 10:06:26 +02003297 /* free proc struct of other processes */
3298 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003299 /* close the FD of the master side for all
3300 * workers, we don't need to close the worker
3301 * side of other workers since it's done with
3302 * the bind_proc */
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003303 if (child->ipc_fd[0] >= 0)
3304 close(child->ipc_fd[0]);
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003305 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandce83b4a2018-10-26 14:47:30 +02003306 child->reloads == 0) {
3307 /* keep this struct if this is our pid */
3308 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003309 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003310 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003311 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003312 mworker_free_child(child);
3313 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003314 }
3315 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003316
William Lallemande1340412017-12-28 16:09:36 +01003317 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3318 devnullfd = open("/dev/null", O_RDWR, 0);
3319 if (devnullfd < 0) {
3320 ha_alert("Cannot open /dev/null\n");
3321 exit(EXIT_FAILURE);
3322 }
3323 }
3324
William Lallemand095ba4c2017-06-01 17:38:50 +02003325 /* Must chroot and setgid/setuid in the children */
3326 /* chroot if needed */
3327 if (global.chroot != NULL) {
3328 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003329 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003330 if (nb_oldpids)
3331 tell_old_pids(SIGTTIN);
3332 protocol_unbind_all();
3333 exit(1);
3334 }
3335 }
3336
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003337 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003338 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003339
William Lallemand7f80eb22017-05-26 18:19:55 +02003340 /* pass through every cli socket, and check if it's bound to
3341 * the current process and if it exposes listeners sockets.
3342 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3343 * */
3344
Willy Tarreau4975d142021-03-13 11:00:33 +01003345 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003346 struct bind_conf *bind_conf;
3347
Willy Tarreau4975d142021-03-13 11:00:33 +01003348 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003349 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003350 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3351 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003352 }
3353 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003354 }
3355
William Lallemand2e8fad92018-11-13 16:18:23 +01003356 /*
3357 * This is only done in daemon mode because we might want the
3358 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3359 * we should now close the 3 first FDs to ensure that we can
3360 * detach from the TTY. We MUST NOT do it in other cases since
3361 * it would have already be done, and 0-2 would have been
3362 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003364 if ((global.mode & MODE_DAEMON) &&
3365 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003366 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003367 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003368 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003369 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3370 }
3371 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003372 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3373 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003374 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 }
3376
William Dauchye039f262019-11-17 15:47:15 +01003377 /* try our best to re-enable core dumps depending on system capabilities.
3378 * What is addressed here :
3379 * - remove file size limits
3380 * - remove core size limits
3381 * - mark the process dumpable again if it lost it due to user/group
3382 */
3383 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3384 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3385
3386#if defined(RLIMIT_FSIZE)
3387 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3388 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3389 ha_alert("[%s.main()] Failed to set the raise the maximum "
3390 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003391 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003392 }
3393 else
3394 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003395 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003396 }
3397#endif
3398
3399#if defined(RLIMIT_CORE)
3400 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3401 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3402 ha_alert("[%s.main()] Failed to set the raise the core "
3403 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003404 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003405 }
3406 else
3407 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003408 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003409 }
3410#endif
3411
3412#if defined(USE_PRCTL)
3413 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3414 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3415 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003416#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003417 {
3418 int traceable = PROC_TRACE_CTL_ENABLE;
3419 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3420 ha_warning("[%s.main()] Failed to set the traceable flag, "
3421 "no core will be dumped.\n", argv[0]);
3422 }
William Dauchye039f262019-11-17 15:47:15 +01003423#endif
3424 }
3425
Christopher Faulete3a5e352017-10-24 13:53:54 +02003426 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003427 reset_usermsgs_ctx();
3428
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003429 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003430 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003431
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003432 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003433 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003434
3435 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003436 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003437
3438 /* wait for all threads to terminate */
3439 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003440
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003441 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003442}
3443
Willy Tarreaubaaee002006-06-26 02:48:02 +02003444/*
3445 * Local variables:
3446 * c-indent-level: 8
3447 * c-basic-offset: 8
3448 * End:
3449 */