blob: d09f15c85a243b2c42b416c2d9e69716f18c70ba [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 Tarreaufc6c0322012-11-16 16:12:27 +010053#ifdef USE_CPU_AFFINITY
Willy Tarreaufc6c0322012-11-16 16:12:27 +010054#include <sched.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000055#if defined(__FreeBSD__) || defined(__DragonFly__)
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020056#include <sys/param.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000057#ifdef __FreeBSD__
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020058#include <sys/cpuset.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000059#endif
David Carlier6d5c8412017-11-29 11:02:32 +000060#include <pthread_np.h>
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020061#endif
David Carlier5e4c8e22019-09-13 05:12:58 +010062#ifdef __APPLE__
63#include <mach/mach_types.h>
64#include <mach/thread_act.h>
65#include <mach/thread_policy.h>
66#endif
Willy Tarreaufc6c0322012-11-16 16:12:27 +010067#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020068
Willy Tarreau636848a2019-04-15 19:38:50 +020069#if defined(USE_PRCTL)
70#include <sys/prctl.h>
71#endif
72
Willy Tarreaubaaee002006-06-26 02:48:02 +020073#ifdef DEBUG_FULL
74#include <assert.h>
75#endif
Tim Duesterhusd6942c82017-11-20 15:58:35 +010076#if defined(USE_SYSTEMD)
77#include <systemd/sd-daemon.h>
78#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020079
Willy Tarreau6c3a6812020-03-06 18:57:15 +010080#include <import/sha1.h>
81
Willy Tarreaub2551052020-06-09 09:07:15 +020082#include <haproxy/acl.h>
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +010083#include <haproxy/action.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020084#include <haproxy/activity.h>
85#include <haproxy/api.h>
86#include <haproxy/arg.h>
87#include <haproxy/auth.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020088#include <haproxy/base64.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020089#include <haproxy/capture-t.h>
Willy Tarreau66243b42021-07-16 15:39:28 +020090#include <haproxy/cfgcond.h>
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +020091#include <haproxy/cfgdiag.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020092#include <haproxy/cfgparse.h>
Willy Tarreauc13ed532020-06-02 10:22:45 +020093#include <haproxy/chunk.h>
Willy Tarreau83487a82020-06-04 20:19:54 +020094#include <haproxy/cli.h>
Willy Tarreau7ea393d2020-06-04 18:02:10 +020095#include <haproxy/connection.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +020096#ifdef USE_CPU_AFFINITY
Amaury Denoyelle982fb532021-04-21 18:39:58 +020097#include <haproxy/cpuset.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +020098#endif
Willy Tarreaueb92deb2020-06-04 10:53:16 +020099#include <haproxy/dns.h>
Willy Tarreau2741c8c2020-06-02 11:28:02 +0200100#include <haproxy/dynbuf.h>
Willy Tarreau8d366972020-05-27 16:10:29 +0200101#include <haproxy/errors.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200102#include <haproxy/fd.h>
Willy Tarreauc7babd82020-06-04 21:29:29 +0200103#include <haproxy/filters.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200104#include <haproxy/global.h>
Willy Tarreau86416052020-06-04 09:20:54 +0200105#include <haproxy/hlua.h>
Willy Tarreauc761f842020-06-04 11:40:28 +0200106#include <haproxy/http_rules.h>
Willy Tarreau853b2972020-05-27 18:01:47 +0200107#include <haproxy/list.h>
Willy Tarreau213e9902020-06-04 14:58:24 +0200108#include <haproxy/listener.h>
Willy Tarreauaeed4a82020-06-04 22:01:04 +0200109#include <haproxy/log.h>
Willy Tarreaub5abe5b2020-06-04 14:07:37 +0200110#include <haproxy/mworker.h>
Willy Tarreau7a00efb2020-06-02 17:02:59 +0200111#include <haproxy/namespace.h>
Willy Tarreau6131d6a2020-06-02 16:48:09 +0200112#include <haproxy/net_helper.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +0200113#include <haproxy/openssl-compat.h>
Willy Tarreau225a90a2020-06-04 15:06:28 +0200114#include <haproxy/pattern.h>
Willy Tarreau3c2a7c22020-06-04 18:38:21 +0200115#include <haproxy/peers.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200116#include <haproxy/pool.h>
117#include <haproxy/protocol.h>
Willy Tarreaubf3b06b2020-08-26 10:23:40 +0200118#include <haproxy/proto_tcp.h>
Willy Tarreaua264d962020-06-04 22:29:18 +0200119#include <haproxy/proxy.h>
Willy Tarreau7cd8b6e2020-06-02 17:32:26 +0200120#include <haproxy/regex.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200121#include <haproxy/sample.h>
Willy Tarreau1e56f922020-06-04 23:20:13 +0200122#include <haproxy/server.h>
Willy Tarreau48d25b32020-06-04 18:58:52 +0200123#include <haproxy/session.h>
Willy Tarreau3727a8a2020-06-04 17:37:26 +0200124#include <haproxy/signal.h>
Willy Tarreau063d47d2020-08-28 16:29:53 +0200125#include <haproxy/sock.h>
Willy Tarreau25140cc2020-08-28 15:40:33 +0200126#include <haproxy/sock_inet.h>
Willy Tarreau209108d2020-06-04 20:30:20 +0200127#include <haproxy/ssl_sock.h>
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +0200128#include <haproxy/stats-t.h>
Willy Tarreaudfd3de82020-06-04 23:46:14 +0200129#include <haproxy/stream.h>
Willy Tarreaucea0e1b2020-06-04 17:25:40 +0200130#include <haproxy/task.h>
Willy Tarreau3f567e42020-05-28 15:29:19 +0200131#include <haproxy/thread.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200132#include <haproxy/time.h>
133#include <haproxy/tools.h>
134#include <haproxy/uri_auth-t.h>
Willy Tarreaua1718922020-06-04 16:25:31 +0200135#include <haproxy/vars.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200136#include <haproxy/version.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200137
Willy Tarreaubaaee002006-06-26 02:48:02 +0200138
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100139/* array of init calls for older platforms */
140DECLARE_INIT_STAGES;
141
Willy Tarreauf4596402021-04-10 16:53:05 +0200142/* create a read_mostly section to hold variables which are accessed a lot
143 * but which almost never change. The purpose is to isolate them in their
144 * own cache lines where they don't risk to be perturbated by write accesses
145 * to neighbor variables. We need to create an empty aligned variable for
146 * this. The fact that the variable is of size zero means that it will be
147 * eliminated at link time if no other variable uses it, but alignment will
148 * be respected.
149 */
150empty_t __read_mostly_align HA_SECTION("read_mostly") ALIGNED(64);
151
Willy Tarreauf0d3b732021-05-06 16:30:32 +0200152#ifdef BUILD_FEATURES
153const char *build_features = BUILD_FEATURES;
154#else
155const char *build_features = "";
156#endif
157
Willy Tarreau477ecd82010-01-03 21:12:30 +0100158/* list of config files */
159static struct list cfg_cfgfiles = LIST_HEAD_INIT(cfg_cfgfiles);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200160int pid; /* current process id */
161
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100162volatile unsigned long sleeping_thread_mask = 0; /* Threads that are about to sleep in poll() */
Willy Tarreau4b3f27b2020-03-12 17:28:01 +0100163volatile unsigned long stopping_thread_mask = 0; /* Threads acknowledged stopping */
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100164
Willy Tarreaubaaee002006-06-26 02:48:02 +0200165/* global options */
166struct global global = {
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100167 .hard_stop_after = TICK_ETERNITY,
Amaury Denoyelle0f50cb92021-03-26 18:50:33 +0100168 .numa_cpu_mapping = 1,
Willy Tarreau149ab772019-01-26 14:27:06 +0100169 .nbthread = 0,
William Lallemand5f232402012-04-05 18:02:55 +0200170 .req_count = 0,
William Lallemand0f99e342011-10-12 17:50:54 +0200171 .logsrvs = LIST_HEAD_INIT(global.logsrvs),
William Lallemand9d5f5482012-11-07 16:12:57 +0100172 .maxzlibmem = 0,
William Lallemandd85f9172012-11-09 17:05:39 +0100173 .comp_rate_lim = 0,
Emeric Brun850efd52014-01-29 12:24:34 +0100174 .ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED,
Emeric Bruned760922010-10-22 17:59:25 +0200175 .unix_bind = {
176 .ux = {
177 .uid = -1,
178 .gid = -1,
179 .mode = 0,
180 }
181 },
Willy Tarreau27a674e2009-08-17 07:23:33 +0200182 .tune = {
Willy Tarreau7ac908b2019-02-27 12:02:18 +0100183 .options = GTUNE_LISTENER_MQ,
Willy Tarreauc77d3642018-12-12 06:19:42 +0100184 .bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
Christopher Faulet546c4692020-01-22 14:31:21 +0100185 .maxrewrite = MAXREWRITE,
Willy Tarreaua24adf02014-11-27 01:11:56 +0100186 .reserved_bufs = RESERVED_BUFS,
Willy Tarreauf3045d22015-04-29 16:24:50 +0200187 .pattern_cache = DEFAULT_PAT_LRU_SIZE,
Olivier Houchard88698d92019-04-16 19:07:22 +0200188 .pool_low_ratio = 20,
189 .pool_high_ratio = 25,
Christopher Faulet41ba36f2019-07-19 09:36:45 +0200190 .max_http_hdr = MAX_HTTP_HDR,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200191#ifdef USE_OPENSSL
Emeric Brun46635772012-11-14 11:32:56 +0100192 .sslcachesize = SSLCACHESIZE,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200193#endif
William Lallemandf3747832012-11-09 12:33:10 +0100194 .comp_maxlevel = 1,
Willy Tarreau7e312732014-02-12 16:35:14 +0100195#ifdef DEFAULT_IDLE_TIMER
196 .idle_timer = DEFAULT_IDLE_TIMER,
197#else
198 .idle_timer = 1000, /* 1 second */
199#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200200 },
Emeric Brun76d88952012-10-05 15:47:31 +0200201#ifdef USE_OPENSSL
202#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200203 .maxsslconn = DEFAULT_MAXSSLCONN,
204#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200205#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206 /* others NULL OK */
207};
208
209/*********************************************************************/
210
211int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100212int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200213int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100214int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100215int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100216int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200217
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500218/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219 * or kill. We will send them a signal every 10 ms until we can bind to all
220 * our ports. With 200 retries, that's about 2 seconds.
221 */
222#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223static int *oldpids = NULL;
224static int oldpids_sig; /* use USR1 or TERM */
225
Olivier Houchardf73629d2017-04-05 22:33:04 +0200226/* Path to the unix socket we use to retrieve listener sockets from the old process */
227static const char *old_unixsocket;
228
William Lallemand85b0bd92017-06-01 17:38:53 +0200229static char *cur_unixsocket = NULL;
230
William Lallemandcb11fd22017-06-01 17:38:52 +0200231int atexit_flag = 0;
232
Willy Tarreaubb545b42010-08-25 12:58:59 +0200233int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234const int zero = 0;
235const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200236const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100238char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200239char *localpeer = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240
William Lallemand00417412020-06-05 14:08:41 +0200241static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200242
William Lallemandbc193052018-09-11 10:06:26 +0200243struct list proc_list = LIST_HEAD_INIT(proc_list);
244
245int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100246unsigned int rlim_fd_cur_at_boot = 0;
247unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200248
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100249/* per-boot randomness */
250unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
251
William Lallemandb3f2be32018-09-11 10:06:18 +0200252static void *run_thread_poll_loop(void *data);
253
Willy Tarreauff055502014-04-28 22:27:06 +0200254/* bitfield of a few warnings to emit just once (WARN_*) */
255unsigned int warned = 0;
256
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200257/* set if experimental features have been used for the current process */
258static unsigned int tainted = 0;
259
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200260unsigned int experimental_directives_allowed = 0;
261
262int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
263 char **errmsg)
264{
265 if (kw->flags & KWF_EXPERIMENTAL) {
266 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200267 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 +0200268 file, linenum, kw->kw);
269 return 1;
270 }
271 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
272 }
273
274 return 0;
275}
276
William Lallemande7361152018-10-26 14:47:36 +0200277/* master CLI configuration (-S flag) */
278struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100279
280/* These are strings to be reported in the output of "haproxy -vv". They may
281 * either be constants (in which case must_free must be zero) or dynamically
282 * allocated strings to pass to free() on exit, and in this case must_free
283 * must be non-zero.
284 */
285struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
286struct build_opts_str {
287 struct list list;
288 const char *str;
289 int must_free;
290};
291
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292/*********************************************************************/
293/* general purpose functions ***************************************/
294/*********************************************************************/
295
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100296/* used to register some build option strings at boot. Set must_free to
297 * non-zero if the string must be freed upon exit.
298 */
299void hap_register_build_opts(const char *str, int must_free)
300{
301 struct build_opts_str *b;
302
303 b = calloc(1, sizeof(*b));
304 if (!b) {
305 fprintf(stderr, "out of memory\n");
306 exit(1);
307 }
308 b->str = str;
309 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200310 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100311}
312
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200313#define VERSION_MAX_ELTS 7
314
315/* This function splits an haproxy version string into an array of integers.
316 * The syntax of the supported version string is the following:
317 *
318 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
319 *
320 * This validates for example:
321 * 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
322 * 2.4-dev18-f6818d-20
323 *
324 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
325 * one fixed place in the array. The tags take a numeric value called <e> which
326 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
327 * considered as zero (henxe 1.5 and 1.5.0 are the same).
328 *
329 * The resulting values are:
330 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
331 * 1.2.1 1, 2, 1, 0, 3, 0, 0
332 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
333 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
334 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
335 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
336 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
337 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
338 *
339 * The function returns non-zero if the conversion succeeded, or zero if it
340 * failed.
341 */
342int split_version(const char *version, unsigned int *value)
343{
344 const char *p, *s;
345 char *error;
346 int nelts;
347
348 /* Initialize array with zeroes */
349 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
350 value[nelts] = 0;
351 value[4] = 3;
352
353 p = version;
354
355 /* If the version number is empty, return false */
356 if (*p == '\0')
357 return 0;
358
359 /* Convert first number <a> */
360 value[0] = strtol(p, &error, 10);
361 p = error + 1;
362 if (*error == '\0')
363 return 1;
364 if (*error == '-')
365 goto split_version_tag;
366 if (*error != '.')
367 return 0;
368
369 /* Convert first number <b> */
370 value[1] = strtol(p, &error, 10);
371 p = error + 1;
372 if (*error == '\0')
373 return 1;
374 if (*error == '-')
375 goto split_version_tag;
376 if (*error != '.')
377 return 0;
378
379 /* Convert first number <c> */
380 value[2] = strtol(p, &error, 10);
381 p = error + 1;
382 if (*error == '\0')
383 return 1;
384 if (*error == '-')
385 goto split_version_tag;
386 if (*error != '.')
387 return 0;
388
389 /* Convert first number <d> */
390 value[3] = strtol(p, &error, 10);
391 p = error + 1;
392 if (*error == '\0')
393 return 1;
394 if (*error != '-')
395 return 0;
396
397 split_version_tag:
398 /* Check for commit number */
399 if (*p >= '0' && *p <= '9')
400 goto split_version_commit;
401
402 /* Read tag */
403 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
404 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
405 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
406 else
407 goto split_version_commit;
408
409 /* Convert tag number */
410 value[5] = strtol(p, &error, 10);
411 p = error + 1;
412 if (*error == '\0')
413 return 1;
414 if (*error != '-')
415 return 0;
416
417 split_version_commit:
418 /* Search the last "-" */
419 s = strrchr(p, '-');
420 if (s) {
421 s++;
422 if (*s == '\0')
423 return 0;
424 value[6] = strtol(s, &error, 10);
425 if (*error != '\0')
426 value[6] = 0;
427 return 1;
428 }
429
430 /* convert the version */
431 value[6] = strtol(p, &error, 10);
432 if (*error != '\0')
433 value[6] = 0;
434
435 return 1;
436}
437
438/* This function compares the current haproxy version with an arbitrary version
439 * string. It returns:
440 * -1 : the version in argument is older than the current haproxy version
441 * 0 : the version in argument is the same as the current haproxy version
442 * 1 : the version in argument is newer than the current haproxy version
443 *
444 * Or some errors:
445 * -2 : the current haproxy version is not parsable
446 * -3 : the version in argument is not parsable
447 */
448int compare_current_version(const char *version)
449{
450 unsigned int loc[VERSION_MAX_ELTS];
451 unsigned int mod[VERSION_MAX_ELTS];
452 int i;
453
454 /* split versions */
455 if (!split_version(haproxy_version, loc))
456 return -2;
457 if (!split_version(version, mod))
458 return -3;
459
460 /* compare versions */
461 for (i = 0; i < VERSION_MAX_ELTS; i++) {
462 if (mod[i] < loc[i])
463 return -1;
464 else if (mod[i] > loc[i])
465 return 1;
466 }
467 return 0;
468}
469
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100470static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200471{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200472 struct utsname utsname;
473
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200474 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100475 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100476
477 if (strlen(PRODUCT_URL_BUGS) > 0) {
478 char base_version[20];
479 int dots = 0;
480 char *del;
481
482 /* only retrieve the base version without distro-specific extensions */
483 for (del = haproxy_version; *del; del++) {
484 if (*del == '.')
485 dots++;
486 else if (*del < '0' || *del > '9')
487 break;
488 }
489
490 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
491 if (dots < 2)
492 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
493 else
494 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
495 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200496
497 if (uname(&utsname) == 0) {
498 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
499 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200500}
501
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100502static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100503{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100504 struct build_opts_str *item;
505
Willy Tarreau7b066db2007-12-02 11:28:59 +0100506 printf("Build options :"
507#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100508 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100509#endif
510#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100511 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100512#endif
513#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100514 "\n CC = " BUILD_CC
515#endif
516#ifdef BUILD_CFLAGS
517 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100518#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100519#ifdef BUILD_OPTIONS
520 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100521#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100522#ifdef BUILD_DEBUG
523 "\n DEBUG = " BUILD_DEBUG
524#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100525#ifdef BUILD_FEATURES
526 "\n\nFeature list : " BUILD_FEATURES
527#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200528 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100529 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200530 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100531 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200532
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100533 list_for_each_entry(item, &build_opts_list, list) {
534 puts(item->str);
535 }
536
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100537 putchar('\n');
538
Willy Tarreaube5b6852009-10-03 18:57:08 +0200539 list_pollers(stdout);
540 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200541 list_mux_proto(stdout);
542 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100543 list_services(stdout);
544 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100545 list_filters(stdout);
546 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100547}
548
Willy Tarreaubaaee002006-06-26 02:48:02 +0200549/*
550 * This function prints the command line usage and exits
551 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100552static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200553{
554 display_version();
555 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200556 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200557 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200558 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100559 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200560 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreau6e064432012-05-08 15:40:42 +0200561 " -dM[<byte>] poisons memory with <byte> (defaults to 0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200562 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200563 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200564 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100565#if defined(USE_SYSTEMD)
566 " -Ws master-worker mode with systemd notify support.\n"
567#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200568 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200569 " -c check mode : only check config files and exit\n"
Maximilian Maderfc0cceb2021-06-06 00:50:22 +0200570 " -cc check condition : evaluate a condition and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100571 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200572 " -m limits the usable amount of memory (in MB)\n"
573 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200574 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575 " -p writes pids of all children to this file\n"
Willy Tarreaue5733232019-05-22 19:24:06 +0200576#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 " -de disables epoll() usage even when available\n"
578#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200579#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200580 " -dk disables kqueue() usage even when available\n"
581#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200582#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000583 " -dv disables event ports usage even when available\n"
584#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200585#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200586 " -dp disables poll() usage even when available\n"
587#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200588#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100589 " -dS disables splice usage (broken on old kernels)\n"
590#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200591#if defined(USE_GETADDRINFO)
592 " -dG disables getaddrinfo() usage\n"
593#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000594#if defined(SO_REUSEPORT)
595 " -dR disables SO_REUSEPORT usage\n"
596#endif
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100597 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100598 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200599 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200600 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200601 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200602 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200603 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200604 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100605 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200606 exit(1);
607}
608
609
610
611/*********************************************************************/
612/* more specific functions ***************************************/
613/*********************************************************************/
614
William Lallemand73b85e72017-06-01 17:38:51 +0200615/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
616 * pids the signal was correctly delivered to.
617 */
William Lallemande25473c2019-04-01 11:29:56 +0200618int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200619{
620 int p;
621 int ret = 0;
622 for (p = 0; p < nb_oldpids; p++)
623 if (kill(oldpids[p], sig) == 0)
624 ret++;
625 return ret;
626}
627
William Lallemand75ea0a02017-11-15 19:02:58 +0100628/*
William Lallemand73b85e72017-06-01 17:38:51 +0200629 * remove a pid forom the olpid array and decrease nb_oldpids
630 * return 1 pid was found otherwise return 0
631 */
632
633int delete_oldpid(int pid)
634{
635 int i;
636
637 for (i = 0; i < nb_oldpids; i++) {
638 if (oldpids[i] == pid) {
639 oldpids[i] = oldpids[nb_oldpids - 1];
640 oldpids[nb_oldpids - 1] = 0;
641 nb_oldpids--;
642 return 1;
643 }
644 }
645 return 0;
646}
647
William Lallemand85b0bd92017-06-01 17:38:53 +0200648
649static void get_cur_unixsocket()
650{
651 /* if -x was used, try to update the stat socket if not available anymore */
Willy Tarreau4975d142021-03-13 11:00:33 +0100652 if (global.cli_fe) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200653 struct bind_conf *bind_conf;
654
655 /* pass through all stats socket */
Willy Tarreau4975d142021-03-13 11:00:33 +0100656 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200657 struct listener *l;
658
659 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
660
Willy Tarreau37159062020-08-27 07:48:42 +0200661 if (l->rx.addr.ss_family == AF_UNIX &&
William Lallemand85b0bd92017-06-01 17:38:53 +0200662 (bind_conf->level & ACCESS_FD_LISTENERS)) {
663 const struct sockaddr_un *un;
664
Willy Tarreau37159062020-08-27 07:48:42 +0200665 un = (struct sockaddr_un *)&l->rx.addr;
William Lallemand85b0bd92017-06-01 17:38:53 +0200666 /* priority to old_unixsocket */
667 if (!cur_unixsocket) {
668 cur_unixsocket = strdup(un->sun_path);
669 } else {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100670 if (old_unixsocket && strcmp(un->sun_path, old_unixsocket) == 0) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200671 free(cur_unixsocket);
672 cur_unixsocket = strdup(old_unixsocket);
673 return;
674 }
675 }
676 }
677 }
678 }
679 }
680 if (!cur_unixsocket && old_unixsocket)
681 cur_unixsocket = strdup(old_unixsocket);
682}
683
William Lallemand73b85e72017-06-01 17:38:51 +0200684/*
685 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800686 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200687 */
William Lallemanda57b7e32018-12-14 21:11:31 +0100688void mworker_reload()
William Lallemand73b85e72017-06-01 17:38:51 +0200689{
William Lallemand00417412020-06-05 14:08:41 +0200690 char **next_argv = NULL;
691 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200692 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200693 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200694 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100695 struct rlimit limit;
William Lallemand7c756a82018-11-26 11:53:40 +0100696 struct per_thread_deinit_fct *ptdf;
William Lallemand73b85e72017-06-01 17:38:51 +0200697
698 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100699#if defined(USE_SYSTEMD)
700 if (global.tune.options & GTUNE_USE_SYSTEMD)
701 sd_notify(0, "RELOADING=1");
702#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200703 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
704
William Lallemandbc193052018-09-11 10:06:26 +0200705 mworker_proc_list_to_env(); /* put the children description in the env */
706
William Lallemand7c756a82018-11-26 11:53:40 +0100707 /* during the reload we must ensure that every FDs that can't be
708 * reuse (ie those that are not referenced in the proc_list)
709 * are closed or they will leak. */
710
711 /* close the listeners FD */
712 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200713
714 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
715 /* close the poller FD and the thread waker pipe FD */
716 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
717 ptdf->fct();
718 if (fdtab)
719 deinit_pollers();
720 }
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500721#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200722 /* close random device FDs */
723 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100724#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100725
Willy Tarreau8dca1952019-03-01 10:21:55 +0100726 /* restore the initial FD limits */
727 limit.rlim_cur = rlim_fd_cur_at_boot;
728 limit.rlim_max = rlim_fd_max_at_boot;
729 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
730 getrlimit(RLIMIT_NOFILE, &limit);
731 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
732 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
733 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
734 }
735
William Lallemand73b85e72017-06-01 17:38:51 +0200736 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200737 while (old_argv[old_argc])
738 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200739
William Lallemand85b0bd92017-06-01 17:38:53 +0200740 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200741 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200742 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200743 if (next_argv == NULL)
744 goto alloc_error;
745
William Lallemand00417412020-06-05 14:08:41 +0200746 /* copy the program name */
747 next_argv[next_argc++] = old_argv[0];
748
749 /* insert the new options just after argv[0] in case we have a -- */
750
William Lallemand73b85e72017-06-01 17:38:51 +0200751 /* add -sf <PID>* to argv */
William Lallemand3f128872019-04-01 11:29:59 +0200752 if (mworker_child_nb() > 0) {
753 struct mworker_proc *child;
754
William Lallemand73b85e72017-06-01 17:38:51 +0200755 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200756
757 list_for_each_entry(child, &proc_list, list) {
William Lallemand677e2f22019-11-19 17:04:18 +0100758 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1 )
William Lallemand3f128872019-04-01 11:29:59 +0200759 continue;
William Lallemand00417412020-06-05 14:08:41 +0200760 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
William Lallemand73b85e72017-06-01 17:38:51 +0200761 goto alloc_error;
762 msg = NULL;
763 }
764 }
William Lallemand2bf6d622017-06-20 11:20:23 +0200765 /* add the -x option with the stat socket */
William Lallemand85b0bd92017-06-01 17:38:53 +0200766 if (cur_unixsocket) {
William Lallemand2bf6d622017-06-20 11:20:23 +0200767 next_argv[next_argc++] = "-x";
768 next_argv[next_argc++] = (char *)cur_unixsocket;
William Lallemand85b0bd92017-06-01 17:38:53 +0200769 }
770
William Lallemand00417412020-06-05 14:08:41 +0200771 /* copy the previous options */
772 for (i = 1; i < old_argc; i++)
773 next_argv[next_argc++] = old_argv[i];
774
Christopher Faulet767a84b2017-11-24 16:50:31 +0100775 ha_warning("Reexecuting Master process\n");
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200776 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100777 execvp(next_argv[0], next_argv);
William Lallemand73b85e72017-06-01 17:38:51 +0200778
Christopher Faulet767a84b2017-11-24 16:50:31 +0100779 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100780 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100781 return;
782
William Lallemand73b85e72017-06-01 17:38:51 +0200783alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100784 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800785 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200786 return;
787}
788
William Lallemandb3f2be32018-09-11 10:06:18 +0200789static void mworker_loop()
790{
791
792#if defined(USE_SYSTEMD)
793 if (global.tune.options & GTUNE_USE_SYSTEMD)
794 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
795#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200796 /* Busy polling makes no sense in the master :-) */
797 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200798
William Lallemandbc193052018-09-11 10:06:26 +0200799 master = 1;
800
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100801 signal_unregister(SIGTTIN);
802 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100803 signal_unregister(SIGUSR1);
804 signal_unregister(SIGHUP);
805 signal_unregister(SIGQUIT);
806
William Lallemandb3f2be32018-09-11 10:06:18 +0200807 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
808 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100809 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
810 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200811 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
812 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
813 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
814 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
815
816 mworker_unblock_signals();
817 mworker_cleanlisteners();
William Lallemand27f3fa52018-12-06 14:05:20 +0100818 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200819
William Lallemandbc193052018-09-11 10:06:26 +0200820 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
821 some SIGCHLD were lost */
822
William Lallemandb3f2be32018-09-11 10:06:18 +0200823 global.nbthread = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200824
William Lallemand2672eb92018-12-14 15:52:39 +0100825#ifdef USE_THREAD
826 tid_bit = 1;
827 all_threads_mask = 1;
828#endif
829
William Lallemandb3f2be32018-09-11 10:06:18 +0200830 jobs++; /* this is the "master" job, we want to take care of the
831 signals even if there is no listener so the poll loop don't
832 leave */
833
834 fork_poller();
Willy Tarreaub4f7cc32019-05-03 09:27:30 +0200835 run_thread_poll_loop(0);
William Lallemandb3f2be32018-09-11 10:06:18 +0200836}
William Lallemandcb11fd22017-06-01 17:38:52 +0200837
838/*
839 * Reexec the process in failure mode, instead of exiting
840 */
841void reexec_on_failure()
842{
843 if (!atexit_flag)
844 return;
845
846 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
847
Christopher Faulet767a84b2017-11-24 16:50:31 +0100848 ha_warning("Reexecuting Master process in waitpid mode\n");
William Lallemandcb11fd22017-06-01 17:38:52 +0200849 mworker_reload();
William Lallemandcb11fd22017-06-01 17:38:52 +0200850}
William Lallemand73b85e72017-06-01 17:38:51 +0200851
852
853/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200854 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
855 * a signal zero to all subscribers. This means that it's as easy as
856 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200857 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100858static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200859{
860 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200861 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100862 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200863}
864
865/*
866 * upon SIGTTOU, we pause everything
867 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100868static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200869{
Willy Tarreau775e0012020-09-24 16:36:26 +0200870 if (protocol_pause_all() & ERR_FATAL) {
871 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200872 ha_warning("%s", msg);
873 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200874 soft_stop();
875 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100876 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200877}
878
879/*
880 * upon SIGTTIN, let's have a soft stop.
881 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100882static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200883{
Willy Tarreau775e0012020-09-24 16:36:26 +0200884 if (protocol_resume_all() & ERR_FATAL) {
885 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 +0200886 ha_warning("%s", msg);
887 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200888 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200889}
890
891/*
892 * this function dumps every server's state when the process receives SIGHUP.
893 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100894static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100896 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897
Christopher Faulet767a84b2017-11-24 16:50:31 +0100898 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200899 while (p) {
900 struct server *s = p->srv;
901
902 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
903 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100904 chunk_printf(&trash,
905 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
906 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200907 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200908 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200909 ha_warning("%s\n", trash.area);
910 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200911 s = s->next;
912 }
913
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200914 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
915 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100916 chunk_printf(&trash,
917 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
918 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200919 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 +0200920 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100921 chunk_printf(&trash,
922 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
923 p->id,
924 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200925 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 +0200926 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100927 chunk_printf(&trash,
928 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
929 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
930 p->id, p->srv_act, p->srv_bck,
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 Tarreaubaaee002006-06-26 02:48:02 +0200932 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200933 ha_warning("%s\n", trash.area);
934 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200935
936 p = p->next;
937 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200938}
939
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100940static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200941{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200942 /* dump memory usage then free everything possible */
943 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100944 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945}
946
William Lallemande1340412017-12-28 16:09:36 +0100947/*
948 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
949 * If <fd> < 0, it opens /dev/null and use it to dup
950 *
951 * In the case of chrooting, you have to open /dev/null before the chroot, and
952 * pass the <fd> to this function
953 */
954static void stdio_quiet(int fd)
955{
956 if (fd < 0)
957 fd = open("/dev/null", O_RDWR, 0);
958
959 if (fd > -1) {
960 fclose(stdin);
961 fclose(stdout);
962 fclose(stderr);
963
964 dup2(fd, 0);
965 dup2(fd, 1);
966 dup2(fd, 2);
967 if (fd > 2)
968 close(fd);
969 return;
970 }
971
972 ha_alert("Cannot open /dev/null\n");
973 exit(EXIT_FAILURE);
974}
975
976
Joseph Herlant03420902018-11-15 10:41:50 -0800977/* This function checks if cfg_cfgfiles contains directories.
978 * If it finds one, it adds all the files (and only files) it contains
979 * in cfg_cfgfiles in place of the directory (and removes the directory).
980 * It adds the files in lexical order.
981 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200982 * It doesn't add files with name starting with '.'
983 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100984static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200985{
986 struct wordlist *wl, *wlb;
987 char *err = NULL;
988
989 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
990 struct stat file_stat;
991 struct dirent **dir_entries = NULL;
992 int dir_entries_nb;
993 int dir_entries_it;
994
995 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +0100996 ha_alert("Cannot open configuration file/directory %s : %s\n",
997 wl->s,
998 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200999 exit(1);
1000 }
1001
1002 if (!S_ISDIR(file_stat.st_mode))
1003 continue;
1004
1005 /* from this point wl->s is a directory */
1006
1007 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1008 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001009 ha_alert("Cannot open configuration directory %s : %s\n",
1010 wl->s,
1011 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001012 exit(1);
1013 }
1014
1015 /* for each element in the directory wl->s */
1016 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1017 struct dirent *dir_entry = dir_entries[dir_entries_it];
1018 char *filename = NULL;
1019 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1020
1021 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001022 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001023 */
1024 if (dir_entry->d_name[0] == '.' ||
1025 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1026 goto next_dir_entry;
1027
1028 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001029 ha_alert("Cannot load configuration files %s : out of memory.\n",
1030 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001031 exit(1);
1032 }
1033
1034 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001035 ha_alert("Cannot open configuration file %s : %s\n",
1036 wl->s,
1037 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001038 exit(1);
1039 }
1040
1041 /* don't add anything else than regular file in cfg_cfgfiles
1042 * this way we avoid loops
1043 */
1044 if (!S_ISREG(file_stat.st_mode))
1045 goto next_dir_entry;
1046
1047 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001048 ha_alert("Cannot load configuration files %s : %s\n",
1049 filename,
1050 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001051 exit(1);
1052 }
1053
1054next_dir_entry:
1055 free(filename);
1056 free(dir_entry);
1057 }
1058
1059 free(dir_entries);
1060
1061 /* remove the current directory (wl) from cfg_cfgfiles */
1062 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001063 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001064 free(wl);
1065 }
1066
1067 free(err);
1068}
1069
Willy Tarreaubaaee002006-06-26 02:48:02 +02001070/*
William Lallemand73b85e72017-06-01 17:38:51 +02001071 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001072 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001073 * Return an allocated copy of argv
1074 */
1075
1076static char **copy_argv(int argc, char **argv)
1077{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001078 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001079
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001080 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001081 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001082 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001083 return NULL;
1084 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001085 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001086
William Lallemanddf6c5a82020-06-04 17:40:23 +02001087 /* first copy argv[0] */
1088 *newargv++ = *argv++;
1089 argc--;
1090
1091 while (argc > 0) {
1092 if (**argv != '-') {
1093 /* non options are copied but will fail in the argument parser */
1094 *newargv++ = *argv++;
1095 argc--;
1096
1097 } else {
1098 char *flag;
1099
1100 flag = *argv + 1;
1101
1102 if (flag[0] == '-' && flag[1] == 0) {
1103 /* "--\0" copy every arguments till the end of argv */
1104 *newargv++ = *argv++;
1105 argc--;
1106
1107 while (argc > 0) {
1108 *newargv++ = *argv++;
1109 argc--;
1110 }
1111 } else {
1112 switch (*flag) {
1113 case 's':
1114 /* -sf / -st and their parameters are ignored */
1115 if (flag[1] == 'f' || flag[1] == 't') {
1116 argc--;
1117 argv++;
1118 /* The list can't contain a negative value since the only
1119 way to know the end of this list is by looking for the
1120 next option or the end of the options */
1121 while (argc > 0 && argv[0][0] != '-') {
1122 argc--;
1123 argv++;
1124 }
William Lallemand398da622020-09-02 16:12:23 +02001125 } else {
1126 argc--;
1127 argv++;
1128
William Lallemanddf6c5a82020-06-04 17:40:23 +02001129 }
1130 break;
1131
1132 case 'x':
1133 /* this option and its parameter are ignored */
1134 argc--;
1135 argv++;
1136 if (argc > 0) {
1137 argc--;
1138 argv++;
1139 }
1140 break;
1141
1142 case 'C':
1143 case 'n':
1144 case 'm':
1145 case 'N':
1146 case 'L':
1147 case 'f':
1148 case 'p':
1149 case 'S':
1150 /* these options have only 1 parameter which must be copied and can start with a '-' */
1151 *newargv++ = *argv++;
1152 argc--;
1153 if (argc == 0)
1154 goto error;
1155 *newargv++ = *argv++;
1156 argc--;
1157 break;
1158 default:
1159 /* for other options just copy them without parameters, this is also done
1160 * for options like "--foo", but this will fail in the argument parser.
1161 * */
1162 *newargv++ = *argv++;
1163 argc--;
1164 break;
1165 }
William Lallemand73b85e72017-06-01 17:38:51 +02001166 }
1167 }
William Lallemand73b85e72017-06-01 17:38:51 +02001168 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001169
William Lallemanddf6c5a82020-06-04 17:40:23 +02001170 return retargv;
1171
1172error:
1173 free(retargv);
1174 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001175}
1176
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001177
1178/* Performs basic random seed initialization. The main issue with this is that
1179 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1180 * which means that there will only be 4 billion possible random sequences once
1181 * srandom() is called, regardless of the internal state. Not calling it is
1182 * even worse as we'll always produce the same randoms sequences. What we do
1183 * here is to create an initial sequence from various entropy sources, hash it
1184 * using SHA1 and keep the resulting 160 bits available globally.
1185 *
1186 * We initialize the current process with the first 32 bits before starting the
1187 * polling loop, where all this will be changed to have process specific and
1188 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001189 *
1190 * Before starting threads, it's still possible to call random() as srandom()
1191 * is initialized from this, but after threads and/or processes are started,
1192 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001193 */
1194static void ha_random_boot(char *const *argv)
1195{
1196 unsigned char message[256];
1197 unsigned char *m = message;
1198 struct timeval tv;
1199 blk_SHA_CTX ctx;
1200 unsigned long l;
1201 int fd;
1202 int i;
1203
1204 /* start with current time as pseudo-random seed */
1205 gettimeofday(&tv, NULL);
1206 write_u32(m, tv.tv_sec); m += 4;
1207 write_u32(m, tv.tv_usec); m += 4;
1208
1209 /* PID and PPID add some OS-based randomness */
1210 write_u16(m, getpid()); m += 2;
1211 write_u16(m, getppid()); m += 2;
1212
1213 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1214 fd = open("/dev/urandom", O_RDONLY);
1215 if (fd >= 0) {
1216 i = read(fd, m, 20);
1217 if (i > 0)
1218 m += i;
1219 close(fd);
1220 }
1221
1222 /* take up to 160 bits bytes from openssl (non-blocking) */
1223#ifdef USE_OPENSSL
1224 if (RAND_bytes(m, 20) == 1)
1225 m += 20;
1226#endif
1227
1228 /* take 160 bits from existing random in case it was already initialized */
1229 for (i = 0; i < 5; i++) {
1230 write_u32(m, random());
1231 m += 4;
1232 }
1233
1234 /* stack address (benefit form operating system's ASLR) */
1235 l = (unsigned long)&m;
1236 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1237
1238 /* argv address (benefit form operating system's ASLR) */
1239 l = (unsigned long)&argv;
1240 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1241
1242 /* use tv_usec again after all the operations above */
1243 gettimeofday(&tv, NULL);
1244 write_u32(m, tv.tv_usec); m += 4;
1245
1246 /*
1247 * At this point, ~84-92 bytes have been used
1248 */
1249
1250 /* finish with the hostname */
1251 strncpy((char *)m, hostname, message + sizeof(message) - m);
1252 m += strlen(hostname);
1253
1254 /* total message length */
1255 l = m - message;
1256
1257 memset(&ctx, 0, sizeof(ctx));
1258 blk_SHA1_Init(&ctx);
1259 blk_SHA1_Update(&ctx, message, l);
1260 blk_SHA1_Final(boot_seed, &ctx);
1261
1262 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001263 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001264}
1265
Willy Tarreau5a023f02019-03-01 14:19:31 +01001266/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1267 * setting, and returns it. It may return -1 meaning "unlimited" if some
1268 * unlimited proxies have been found and the global.maxconn value is not yet
1269 * set. It may also return a value greater than maxconn if it's not yet set.
1270 * Note that a value of zero means there is no need for pipes. -1 is never
1271 * returned if global.maxconn is valid.
1272 */
1273static int compute_ideal_maxpipes()
1274{
1275 struct proxy *cur;
1276 int nbfe = 0, nbbe = 0;
1277 int unlimited = 0;
1278 int pipes;
1279 int max;
1280
1281 for (cur = proxies_list; cur; cur = cur->next) {
1282 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1283 if (cur->cap & PR_CAP_FE) {
1284 max = cur->maxconn;
1285 nbfe += max;
1286 if (!max) {
1287 unlimited = 1;
1288 break;
1289 }
1290 }
1291 if (cur->cap & PR_CAP_BE) {
1292 max = cur->fullconn ? cur->fullconn : global.maxconn;
1293 nbbe += max;
1294 if (!max) {
1295 unlimited = 1;
1296 break;
1297 }
1298 }
1299 }
1300 }
1301
1302 pipes = MAX(nbfe, nbbe);
1303 if (global.maxconn) {
1304 if (pipes > global.maxconn || unlimited)
1305 pipes = global.maxconn;
1306 } else if (unlimited) {
1307 pipes = -1;
1308 }
1309
1310 return pipes >= 4 ? pipes / 4 : pipes;
1311}
1312
Willy Tarreauac350932019-03-01 15:43:14 +01001313/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1314 * rlimits and computes an ideal maxconn. It's meant to be called only when
1315 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001316 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1317 * default 100) is returned as it is expected that it will even run on tight
1318 * environments, and will maintain compatibility with previous packages that
1319 * used to rely on this value as the default one. The system will emit a
1320 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001321 */
1322static int compute_ideal_maxconn()
1323{
1324 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1325 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1326 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001327 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001328 int maxconn;
1329
1330 /* we have to take into account these elements :
1331 * - number of engine_fds, which inflates the number of FD needed per
1332 * connection by this number.
1333 * - number of pipes per connection on average : for the unlimited
1334 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1335 * fixed value of 2*pipes.
1336 * - two FDs per connection
1337 */
1338
1339 /* subtract listeners and checks */
1340 remain -= global.maxsock;
1341
Willy Tarreau3f200852019-03-14 19:13:17 +01001342 /* one epoll_fd/kqueue_fd per thread */
1343 remain -= global.nbthread;
1344
1345 /* one wake-up pipe (2 fd) per thread */
1346 remain -= 2 * global.nbthread;
1347
Willy Tarreauac350932019-03-01 15:43:14 +01001348 /* Fixed pipes values : we only subtract them if they're not larger
1349 * than the remaining FDs because pipes are optional.
1350 */
1351 if (pipes >= 0 && pipes * 2 < remain)
1352 remain -= pipes * 2;
1353
1354 if (pipes < 0) {
1355 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1356 * = maxconn * (2 + 0.5 + engine_fds)
1357 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1358 */
1359 maxconn = 2 * remain / (5 + 2 * engine_fds);
1360 } else {
1361 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1362 * = maxconn * (2 + engine_fds)
1363 */
1364 maxconn = remain / (2 + engine_fds);
1365 }
1366
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001367 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001368}
1369
Willy Tarreaua409f302020-03-10 17:08:53 +01001370/* computes the estimated maxsock value for the given maxconn based on the
1371 * possibly set global.maxpipes and existing partial global.maxsock. It may
1372 * temporarily change global.maxconn for the time needed to propagate the
1373 * computations, and will reset it.
1374 */
1375static int compute_ideal_maxsock(int maxconn)
1376{
1377 int maxpipes = global.maxpipes;
1378 int maxsock = global.maxsock;
1379
1380
1381 if (!maxpipes) {
1382 int old_maxconn = global.maxconn;
1383
1384 global.maxconn = maxconn;
1385 maxpipes = compute_ideal_maxpipes();
1386 global.maxconn = old_maxconn;
1387 }
1388
1389 maxsock += maxconn * 2; /* each connection needs two sockets */
1390 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1391 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1392 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1393
1394 /* compute fd used by async engines */
1395 if (global.ssl_used_async_engines) {
1396 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1397
1398 maxsock += maxconn * sides * global.ssl_used_async_engines;
1399 }
1400 return maxsock;
1401}
1402
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001403/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001404 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1405 * value is accepted, non-zero otherwise. This is used to determine if an
1406 * automatic limit may be applied or not. When it is not, the caller knows that
1407 * the highest we can do is the rlim_max at boot. In case of error, we return
1408 * that the setting is possible, so that we defer the error processing to the
1409 * final stage in charge of enforcing this.
1410 */
1411static int check_if_maxsock_permitted(int maxsock)
1412{
1413 struct rlimit orig_limit, test_limit;
1414 int ret;
1415
1416 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1417 return 1;
1418
1419 /* don't go further if we can't even set to what we have */
1420 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1421 return 1;
1422
1423 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1424 test_limit.rlim_cur = test_limit.rlim_max;
1425 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1426
1427 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1428 return 1;
1429
1430 return ret == 0;
1431}
1432
Amaury Denoyelle484454d2021-05-05 16:18:45 +02001433void mark_tainted(const enum tainted_flags flag)
1434{
1435 HA_ATOMIC_OR(&tainted, flag);
1436}
1437
1438unsigned int get_tainted()
1439{
1440 int tainted_state;
1441 HA_ATOMIC_STORE(&tainted_state, tainted);
1442 return tainted_state;
1443}
Willy Tarreau304e17e2020-03-10 17:54:54 +01001444
William Lallemand73b85e72017-06-01 17:38:51 +02001445/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02001446 * This function initializes all the necessary variables. It only returns
1447 * if everything is OK. If something fails, it exits.
1448 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001449static void init(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450{
Willy Tarreaubaaee002006-06-26 02:48:02 +02001451 int arg_mode = 0; /* MODE_DEBUG, ... */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001452 char *tmp;
1453 char *cfg_pidfile = NULL;
Willy Tarreau058e9072009-07-20 09:30:05 +02001454 int err_code = 0;
Maxime de Roucy0f503922016-05-13 23:52:55 +02001455 char *err_msg = NULL;
Willy Tarreau477ecd82010-01-03 21:12:30 +01001456 struct wordlist *wl;
Kevinm48936af2010-12-22 16:08:21 +00001457 char *progname;
Willy Tarreau576132e2011-09-10 19:26:56 +02001458 char *change_dir = NULL;
Christopher Fauletd7c91962015-04-30 11:48:27 +02001459 struct proxy *px;
Willy Tarreaue6945732016-12-21 19:57:00 +01001460 struct post_check_fct *pcf;
Willy Tarreauac350932019-03-01 15:43:14 +01001461 int ideal_maxconn;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001462 char *check_condition = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001463
Christopher Faulete3a5e352017-10-24 13:53:54 +02001464 global.mode = MODE_STARTING;
William Lallemand00417412020-06-05 14:08:41 +02001465 old_argv = copy_argv(argc, argv);
1466 if (!old_argv) {
William Lallemanddf6c5a82020-06-04 17:40:23 +02001467 ha_alert("failed to copy argv.\n");
1468 exit(1);
1469 }
William Lallemand73b85e72017-06-01 17:38:51 +02001470
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001471 if (!init_trash_buffers(1)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001472 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet748919a2017-07-26 14:59:46 +02001473 exit(1);
1474 }
David du Colombier7af46052012-05-16 14:16:48 +02001475
Emeric Brun2b920a12010-09-23 18:30:22 +02001476 /* NB: POSIX does not make it mandatory for gethostname() to NULL-terminate
1477 * the string in case of truncation, and at least FreeBSD appears not to do
1478 * it.
1479 */
1480 memset(hostname, 0, sizeof(hostname));
1481 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001482
1483 if ((localpeer = strdup(hostname)) == NULL) {
1484 ha_alert("Cannot allocate memory for local peer.\n");
1485 exit(EXIT_FAILURE);
1486 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001487 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Emeric Brun2b920a12010-09-23 18:30:22 +02001488
William Lallemand24c928c2020-01-14 17:58:18 +01001489 /* we were in mworker mode, we should restart in mworker mode */
1490 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1491 global.mode |= MODE_MWORKER;
1492
Willy Tarreaubaaee002006-06-26 02:48:02 +02001493 /*
1494 * Initialize the previously static variables.
1495 */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001496
Willy Tarreau173d9952018-01-26 21:48:23 +01001497 totalconn = actconn = listeners = stopping = 0;
Cyril Bonté203ec5a2017-03-23 22:44:13 +01001498 killed = 0;
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001499
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500
1501#ifdef HAPROXY_MEMMAX
Willy Tarreau70060452015-12-14 12:46:07 +01001502 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001503#endif
1504
Benoit GARNIERb413c2a2016-03-27 11:08:03 +02001505 tzset();
Willy Tarreauc4c80fb2021-04-11 15:00:34 +02001506 tv_init_process_date();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001507 start_date = now;
1508
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001509 ha_random_boot(argv);
Willy Tarreau84310e22014-02-14 11:59:04 +01001510
Willy Tarreau8ed669b2013-01-11 15:49:37 +01001511 if (init_acl() != 0)
1512 exit(1);
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001513
Amaury Denoyellec593bcd2021-05-19 15:35:29 +02001514#ifdef USE_OPENSSL
1515 /* Initialize the random generator.
1516 * Must be called before chroot for access to /dev/urandom
1517 */
1518 if (!ssl_initialize_random()) {
1519 ha_alert("OpenSSL random data generator initialization failed.\n");
1520 exit(1);
1521 }
1522#endif
1523
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001524 /* Initialise lua. */
1525 hlua_init();
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001526
Christopher Fauletff2613e2016-11-09 11:36:17 +01001527 /* Initialize process vars */
Willy Tarreaucfc4f242021-05-08 11:41:28 +02001528 vars_init(&proc_vars, SCOPE_PROC);
Christopher Fauletff2613e2016-11-09 11:36:17 +01001529
Willy Tarreau43b78992009-01-25 15:42:27 +01001530 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001531#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001532 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001533#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001534#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001535 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001536#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001537#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001538 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001539#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001540#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001541 global.tune.options |= GTUNE_USE_EVPORTS;
1542#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001543#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001544 global.tune.options |= GTUNE_USE_SPLICE;
1545#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001546#if defined(USE_GETADDRINFO)
1547 global.tune.options |= GTUNE_USE_GAI;
1548#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001549#if defined(SO_REUSEPORT)
1550 global.tune.options |= GTUNE_USE_REUSEPORT;
1551#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001552#ifdef USE_THREAD
1553 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1554#endif
William Dauchya5194602020-03-28 19:29:58 +01001555 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001556
1557 pid = getpid();
1558 progname = *argv;
1559 while ((tmp = strchr(progname, '/')) != NULL)
1560 progname = tmp + 1;
1561
Kevinm48936af2010-12-22 16:08:21 +00001562 /* the process name is used for the logs only */
Eric Salama7cea6062020-10-02 11:58:19 +02001563 chunk_initlen(&global.log_tag, strdup(progname), strlen(progname), strlen(progname));
1564 if (b_orig(&global.log_tag) == NULL) {
1565 chunk_destroy(&global.log_tag);
1566 ha_alert("Cannot allocate memory for log_tag.\n");
1567 exit(EXIT_FAILURE);
1568 }
Kevinm48936af2010-12-22 16:08:21 +00001569
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 argc--; argv++;
1571 while (argc > 0) {
1572 char *flag;
1573
1574 if (**argv == '-') {
1575 flag = *argv+1;
1576
1577 /* 1 arg */
1578 if (*flag == 'v') {
1579 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001580 if (flag[1] == 'v') /* -vv */
1581 display_build_opts();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001582 exit(0);
1583 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001584#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001585 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001586 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001588#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001590 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001592#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001593 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001594 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001595#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001596#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001597 else if (*flag == 'd' && flag[1] == 'v')
1598 global.tune.options &= ~GTUNE_USE_EVPORTS;
1599#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001600#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001601 else if (*flag == 'd' && flag[1] == 'S')
1602 global.tune.options &= ~GTUNE_USE_SPLICE;
1603#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001604#if defined(USE_GETADDRINFO)
1605 else if (*flag == 'd' && flag[1] == 'G')
1606 global.tune.options &= ~GTUNE_USE_GAI;
1607#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001608#if defined(SO_REUSEPORT)
1609 else if (*flag == 'd' && flag[1] == 'R')
1610 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1611#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001612 else if (*flag == 'd' && flag[1] == 'V')
1613 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001614 else if (*flag == 'V')
1615 arg_mode |= MODE_VERBOSE;
1616 else if (*flag == 'd' && flag[1] == 'b')
1617 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001618 else if (*flag == 'd' && flag[1] == 'D')
1619 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001620 else if (*flag == 'd' && flag[1] == 'W')
1621 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreau6e064432012-05-08 15:40:42 +02001622 else if (*flag == 'd' && flag[1] == 'M')
1623 mem_poison_byte = flag[2] ? strtol(flag + 2, NULL, 0) : 'P';
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001624 else if (*flag == 'd' && flag[1] == 'r')
1625 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001626 else if (*flag == 'd')
1627 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001628 else if (*flag == 'c' && flag[1] == 'c') {
1629 arg_mode |= MODE_CHECK_CONDITION;
1630 argv++;
1631 argc--;
1632 check_condition = *argv;
1633 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001634 else if (*flag == 'c')
1635 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001636 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001637 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001638 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001639 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001640#if defined(USE_SYSTEMD)
1641 global.tune.options |= GTUNE_USE_SYSTEMD;
1642#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001643 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 +01001644 usage(progname);
1645#endif
1646 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001647 else if (*flag == 'W')
1648 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001649 else if (*flag == 'q')
1650 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001651 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001652 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001653 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001654 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001655 }
William Lallemand4fc09692017-06-19 16:37:19 +02001656 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001657 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001658 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001659
Olivier Houchardf73629d2017-04-05 22:33:04 +02001660 argv++;
1661 argc--;
1662 }
William Lallemande7361152018-10-26 14:47:36 +02001663 else if (*flag == 'S') {
1664 struct wordlist *c;
1665
William Lallemanda6b32492020-06-04 23:49:20 +02001666 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001667 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1668 usage(progname);
1669 }
1670 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1671 ha_alert("Cannot allocate memory\n");
1672 exit(EXIT_FAILURE);
1673 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001674 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001675
1676 argv++;
1677 argc--;
1678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001679 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1680 /* list of pids to finish ('f') or terminate ('t') */
1681
1682 if (flag[1] == 'f')
1683 oldpids_sig = SIGUSR1; /* finish then exit */
1684 else
1685 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001686 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001687 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001688 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1689 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001690 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001691 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001692 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001693 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001694 errno = 0;
1695 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1696 if (errno) {
1697 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1698 flag,
1699 *argv, strerror(errno));
1700 exit(1);
1701 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001702 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001703 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001704 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1705 flag, endptr);
1706 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001707 }
Chris Lane236062f2018-02-05 23:15:44 +00001708 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001709 if (oldpids[nb_oldpids] <= 0)
1710 usage(progname);
1711 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 }
1713 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001714 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1715 /* now that's a cfgfile list */
1716 argv++; argc--;
1717 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001718 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001719 ha_alert("Cannot load configuration file/directory %s : %s\n",
1720 *argv,
1721 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001722 exit(1);
1723 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001724 argv++; argc--;
1725 }
1726 break;
1727 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001728 else { /* >=2 args */
1729 argv++; argc--;
1730 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001731 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001732
1733 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001734 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001735 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001736 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001737 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001738 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001739 free(localpeer);
1740 if ((localpeer = strdup(*argv)) == NULL) {
1741 ha_alert("Cannot allocate memory for local peer.\n");
1742 exit(EXIT_FAILURE);
1743 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001744 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001745 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001746 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001747 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001748 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001749 ha_alert("Cannot load configuration file/directory %s : %s\n",
1750 *argv,
1751 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001752 exit(1);
1753 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001754 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001755 case 'p' : cfg_pidfile = *argv; break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001756 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001757 }
1758 }
1759 }
1760 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001761 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001762 argv++; argc--;
1763 }
1764
Christopher Faulete3a5e352017-10-24 13:53:54 +02001765 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001766 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001767 | MODE_DIAG | MODE_CHECK_CONDITION));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001768
William Lallemand944e6192018-11-21 15:48:31 +01001769 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001770 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001771 global.mode |= MODE_MWORKER_WAIT;
1772 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001773 }
1774
Willy Tarreau26146192021-07-21 10:01:36 +02001775 if ((global.mode & (MODE_MWORKER | MODE_CHECK | MODE_CHECK_CONDITION)) == MODE_MWORKER &&
1776 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001777 atexit_flag = 1;
1778 atexit(reexec_on_failure);
1779 }
1780
Willy Tarreau576132e2011-09-10 19:26:56 +02001781 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001782 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001783 exit(1);
1784 }
1785
Willy Tarreaubaaee002006-06-26 02:48:02 +02001786 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001787
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001788#ifdef USE_CPU_AFFINITY
1789 {
1790 int i;
Willy Tarreau44ea6312021-06-15 08:57:56 +02001791 ha_cpuset_zero(&cpu_map.proc);
1792 ha_cpuset_zero(&cpu_map.proc_t1);
Willy Tarreau26f42a02021-05-14 08:26:38 +02001793 for (i = 0; i < MAX_THREADS; ++i) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02001794 ha_cpuset_zero(&cpu_map.thread[i]);
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001795 }
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001796 }
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001797#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001798
Amaury Denoyelle11124302021-06-04 18:22:08 +02001799 usermsgs_clr("config");
1800
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001801 if (global.mode & MODE_CHECK_CONDITION) {
1802 int result;
1803
1804 uint32_t err;
1805 const char *errptr;
1806 char *errmsg = NULL;
1807
1808 char *args[MAX_LINE_ARGS+1];
1809 int arg = sizeof(args) / sizeof(*args);
1810 size_t outlen = strlen(check_condition) + 1;
Willy Tarreauc8194c32021-07-16 16:38:58 +02001811 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001812
1813 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02001814 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001815 &errptr);
1816
1817 if (err & PARSE_ERR_QUOTE) {
1818 ha_alert("Syntax Error in condition: Unmatched quote.\n");
1819 exit(2);
1820 }
1821
1822 if (err & PARSE_ERR_HEX) {
1823 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
1824 exit(2);
1825 }
1826
1827 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
1828 ha_alert("Error in condition: Line too long.\n");
1829 exit(2);
1830 }
1831
Willy Tarreauc8194c32021-07-16 16:38:58 +02001832 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001833 ha_alert("Error in condition: Too many words.\n");
1834 exit(2);
1835 }
1836
1837 if (err) {
1838 ha_alert("Unhandled error in condition, please report this to the developers.\n");
1839 exit(2);
1840 }
1841
Willy Tarreauc8194c32021-07-16 16:38:58 +02001842 /* remerge all words into a single expression */
1843 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
1844 ;
1845
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001846 result = cfg_eval_condition(args, &errmsg, &errptr);
1847
1848 if (result < 0) {
1849 if (errmsg)
1850 ha_alert("Failed to evaluate condition: %s\n", errmsg);
1851
1852 exit(2);
1853 }
1854
1855 exit(result ? 0 : 1);
1856 }
1857
William Lallemand944e6192018-11-21 15:48:31 +01001858 /* in wait mode, we don't try to read the configuration files */
1859 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001860 char *env_cfgfiles = NULL;
1861 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001862
William Lallemand944e6192018-11-21 15:48:31 +01001863 /* handle cfgfiles that are actually directories */
1864 cfgfiles_expand_directories();
1865
1866 if (LIST_ISEMPTY(&cfg_cfgfiles))
1867 usage(progname);
1868
1869
1870 list_for_each_entry(wl, &cfg_cfgfiles, list) {
1871 int ret;
1872
Christopher Faulet4e366822021-01-12 18:57:38 +01001873 if (env_err == 0) {
1874 if (!memprintf(&env_cfgfiles, "%s%s%s",
1875 (env_cfgfiles ? env_cfgfiles : ""),
1876 (env_cfgfiles ? ";" : ""), wl->s))
1877 env_err = 1;
1878 }
William Lallemand7b302d82019-05-20 11:15:37 +02001879
William Lallemand944e6192018-11-21 15:48:31 +01001880 ret = readcfgfile(wl->s);
1881 if (ret == -1) {
1882 ha_alert("Could not open configuration file %s : %s\n",
1883 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01001884 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001885 exit(1);
1886 }
1887 if (ret & (ERR_ABORT|ERR_FATAL))
1888 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
1889 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01001890 if (err_code & ERR_ABORT) {
1891 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001892 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01001893 }
Willy Tarreauc4382422009-12-06 13:10:44 +01001894 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001895
William Lallemand944e6192018-11-21 15:48:31 +01001896 /* do not try to resolve arguments nor to spot inconsistencies when
1897 * the configuration contains fatal errors caused by files not found
1898 * or failed memory allocations.
1899 */
1900 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1901 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01001902 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001903 exit(1);
1904 }
Christopher Faulet4e366822021-01-12 18:57:38 +01001905 if (env_err) {
1906 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
1907 exit(1);
1908 }
1909 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
1910 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02001911
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02001912 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001913 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01001914 struct mworker_proc *tmproc;
1915
William Lallemand482f9a92019-04-12 16:15:00 +02001916 setenv("HAPROXY_MWORKER", "1", 1);
1917
William Lallemand16dd1b32018-11-19 18:46:18 +01001918 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
1919
William Lallemandf3a86832019-04-01 11:29:58 +02001920 tmproc = calloc(1, sizeof(*tmproc));
William Lallemand16dd1b32018-11-19 18:46:18 +01001921 if (!tmproc) {
1922 ha_alert("Cannot allocate process structures.\n");
1923 exit(EXIT_FAILURE);
1924 }
William Lallemand8f7069a2019-04-12 16:09:23 +02001925 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01001926 tmproc->reloads = 0;
William Lallemand16dd1b32018-11-19 18:46:18 +01001927 tmproc->pid = pid;
1928 tmproc->timestamp = start_date.tv_sec;
1929 tmproc->ipc_fd[0] = -1;
1930 tmproc->ipc_fd[1] = -1;
1931
1932 proc_self = tmproc;
1933
Willy Tarreau2b718102021-04-21 07:32:39 +02001934 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01001935 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001936
Willy Tarreau6185a032021-06-15 08:02:06 +02001937 tmproc = calloc(1, sizeof(*tmproc));
1938 if (!tmproc) {
1939 ha_alert("Cannot allocate process structures.\n");
1940 exit(EXIT_FAILURE);
1941 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001942
Willy Tarreau6185a032021-06-15 08:02:06 +02001943 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
1944 tmproc->pid = -1;
1945 tmproc->reloads = 0;
1946 tmproc->timestamp = -1;
Willy Tarreau6185a032021-06-15 08:02:06 +02001947 tmproc->ipc_fd[0] = -1;
1948 tmproc->ipc_fd[1] = -1;
William Lallemandce83b4a2018-10-26 14:47:30 +02001949
Willy Tarreau6185a032021-06-15 08:02:06 +02001950 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
1951 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02001952 }
Willy Tarreau6185a032021-06-15 08:02:06 +02001953
1954 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01001955 }
1956 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
1957 struct wordlist *it, *c;
1958
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02001959 /* get the info of the children in the env */
1960 if (mworker_env_to_proc_list() < 0) {
1961 exit(EXIT_FAILURE);
1962 }
William Lallemande7361152018-10-26 14:47:36 +02001963
William Lallemand550db6d2018-11-06 17:37:12 +01001964 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02001965
William Lallemand550db6d2018-11-06 17:37:12 +01001966 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02001967 ha_alert("Can't create the master's CLI.\n");
1968 exit(EXIT_FAILURE);
1969 }
William Lallemande7361152018-10-26 14:47:36 +02001970
William Lallemand550db6d2018-11-06 17:37:12 +01001971 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
1972
1973 if (mworker_cli_proxy_new_listener(c->s) < 0) {
1974 ha_alert("Can't create the master's CLI.\n");
1975 exit(EXIT_FAILURE);
1976 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001977 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01001978 free(c->s);
1979 free(c);
1980 }
1981 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001982 }
1983
Eric Salama5ba83352021-03-16 15:11:17 +01001984 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
1985 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
1986 }
1987
Willy Tarreaue90904d2021-02-12 14:08:31 +01001988 /* defaults sections are not needed anymore */
1989 proxy_destroy_all_defaults();
1990
Willy Tarreaubb925012009-07-23 13:36:36 +02001991 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02001992 for (px = proxies_list; px; px = px->next) {
1993 struct server *srv;
1994 struct post_proxy_check_fct *ppcf;
1995 struct post_server_check_fct *pscf;
1996
Christopher Fauletd5bd8242020-11-02 16:20:13 +01001997 if (px->disabled)
1998 continue;
1999
Christopher Fauletc1692962019-08-12 09:51:07 +02002000 list_for_each_entry(pscf, &post_server_check_list, list) {
2001 for (srv = px->srv; srv; srv = srv->next)
2002 err_code |= pscf->fct(srv);
2003 }
2004 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2005 err_code |= ppcf->fct(px);
2006 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002007 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002008 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002009 exit(1);
2010 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002011
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002012 err_code |= pattern_finalize_config();
2013 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2014 ha_alert("Failed to finalize pattern config.\n");
2015 exit(1);
2016 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002017
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002018 if (global.rlimit_memmax_all)
2019 global.rlimit_memmax = global.rlimit_memmax_all;
2020
Willy Tarreaue5733232019-05-22 19:24:06 +02002021#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002022 err_code |= netns_init();
2023 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002024 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002025 exit(1);
2026 }
2027#endif
2028
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002029 /* Apply server states */
2030 apply_server_state();
2031
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002032 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002033 srv_compute_all_admin_states(px);
2034
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002035 /* Apply servers' configured address */
2036 err_code |= srv_init_addr();
2037 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002038 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002039 exit(1);
2040 }
2041
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002042 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2043 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2044 exit(1);
2045 }
2046
Willy Tarreaubaaee002006-06-26 02:48:02 +02002047 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002048 struct peers *pr;
2049 struct proxy *px;
2050
Willy Tarreaubebd2122020-04-15 16:06:11 +02002051 if (warned & WARN_ANY)
2052 qfprintf(stdout, "Warnings were found.\n");
2053
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002054 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002055 if (pr->peers_fe)
2056 break;
2057
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002058 for (px = proxies_list; px; px = px->next)
Willy Tarreauc3914d42020-09-24 08:39:22 +02002059 if (!px->disabled && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002060 break;
2061
2062 if (pr || px) {
2063 /* At least one peer or one listener has been found */
2064 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002065 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002066 }
2067 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2068 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002069 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002070
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002071 if (global.mode & MODE_DIAG) {
2072 cfg_run_diagnostics();
2073 }
2074
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002075 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002076 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002077
Willy Tarreaue6945732016-12-21 19:57:00 +01002078 list_for_each_entry(pcf, &post_check_list, list) {
2079 err_code |= pcf->fct();
2080 if (err_code & (ERR_ABORT|ERR_FATAL))
2081 exit(1);
2082 }
2083
Willy Tarreaubaaee002006-06-26 02:48:02 +02002084 if (cfg_maxconn > 0)
2085 global.maxconn = cfg_maxconn;
2086
Willy Tarreau4975d142021-03-13 11:00:33 +01002087 if (global.cli_fe)
2088 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002089
2090 if (cfg_peers) {
2091 /* peers also need to bypass global maxconn */
2092 struct peers *p = cfg_peers;
2093
2094 for (p = cfg_peers; p; p = p->next)
2095 if (p->peers_fe)
2096 global.maxsock += p->peers_fe->maxconn;
2097 }
2098
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099 if (cfg_pidfile) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002100 free(global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002101 global.pidfile = strdup(cfg_pidfile);
2102 }
2103
Willy Tarreaud0256482015-01-15 21:45:22 +01002104 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002105 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2106 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2107 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2108 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002109 *
2110 * If memmax is set, then it depends on which values are set. If
2111 * maxsslconn is set, we use memmax to determine how many cleartext
2112 * connections may be added, and set maxconn to the sum of the two.
2113 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2114 * the remaining amount of memory between memmax and the cleartext
2115 * connections. If neither are set, then it is considered that all
2116 * connections are SSL-capable, and maxconn is computed based on this,
2117 * then maxsslconn accordingly. We need to know if SSL is used on the
2118 * frontends, backends, or both, because when it's used on both sides,
2119 * we need twice the value for maxsslconn, but we only count the
2120 * handshake once since it is not performed on the two sides at the
2121 * same time (frontend-side is terminated before backend-side begins).
2122 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002123 * ssl_handshake_cost during its initialization. In any case, if
2124 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2125 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002126 */
Willy Tarreauac350932019-03-01 15:43:14 +01002127 ideal_maxconn = compute_ideal_maxconn();
2128
Willy Tarreaud0256482015-01-15 21:45:22 +01002129 if (!global.rlimit_memmax) {
2130 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002131 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002132 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2133 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2134 }
2135 }
2136#ifdef USE_OPENSSL
2137 else if (!global.maxconn && !global.maxsslconn &&
2138 (global.ssl_used_frontend || global.ssl_used_backend)) {
2139 /* memmax is set, compute everything automatically. Here we want
2140 * to ensure that all SSL connections will be served. We take
2141 * care of the number of sides where SSL is used, and consider
2142 * the worst case : SSL used on both sides and doing a handshake
2143 * simultaneously. Note that we can't have more than maxconn
2144 * handshakes at a time by definition, so for the worst case of
2145 * two SSL conns per connection, we count a single handshake.
2146 */
2147 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2148 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002149 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002150
2151 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2152 mem -= global.maxzlibmem;
2153 mem = mem * MEM_USABLE_RATIO;
2154
Willy Tarreau304e17e2020-03-10 17:54:54 +01002155 /* Principle: we test once to set maxconn according to the free
2156 * memory. If it results in values the system rejects, we try a
2157 * second time by respecting rlim_fd_max. If it fails again, we
2158 * go back to the initial value and will let the final code
2159 * dealing with rlimit report the error. That's up to 3 attempts.
2160 */
2161 do {
2162 global.maxconn = mem /
2163 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2164 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2165 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002166
Willy Tarreau304e17e2020-03-10 17:54:54 +01002167 if (retried == 1)
2168 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2169 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002170#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002171 if (global.maxconn > SYSTEM_MAXCONN)
2172 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002173#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002174 global.maxsslconn = sides * global.maxconn;
2175
2176 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2177 break;
2178 } while (retried++ < 2);
2179
Willy Tarreaud0256482015-01-15 21:45:22 +01002180 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2181 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2182 global.maxconn, global.maxsslconn);
2183 }
2184 else if (!global.maxsslconn &&
2185 (global.ssl_used_frontend || global.ssl_used_backend)) {
2186 /* memmax and maxconn are known, compute maxsslconn automatically.
2187 * maxsslconn being forced, we don't know how many of it will be
2188 * on each side if both sides are being used. The worst case is
2189 * when all connections use only one SSL instance because
2190 * handshakes may be on two sides at the same time.
2191 */
2192 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2193 int64_t mem = global.rlimit_memmax * 1048576ULL;
2194 int64_t sslmem;
2195
2196 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2197 mem -= global.maxzlibmem;
2198 mem = mem * MEM_USABLE_RATIO;
2199
Willy Tarreau87b09662015-04-03 00:22:06 +02002200 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002201 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2202 global.maxsslconn = round_2dig(global.maxsslconn);
2203
2204 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002205 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2206 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2207 "without SSL is %d, but %d was found and SSL is in use.\n",
2208 global.rlimit_memmax,
2209 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2210 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002211 exit(1);
2212 }
2213
2214 if (global.maxsslconn > sides * global.maxconn)
2215 global.maxsslconn = sides * global.maxconn;
2216
2217 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2218 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2219 }
2220#endif
2221 else if (!global.maxconn) {
2222 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2223 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2224 int64_t mem = global.rlimit_memmax * 1048576ULL;
2225 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002226 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002227
2228 if (global.ssl_used_frontend || global.ssl_used_backend)
2229 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2230
2231 mem -= global.maxzlibmem;
2232 mem = mem * MEM_USABLE_RATIO;
2233
2234 clearmem = mem;
2235 if (sides)
2236 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2237
Willy Tarreau304e17e2020-03-10 17:54:54 +01002238 /* Principle: we test once to set maxconn according to the free
2239 * memory. If it results in values the system rejects, we try a
2240 * second time by respecting rlim_fd_max. If it fails again, we
2241 * go back to the initial value and will let the final code
2242 * dealing with rlimit report the error. That's up to 3 attempts.
2243 */
2244 do {
2245 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2246 if (retried == 1)
2247 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2248 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002249#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002250 if (global.maxconn > SYSTEM_MAXCONN)
2251 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002252#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002253
Willy Tarreau304e17e2020-03-10 17:54:54 +01002254 if (clearmem <= 0 || !global.maxconn) {
2255 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2256 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2257 "is %d, but %d was found.\n",
2258 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002259 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002260 global.maxsslconn);
2261 exit(1);
2262 }
2263
2264 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2265 break;
2266 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002267
2268 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2269 if (sides && global.maxsslconn > sides * global.maxconn) {
2270 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2271 "to be limited to %d. Better reduce global.maxsslconn to get more "
2272 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2273 }
2274 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2275 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002276 }
2277
Willy Tarreaua409f302020-03-10 17:08:53 +01002278 global.maxsock = compute_ideal_maxsock(global.maxconn);
2279 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002280 if (!global.maxpipes)
2281 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002282
Olivier Houchard88698d92019-04-16 19:07:22 +02002283 /* update connection pool thresholds */
2284 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2285 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2286
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002287 proxy_adjust_all_maxconn();
2288
Willy Tarreau1db37712007-06-03 17:16:49 +02002289 if (global.tune.maxpollevents <= 0)
2290 global.tune.maxpollevents = MAX_POLL_EVENTS;
2291
Willy Tarreau060a7612021-03-10 11:06:26 +01002292 if (global.tune.runqueue_depth <= 0) {
2293 /* tests on various thread counts from 1 to 64 have shown an
2294 * optimal queue depth following roughly 1/sqrt(threads).
2295 */
2296 int s = my_flsl(global.nbthread);
2297 s += (global.nbthread / s); // roughly twice the sqrt.
2298 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2299 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002300
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002301 if (global.tune.recv_enough == 0)
2302 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2303
Willy Tarreau27a674e2009-08-17 07:23:33 +02002304 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2305 global.tune.maxrewrite = global.tune.bufsize / 2;
2306
Amaury Denoyelle11124302021-06-04 18:22:08 +02002307 usermsgs_clr(NULL);
2308
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2310 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002311 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002312 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2313 }
2314
William Lallemand095ba4c2017-06-01 17:38:50 +02002315 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002316 /* command line daemon mode inhibits foreground and debug modes mode */
2317 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002318 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002320
2321 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002322
William Lallemand095ba4c2017-06-01 17:38:50 +02002323 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002324 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002325 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002326 }
2327
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002328 if (global.nbthread < 1)
2329 global.nbthread = 1;
2330
Christopher Faulet3ef26392017-08-29 16:46:57 +02002331 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002332 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002333 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002334 exit(1);
2335 }
2336
Christopher Faulet96d44832017-11-14 22:02:30 +01002337 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002338 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002339 exit(1);
2340 }
2341
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002342 /*
2343 * Note: we could register external pollers here.
2344 * Built-in pollers have been registered before main().
2345 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002346
Willy Tarreau43b78992009-01-25 15:42:27 +01002347 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002348 disable_poller("kqueue");
2349
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002350 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2351 disable_poller("evports");
2352
Willy Tarreau43b78992009-01-25 15:42:27 +01002353 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002354 disable_poller("epoll");
2355
Willy Tarreau43b78992009-01-25 15:42:27 +01002356 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002357 disable_poller("poll");
2358
Willy Tarreau43b78992009-01-25 15:42:27 +01002359 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002360 disable_poller("select");
2361
2362 /* Note: we could disable any poller by name here */
2363
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002364 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002365 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002366 fprintf(stderr, "\n");
2367 list_filters(stderr);
2368 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002369
Willy Tarreau4f60f162007-04-08 16:39:58 +02002370 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002371 ha_alert("No polling mechanism available.\n"
2372 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2373 " is too low on this platform to support maxconn and the number of listeners\n"
2374 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2375 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2376 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2377 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2378 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2379 " check build settings using 'haproxy -vv'.\n\n",
2380 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002381 exit(1);
2382 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002383 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2384 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002385 }
2386
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002387 if (!global.node)
2388 global.node = strdup(hostname);
2389
Willy Tarreau02b092f2020-10-07 18:36:54 +02002390 /* stop disabled proxies */
2391 for (px = proxies_list; px; px = px->next) {
Willy Tarreauc3914d42020-09-24 08:39:22 +02002392 if (px->disabled)
Willy Tarreau02b092f2020-10-07 18:36:54 +02002393 stop_proxy(px);
2394 }
2395
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002396 if (!hlua_post_init())
2397 exit(1);
Thomas Holmes6abded42015-05-12 16:23:58 +01002398
Maxime de Roucy0f503922016-05-13 23:52:55 +02002399 free(err_msg);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400}
2401
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002402void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002403{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002404 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002405 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002406 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002407 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002408 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002409 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002410 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002411 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002412 struct per_thread_init_fct *tif, *tifb;
2413 struct per_thread_deinit_fct *tdf, *tdfb;
2414 struct per_thread_alloc_fct *taf, *tafb;
2415 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002416 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002417 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002418 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002419 int cur_fd;
2420
2421 /* At this point the listeners state is weird:
2422 * - most listeners are still bound and referenced in their protocol
2423 * - some might be zombies that are not in their proto anymore, but
2424 * still appear in their proxy's listeners with a valid FD.
2425 * - some might be stopped and still appear in their proxy as FD #-1
2426 * - among all of them, some might be inherited hence shared and we're
2427 * not allowed to pause them or whatever, we must just close them.
2428 * - finally some are not listeners (pipes, logs, stdout, etc) and
2429 * must be left intact.
2430 *
2431 * The safe way to proceed is to unbind (and close) whatever is not yet
2432 * unbound so that no more receiver/listener remains alive. Then close
2433 * remaining listener FDs, which correspond to zombie listeners (those
2434 * belonging to disabled proxies that were in another process).
2435 * objt_listener() would be cleaner here but not converted yet.
2436 */
2437 protocol_unbind_all();
2438
2439 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002440 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002441 continue;
2442
Willy Tarreaua74cb382020-10-15 21:29:49 +02002443 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002444 struct listener *l = fdtab[cur_fd].owner;
2445
2446 BUG_ON(l->state != LI_INIT);
2447 unbind_listener(l);
2448 }
2449 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002450
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002451 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002453 /* build a list of unique uri_auths */
2454 if (!ua)
2455 ua = p->uri_auth;
2456 else {
2457 /* check if p->uri_auth is unique */
2458 for (uap = ua; uap; uap=uap->next)
2459 if (uap == p->uri_auth)
2460 break;
2461
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002462 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002463 /* add it, if it is */
2464 p->uri_auth->next = ua;
2465 ua = p->uri_auth;
2466 }
William Lallemand0f99e342011-10-12 17:50:54 +02002467 }
2468
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002469 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002470 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002471 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002473
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002474 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002475 struct stat_scope *scope, *scopep;
2476
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002477 uap = ua;
2478 ua = ua->next;
2479
Willy Tarreaua534fea2008-08-03 12:19:50 +02002480 free(uap->uri_prefix);
2481 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002482 free(uap->node);
2483 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002484
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002485 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002486 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002487
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002488 scope = uap->scope;
2489 while (scope) {
2490 scopep = scope;
2491 scope = scope->next;
2492
2493 free(scopep->px_id);
2494 free(scopep);
2495 }
2496
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002497 free(uap);
2498 }
2499
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002500 userlist_free(userlist);
2501
David Carlier834cb2e2015-09-25 12:02:25 +01002502 cfg_unregister_sections();
2503
Christopher Faulet0132d062017-07-26 15:33:35 +02002504 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002505
Willy Tarreau05554e62016-12-21 20:46:26 +01002506 list_for_each_entry(pdf, &post_deinit_list, list)
2507 pdf->fct();
2508
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002509 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002510 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002511 ha_free(&global.chroot);
2512 ha_free(&global.pidfile);
2513 ha_free(&global.node);
2514 ha_free(&global.desc);
2515 ha_free(&oldpids);
2516 ha_free(&old_argv);
2517 ha_free(&localpeer);
2518 ha_free(&global.server_state_base);
2519 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002520 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002521 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002522
William Lallemand0f99e342011-10-12 17:50:54 +02002523 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002524 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002525 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002526 free(log);
2527 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002528 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002529 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002530 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002531 free(wl);
2532 }
2533
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002534 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2535 if (bol->must_free)
2536 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002537 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002538 free(bol);
2539 }
2540
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002541 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002542 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002543 free(pxdf);
2544 }
2545
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002546 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002547 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002548 free(pdf);
2549 }
2550
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002551 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002552 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002553 free(srvdf);
2554 }
2555
Tim Duesterhusfc854942020-09-10 19:46:42 +02002556 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002557 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002558 free(pcf);
2559 }
2560
Tim Duesterhus34bef072020-07-04 11:49:50 +02002561 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002562 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002563 free(pscf);
2564 }
2565
Tim Duesterhus53508d62020-09-10 19:46:40 +02002566 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002567 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002568 free(ppcf);
2569 }
2570
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002571 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002572 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002573 free(tif);
2574 }
2575
2576 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002577 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002578 free(tdf);
2579 }
2580
2581 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002582 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002583 free(taf);
2584 }
2585
2586 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002587 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002588 free(tff);
2589 }
2590
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002591 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002592 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002593 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594} /* end deinit() */
2595
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002596__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002597{
2598 deinit();
2599 exit(status);
2600}
William Lallemand72160322018-11-06 17:37:16 +01002601
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002602/* Handler of the task of mux_stopping_data.
2603 * Called on soft-stop.
2604 */
2605struct task *mux_stopping_process(struct task *t, void *ctx, unsigned int state)
2606{
2607 struct connection *conn, *back;
2608
2609 list_for_each_entry_safe(conn, back, &mux_stopping_data[tid].list, stopping_list) {
2610 if (conn->mux && conn->mux->wake)
2611 conn->mux->wake(conn);
2612 }
2613
2614 return t;
2615}
2616
Willy Tarreau918ff602011-07-25 16:33:49 +02002617/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002618void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002619{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002620 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002621
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002622 /* allocates the thread bound mux_stopping_data task */
2623 mux_stopping_data[tid].task = task_new(tid_bit);
2624 mux_stopping_data[tid].task->process = mux_stopping_process;
2625 LIST_INIT(&mux_stopping_data[tid].list);
2626
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002627 tv_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002628 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002629 wake_expired_tasks();
2630
William Lallemand1aab50b2018-06-07 09:46:01 +02002631 /* check if we caught some signals and process them in the
2632 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002633 if (signal_queue_len && tid == 0) {
2634 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002635 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002636 }
2637
2638 /* Process a few tasks */
2639 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002640
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002641 /* also stop if we failed to cleanly stop all tasks */
2642 if (killed > 1)
2643 break;
2644
Willy Tarreau10146c92015-04-13 20:44:19 +02002645 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002646 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002647 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002648 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002649 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002650 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2651 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002652 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002653 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002654 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002655 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002656 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002657 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002658
Willy Tarreau4f46a352020-03-23 09:27:28 +01002659 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002660 int i;
2661
2662 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002663 /* stop muxes before acknowledging stopping */
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002664 if (!(stopping_thread_mask & tid_bit)) {
2665 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2666 wake = 1;
2667 }
2668
Willy Tarreau1db42732021-04-06 11:44:07 +02002669 if (_HA_ATOMIC_OR_FETCH(&stopping_thread_mask, tid_bit) == tid_bit) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002670 /* notify all threads that stopping was just set */
2671 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002672 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002673 wake_thread(i);
2674 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002675 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002676
2677 /* stop when there's nothing left to do */
2678 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002679 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2680 /* wake all threads waiting on jobs==0 */
2681 for (i = 0; i < global.nbthread; i++)
2682 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2683 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002684 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002685 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002686 }
2687
Willy Tarreauc49ba522019-12-11 08:12:23 +01002688 /* If we have to sleep, measure how long */
2689 next = wake ? TICK_ETERNITY : next_timer_expiry();
2690
Willy Tarreau58b458d2008-06-29 22:40:23 +02002691 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002692 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002693
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002694 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002695 }
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002696
2697 task_destroy(mux_stopping_data[tid].task);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002698}
2699
Christopher Faulet1d17c102017-08-29 15:38:48 +02002700static void *run_thread_poll_loop(void *data)
2701{
Willy Tarreau082b6282019-05-22 14:42:12 +02002702 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002703 struct per_thread_init_fct *ptif;
2704 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002705 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002706 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002707 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2708 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002709
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02002710 ha_set_tid((unsigned long)data);
Willy Tarreaud022e9c2019-09-24 08:25:15 +02002711 sched = &task_per_thread[tid];
Willy Tarreau91e6df02019-05-03 17:21:18 +02002712
Willy Tarreauf6178242019-05-21 19:46:58 +02002713#if (_POSIX_TIMERS > 0) && defined(_POSIX_THREAD_CPUTIME)
Willy Tarreau91e6df02019-05-03 17:21:18 +02002714#ifdef USE_THREAD
Willy Tarreau8323a372019-05-20 18:57:53 +02002715 pthread_getcpuclockid(pthread_self(), &ti->clock_id);
Willy Tarreau624dcbf2019-05-20 20:23:06 +02002716#else
Willy Tarreau8323a372019-05-20 18:57:53 +02002717 ti->clock_id = CLOCK_THREAD_CPUTIME_ID;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002718#endif
Willy Tarreau663fda42019-05-21 15:14:08 +02002719#endif
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002720 /* Now, initialize one thread init at a time. This is better since
2721 * some init code is a bit tricky and may release global resources
2722 * after reallocating them locally. This will also ensure there is
2723 * no race on file descriptors allocation.
2724 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002725#ifdef USE_THREAD
2726 pthread_mutex_lock(&init_mutex);
2727#endif
2728 /* The first thread must set the number of threads left */
2729 if (!init_left)
2730 init_left = global.nbthread;
2731 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002732
Willy Tarreauc4c80fb2021-04-11 15:00:34 +02002733 tv_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002734
Willy Tarreau082b6282019-05-22 14:42:12 +02002735 /* per-thread alloc calls performed here are not allowed to snoop on
2736 * other threads, so they are free to initialize at their own rhythm
2737 * as long as they act as if they were alone. None of them may rely
2738 * on resources initialized by the other ones.
2739 */
2740 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2741 if (!ptaf->fct()) {
2742 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002743#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002744 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002745#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02002746 exit(1);
2747 }
2748 }
2749
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002750 /* per-thread init calls performed here are not allowed to snoop on
2751 * other threads, so they are free to initialize at their own rhythm
2752 * as long as they act as if they were alone.
2753 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002754 list_for_each_entry(ptif, &per_thread_init_list, list) {
2755 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002756 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002757#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002758 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002759#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002760 exit(1);
2761 }
2762 }
2763
Willy Tarreau71092822019-06-10 09:51:04 +02002764 /* enabling protocols will result in fd_insert() calls to be performed,
2765 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002766 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002767 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002768 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002769 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002770
Willy Tarreau34a150c2019-06-11 09:16:41 +02002771#ifdef USE_THREAD
2772 pthread_cond_broadcast(&init_cond);
2773 pthread_mutex_unlock(&init_mutex);
2774
2775 /* now wait for other threads to finish starting */
2776 pthread_mutex_lock(&init_mutex);
2777 while (init_left)
2778 pthread_cond_wait(&init_cond, &init_mutex);
2779 pthread_mutex_unlock(&init_mutex);
2780#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002781
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002782#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2783 /* Let's refrain from using setuid executables. This way the impact of
2784 * an eventual vulnerability in a library remains limited. It may
2785 * impact external checks but who cares about them anyway ? In the
2786 * worst case it's possible to disable the option. Obviously we do this
2787 * in workers only. We can't hard-fail on this one as it really is
2788 * implementation dependent though we're interested in feedback, hence
2789 * the warning.
2790 */
2791 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2792 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002793 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 +01002794 ha_warning("Failed to disable setuid, please report to developers with detailed "
2795 "information about your operating system. You can silence this warning "
2796 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2797 }
2798 }
2799#endif
2800
Willy Tarreaud96f1122019-12-03 07:07:36 +01002801#if defined(RLIMIT_NPROC)
2802 /* all threads have started, it's now time to prevent any new thread
2803 * or process from starting. Obviously we do this in workers only. We
2804 * can't hard-fail on this one as it really is implementation dependent
2805 * though we're interested in feedback, hence the warning.
2806 */
2807 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2808 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2809 static int warn_fail;
2810
Willy Tarreau18515722021-04-06 11:57:41 +02002811 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002812 ha_warning("Failed to disable forks, please report to developers with detailed "
2813 "information about your operating system. You can silence this warning "
2814 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2815 }
2816 }
2817#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002818 run_poll_loop();
2819
2820 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2821 ptdf->fct();
2822
Willy Tarreau082b6282019-05-22 14:42:12 +02002823 list_for_each_entry(ptff, &per_thread_free_list, list)
2824 ptff->fct();
2825
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002826#ifdef USE_THREAD
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002827 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002828 if (tid > 0)
2829 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002830#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002831 return NULL;
2832}
Christopher Faulet1d17c102017-08-29 15:38:48 +02002833
William Dauchyf9af9d72019-11-17 15:47:16 +01002834/* set uid/gid depending on global settings */
2835static void set_identity(const char *program_name)
2836{
2837 if (global.gid) {
2838 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
2839 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
2840 " without 'uid'/'user' is generally useless.\n", program_name);
2841
2842 if (setgid(global.gid) == -1) {
2843 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
2844 protocol_unbind_all();
2845 exit(1);
2846 }
2847 }
2848
2849 if (global.uid && setuid(global.uid) == -1) {
2850 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
2851 protocol_unbind_all();
2852 exit(1);
2853 }
2854}
2855
Willy Tarreaubaaee002006-06-26 02:48:02 +02002856int main(int argc, char **argv)
2857{
2858 int err, retry;
2859 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02002860 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02002861 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
2862
2863 /* Catch forced CFLAGS that miss 2-complement integer overflow */
2864 if (intovf + 0x7FFFFFFF >= intovf) {
2865 fprintf(stderr,
2866 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
2867 "The source code was miscompiled by the compiler, which usually indicates that\n"
2868 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
2869 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
2870 "and INSTALL files to decide on the best way to pass your local build options.\n"
2871 "\nBuild options :"
2872#ifdef BUILD_TARGET
2873 "\n TARGET = " BUILD_TARGET
2874#endif
2875#ifdef BUILD_CPU
2876 "\n CPU = " BUILD_CPU
2877#endif
2878#ifdef BUILD_CC
2879 "\n CC = " BUILD_CC
2880#endif
2881#ifdef BUILD_CFLAGS
2882 "\n CFLAGS = " BUILD_CFLAGS
2883#endif
2884#ifdef BUILD_OPTIONS
2885 "\n OPTIONS = " BUILD_OPTIONS
2886#endif
2887#ifdef BUILD_DEBUG
2888 "\n DEBUG = " BUILD_DEBUG
2889#endif
2890 "\n\n");
2891 return 1;
2892 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002893
Olivier Houchard5fa300d2018-02-03 15:15:21 +01002894 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01002895
Willy Tarreaubf696402019-03-01 10:09:28 +01002896 /* take a copy of initial limits before we possibly change them */
2897 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02002898
2899 if (limit.rlim_max == RLIM_INFINITY)
2900 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01002901 rlim_fd_cur_at_boot = limit.rlim_cur;
2902 rlim_fd_max_at_boot = limit.rlim_max;
2903
Willy Tarreau5794fb02018-11-25 18:43:29 +01002904 /* process all initcalls in order of potential dependency */
2905 RUN_INITCALLS(STG_PREPARE);
2906 RUN_INITCALLS(STG_LOCK);
2907 RUN_INITCALLS(STG_ALLOC);
2908 RUN_INITCALLS(STG_POOL);
2909 RUN_INITCALLS(STG_REGISTER);
2910 RUN_INITCALLS(STG_INIT);
2911
Emeric Bruncf20bf12010-10-22 16:06:11 +02002912 init(argc, argv);
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002913 signal_register_fct(SIGQUIT, dump, SIGQUIT);
2914 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
2915 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02002916 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002917
Willy Tarreaue437c442010-03-17 18:02:46 +01002918 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
2919 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
2920 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002921 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002922 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002923
Willy Tarreaudc23a922011-02-16 11:10:36 +01002924 /* ulimits */
2925 if (!global.rlimit_nofile)
2926 global.rlimit_nofile = global.maxsock;
2927
2928 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01002929 limit.rlim_cur = global.rlimit_nofile;
2930 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
2931
Willy Tarreaudc23a922011-02-16 11:10:36 +01002932 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02002933 getrlimit(RLIMIT_NOFILE, &limit);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002934 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2935 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
2936 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002937 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002938 }
2939 else {
2940 /* try to set it to the max possible at least */
2941 limit.rlim_cur = limit.rlim_max;
2942 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
2943 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02002944
William Dauchya5194602020-03-28 19:29:58 +01002945 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002946 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
2947 global.rlimit_nofile = limit.rlim_cur;
2948 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01002949 }
2950 }
2951
2952 if (global.rlimit_memmax) {
2953 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01002954 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01002955#ifdef RLIMIT_AS
2956 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002957 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2958 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2959 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002960 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002961 }
2962 else
William Dauchya5194602020-03-28 19:29:58 +01002963 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002964 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002965 }
2966#else
2967 if (setrlimit(RLIMIT_DATA, &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#endif
2978 }
2979
Olivier Houchardf73629d2017-04-05 22:33:04 +02002980 if (old_unixsocket) {
William Lallemand85b0bd92017-06-01 17:38:53 +02002981 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02002982 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002983 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02002984 if (!(global.mode & MODE_MWORKER))
2985 exit(1);
2986 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02002987 }
2988 }
William Lallemand85b0bd92017-06-01 17:38:53 +02002989 get_cur_unixsocket();
2990
Willy Tarreaubaaee002006-06-26 02:48:02 +02002991 /* We will loop at most 100 times with 10 ms delay each time.
2992 * That's at most 1 second. We only send a signal to old pids
2993 * if we cannot grab at least one port.
2994 */
2995 retry = MAX_START_RETRIES;
2996 err = ERR_NONE;
2997 while (retry >= 0) {
2998 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02002999 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003000 /* exit the loop on no error or fatal error */
3001 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003002 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003003 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 break;
3005
3006 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3007 * listening sockets. So on those platforms, it would be wiser to
3008 * simply send SIGUSR1, which will not be undoable.
3009 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003010 if (tell_old_pids(SIGTTOU) == 0) {
3011 /* no need to wait if we can't contact old pids */
3012 retry = 0;
3013 continue;
3014 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003015 /* give some time to old processes to stop listening */
3016 w.tv_sec = 0;
3017 w.tv_usec = 10*1000;
3018 select(0, NULL, NULL, NULL, &w);
3019 retry--;
3020 }
3021
Willy Tarreaue91bff22020-09-02 11:11:43 +02003022 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003023 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003024 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003025 if (retry != MAX_START_RETRIES && nb_oldpids) {
3026 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003027 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003028 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003029 exit(1);
3030 }
3031
William Lallemand944e6192018-11-21 15:48:31 +01003032 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003033 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003034 /* Note: we don't have to send anything to the old pids because we
3035 * never stopped them. */
3036 exit(1);
3037 }
3038
Willy Tarreaue91bff22020-09-02 11:11:43 +02003039 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003040 * the previous process gave us, we don't need them anymore
3041 */
3042 while (xfer_sock_list != NULL) {
3043 struct xfer_sock_list *tmpxfer = xfer_sock_list->next;
3044 close(xfer_sock_list->fd);
3045 free(xfer_sock_list->iface);
3046 free(xfer_sock_list->namespace);
3047 free(xfer_sock_list);
3048 xfer_sock_list = tmpxfer;
3049 }
Willy Tarreaudd815982007-10-16 12:25:14 +02003050
Willy Tarreaubaaee002006-06-26 02:48:02 +02003051 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003052 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3053 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003054
Willy Tarreaubaaee002006-06-26 02:48:02 +02003055 /* MODE_QUIET can inhibit alerts and warnings below this line */
3056
PiBa-NL149a81a2017-12-25 21:03:31 +01003057 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3058 /* either stdin/out/err are already closed or should stay as they are. */
3059 if ((global.mode & MODE_DAEMON)) {
3060 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3061 global.mode &= ~MODE_VERBOSE;
3062 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3063 }
3064 } else {
3065 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3066 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003067 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003068 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003069 }
3070
3071 /* open log & pid files before the chroot */
William Lallemand80293002017-11-06 11:00:03 +01003072 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003073 unlink(global.pidfile);
3074 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3075 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003076 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077 if (nb_oldpids)
3078 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003079 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 exit(1);
3081 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 }
3083
Willy Tarreaub38651a2007-03-24 17:24:39 +01003084 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003085 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3086 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003087 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003088 exit(1);
3089 }
3090
Jackie Tapia749f74c2020-07-22 18:59:40 -05003091 /* If the user is not root, we'll still let them try the configuration
3092 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003093 */
3094 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003095 ha_warning("[%s.main()] Some options which require full privileges"
3096 " might not work well.\n"
3097 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003098
William Lallemand095ba4c2017-06-01 17:38:50 +02003099 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3100
3101 /* chroot if needed */
3102 if (global.chroot != NULL) {
3103 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003104 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003105 if (nb_oldpids)
3106 tell_old_pids(SIGTTIN);
3107 protocol_unbind_all();
3108 exit(1);
3109 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003110 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003111 }
3112
William Lallemand944e6192018-11-21 15:48:31 +01003113 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003114 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115
William Lallemand27edc4b2019-05-07 17:49:33 +02003116 /* send a SIGTERM to workers who have a too high reloads number */
3117 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3118 mworker_kill_max_reloads(SIGTERM);
3119
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 /* Note that any error at this stage will be fatal because we will not
3121 * be able to restart the old pids.
3122 */
3123
William Dauchyf9af9d72019-11-17 15:47:16 +01003124 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3125 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003126
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127 /* check ulimits */
3128 limit.rlim_cur = limit.rlim_max = 0;
3129 getrlimit(RLIMIT_NOFILE, &limit);
3130 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003131 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3132 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3133 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3134 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3135 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003136 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003137 }
3138 else
3139 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003140 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003141 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3142 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003143 }
3144
William Lallemand944e6192018-11-21 15:48:31 +01003145 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003146 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003147 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003148 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003149
William Lallemand095ba4c2017-06-01 17:38:50 +02003150 /*
3151 * if daemon + mworker: must fork here to let a master
3152 * process live in background before forking children
3153 */
William Lallemand73b85e72017-06-01 17:38:51 +02003154
3155 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3156 && (global.mode & MODE_MWORKER)
3157 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003158 ret = fork();
3159 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003160 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003161 protocol_unbind_all();
3162 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003163 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003164 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003165 } else /* change the process group ID in the child (master process) */
3166 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003167 }
William Lallemande20b6a62017-06-01 17:38:55 +02003168
William Lallemande20b6a62017-06-01 17:38:55 +02003169
William Lallemanddeed7802017-11-06 11:00:04 +01003170 /* if in master-worker mode, write the PID of the father */
3171 if (global.mode & MODE_MWORKER) {
3172 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003173 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003174 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003175 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003176 }
3177
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003179 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003180 if (global.mode & MODE_MWORKER)
3181 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003182
3183 ret = fork();
3184 if (ret < 0) {
3185 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3186 protocol_unbind_all();
3187 exit(1); /* there has been an error */
3188 }
3189 else if (ret == 0) { /* child breaks here */
Willy Tarreau3c032f22021-07-21 10:17:02 +02003190 /* This one must not be exported, it's internal! */
3191 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003192 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003193 }
3194 else { /* parent here */
3195 in_parent = 1;
3196
William Lallemand944e6192018-11-21 15:48:31 +01003197 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3198 char pidstr[100];
3199 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003200 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003201 }
3202 if (global.mode & MODE_MWORKER) {
3203 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003204
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003205 ha_notice("New worker #%d (%d) forked\n", 1, ret);
William Lallemand944e6192018-11-21 15:48:31 +01003206 /* find the right mworker_proc */
3207 list_for_each_entry(child, &proc_list, list) {
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003208 if (child->reloads == 0 && child->options & PROC_O_TYPE_WORKER) {
William Lallemand944e6192018-11-21 15:48:31 +01003209 child->timestamp = now.tv_sec;
3210 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003211 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003212 break;
3213 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003214 }
3215 }
William Lallemand944e6192018-11-21 15:48:31 +01003216 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003217
William Lallemand944e6192018-11-21 15:48:31 +01003218 } else {
3219 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003220 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003221 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003222
3223#ifdef USE_CPU_AFFINITY
Willy Tarreau44ea6312021-06-15 08:57:56 +02003224 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 +02003225
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003226#ifdef __FreeBSD__
Willy Tarreau44ea6312021-06-15 08:57:56 +02003227 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003228 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
David Carlier2d0493a2020-12-02 21:14:51 +00003229#elif defined(__linux__) || defined(__DragonFly__)
Willy Tarreau44ea6312021-06-15 08:57:56 +02003230 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003231 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003232#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003233 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003234#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003235 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003236 if (pidfd >= 0) {
3237 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3238 close(pidfd);
3239 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003240
3241 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003242 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003243
Willy Tarreaud67ff342021-06-15 07:58:09 +02003244 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003245 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003246
3247 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3248 (global.mode & MODE_DAEMON)) {
3249 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003250 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3251 stdio_quiet(-1);
3252
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003253 global.mode &= ~MODE_VERBOSE;
3254 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003255 }
3256
William Lallemandb3f2be32018-09-11 10:06:18 +02003257 mworker_loop();
William Lallemand1499b9b2017-06-07 15:04:47 +02003258 /* should never get there */
3259 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003260 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003261#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003262 ssl_free_dh();
3263#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003264 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003265 }
3266
William Lallemandcb11fd22017-06-01 17:38:52 +02003267 /* child must never use the atexit function */
3268 atexit_flag = 0;
3269
William Lallemandbc193052018-09-11 10:06:26 +02003270 /* close useless master sockets */
3271 if (global.mode & MODE_MWORKER) {
3272 struct mworker_proc *child, *it;
3273 master = 0;
3274
William Lallemand309dc9a2018-10-26 14:47:45 +02003275 mworker_cli_proxy_stop();
3276
William Lallemandbc193052018-09-11 10:06:26 +02003277 /* free proc struct of other processes */
3278 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003279 /* close the FD of the master side for all
3280 * workers, we don't need to close the worker
3281 * side of other workers since it's done with
3282 * the bind_proc */
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003283 if (child->ipc_fd[0] >= 0)
3284 close(child->ipc_fd[0]);
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003285 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandce83b4a2018-10-26 14:47:30 +02003286 child->reloads == 0) {
3287 /* keep this struct if this is our pid */
3288 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003289 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003290 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003291 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003292 mworker_free_child(child);
3293 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003294 }
3295 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003296
William Lallemande1340412017-12-28 16:09:36 +01003297 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3298 devnullfd = open("/dev/null", O_RDWR, 0);
3299 if (devnullfd < 0) {
3300 ha_alert("Cannot open /dev/null\n");
3301 exit(EXIT_FAILURE);
3302 }
3303 }
3304
William Lallemand095ba4c2017-06-01 17:38:50 +02003305 /* Must chroot and setgid/setuid in the children */
3306 /* chroot if needed */
3307 if (global.chroot != NULL) {
3308 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003309 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003310 if (nb_oldpids)
3311 tell_old_pids(SIGTTIN);
3312 protocol_unbind_all();
3313 exit(1);
3314 }
3315 }
3316
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003317 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003318 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003319
William Lallemand7f80eb22017-05-26 18:19:55 +02003320 /* pass through every cli socket, and check if it's bound to
3321 * the current process and if it exposes listeners sockets.
3322 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3323 * */
3324
Willy Tarreau4975d142021-03-13 11:00:33 +01003325 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003326 struct bind_conf *bind_conf;
3327
Willy Tarreau4975d142021-03-13 11:00:33 +01003328 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003329 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003330 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3331 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003332 }
3333 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003334 }
3335
William Lallemand2e8fad92018-11-13 16:18:23 +01003336 /*
3337 * This is only done in daemon mode because we might want the
3338 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3339 * we should now close the 3 first FDs to ensure that we can
3340 * detach from the TTY. We MUST NOT do it in other cases since
3341 * it would have already be done, and 0-2 would have been
3342 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003343 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003344 if ((global.mode & MODE_DAEMON) &&
3345 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003346 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003347 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003348 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003349 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3350 }
3351 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003352 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3353 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003354 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355 }
3356
William Dauchye039f262019-11-17 15:47:15 +01003357 /* try our best to re-enable core dumps depending on system capabilities.
3358 * What is addressed here :
3359 * - remove file size limits
3360 * - remove core size limits
3361 * - mark the process dumpable again if it lost it due to user/group
3362 */
3363 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3364 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3365
3366#if defined(RLIMIT_FSIZE)
3367 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3368 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3369 ha_alert("[%s.main()] Failed to set the raise the maximum "
3370 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003371 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003372 }
3373 else
3374 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003375 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003376 }
3377#endif
3378
3379#if defined(RLIMIT_CORE)
3380 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3381 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3382 ha_alert("[%s.main()] Failed to set the raise the core "
3383 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003384 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003385 }
3386 else
3387 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003388 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003389 }
3390#endif
3391
3392#if defined(USE_PRCTL)
3393 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3394 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3395 "no core will be dumped.\n", argv[0]);
3396#endif
3397 }
3398
Christopher Faulete3a5e352017-10-24 13:53:54 +02003399 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003400 reset_usermsgs_ctx();
3401
Willy Tarreau4f60f162007-04-08 16:39:58 +02003402 /*
3403 * That's it : the central polling loop. Run until we stop.
3404 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02003405#ifdef USE_THREAD
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003406 {
William Lallemand1aab50b2018-06-07 09:46:01 +02003407 sigset_t blocked_sig, old_sig;
Willy Tarreauc40efc12019-05-03 09:22:44 +02003408 int i;
3409
William Lallemand1aab50b2018-06-07 09:46:01 +02003410 /* ensure the signals will be blocked in every thread */
3411 sigfillset(&blocked_sig);
3412 sigdelset(&blocked_sig, SIGPROF);
3413 sigdelset(&blocked_sig, SIGBUS);
3414 sigdelset(&blocked_sig, SIGFPE);
3415 sigdelset(&blocked_sig, SIGILL);
3416 sigdelset(&blocked_sig, SIGSEGV);
3417 pthread_sigmask(SIG_SETMASK, &blocked_sig, &old_sig);
3418
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003419 /* Create nbthread-1 thread. The first thread is the current process */
David Carliera92c5ce2019-09-13 05:03:12 +01003420 ha_thread_info[0].pthread = pthread_self();
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003421 for (i = 1; i < global.nbthread; i++)
David Carliera92c5ce2019-09-13 05:03:12 +01003422 pthread_create(&ha_thread_info[i].pthread, NULL, &run_thread_poll_loop, (void *)(long)i);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003423
Christopher Faulet62519022017-10-16 15:49:32 +02003424#ifdef USE_CPU_AFFINITY
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003425 /* Now the CPU affinity for all threads */
Amaury Denoyelleaf02c572021-04-15 16:29:58 +02003426
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003427 for (i = 0; i < global.nbthread; i++) {
Willy Tarreau44ea6312021-06-15 08:57:56 +02003428 if (ha_cpuset_count(&cpu_map.proc))
3429 ha_cpuset_and(&cpu_map.thread[i], &cpu_map.proc);
Christopher Faulet62519022017-10-16 15:49:32 +02003430
Willy Tarreau421f02e2018-01-20 18:19:22 +01003431 if (i < MAX_THREADS && /* only the first 32/64 threads may be pinned */
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003432 ha_cpuset_count(&cpu_map.thread[i])) {/* only do this if the thread has a THREAD map */
David Carlier5e4c8e22019-09-13 05:12:58 +01003433#if defined(__APPLE__)
3434 int j;
Amaury Denoyelle8f685c12021-04-27 16:45:29 +02003435 unsigned long set = cpu_map.thread[i].cpuset;
David Carlier5e4c8e22019-09-13 05:12:58 +01003436
Amaury Denoyelle8f685c12021-04-27 16:45:29 +02003437 while ((j = ffsl(set)) > 0) {
David Carlier5e4c8e22019-09-13 05:12:58 +01003438 thread_affinity_policy_data_t cpu_set = { j - 1 };
3439 thread_port_t mthread = pthread_mach_thread_np(ha_thread_info[i].pthread);
3440 thread_policy_set(mthread, THREAD_AFFINITY_POLICY, (thread_policy_t)&cpu_set, 1);
Amaury Denoyelle8f685c12021-04-27 16:45:29 +02003441 set &= ~(1UL << (j - 1));
David Carlier5e4c8e22019-09-13 05:12:58 +01003442 }
3443#else
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003444 struct hap_cpuset *set = &cpu_map.thread[i];
David Carliera92c5ce2019-09-13 05:03:12 +01003445 pthread_setaffinity_np(ha_thread_info[i].pthread,
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003446 sizeof(set->cpuset), &set->cpuset);
David Carlier5e4c8e22019-09-13 05:12:58 +01003447#endif
Olivier Houchard829aa242017-12-01 18:19:43 +01003448 }
Christopher Faulet1d17c102017-08-29 15:38:48 +02003449 }
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003450#endif /* !USE_CPU_AFFINITY */
3451
William Lallemand1aab50b2018-06-07 09:46:01 +02003452 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003453 haproxy_unblock_signals();
William Lallemand1aab50b2018-06-07 09:46:01 +02003454
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003455 /* Finally, start the poll loop for the first thread */
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02003456 run_thread_poll_loop(0);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003457
3458 /* Wait the end of other threads */
3459 for (i = 1; i < global.nbthread; i++)
David Carliera92c5ce2019-09-13 05:03:12 +01003460 pthread_join(ha_thread_info[i].pthread, NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02003461
Christopher Fauletb79a94c2017-05-30 15:34:30 +02003462#if defined(DEBUG_THREAD) || defined(DEBUG_FULL)
3463 show_lock_stats();
3464#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003465 }
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003466#else /* ! USE_THREAD */
William Lallemandd3801c12018-09-11 10:06:23 +02003467 haproxy_unblock_signals();
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02003468 run_thread_poll_loop(0);
Christopher Faulet62519022017-10-16 15:49:32 +02003469#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003470
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003471 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003472}
3473
Willy Tarreaubaaee002006-06-26 02:48:02 +02003474/*
3475 * Local variables:
3476 * c-indent-level: 8
3477 * c-basic-offset: 8
3478 * End:
3479 */