blob: 84e6b9050a6388a97bba427f3f36fbb18d877ecd [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
Willy Tarreaua5357cd2021-05-09 06:14:25 +02002 * HAProxy : High Availability-enabled HTTP/TCP proxy
Willy Tarreau421ed392021-01-06 17:41:32 +01003 * Copyright 2000-2021 Willy Tarreau <willy@haproxy.org>.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
Ilya Shipitsin46a030c2020-07-05 16:36:08 +050010 * Please refer to RFC7230 - RFC7235 information about HTTP protocol, and
11 * RFC6265 for information about cookies usage. More generally, the IETF HTTP
Willy Tarreaubaaee002006-06-26 02:48:02 +020012 * Working Group's web site should be consulted for protocol related changes :
13 *
14 * http://ftp.ics.uci.edu/pub/ietf/http/
15 *
16 * Pending bugs (may be not fixed because never reproduced) :
17 * - solaris only : sometimes, an HTTP proxy with only a dispatch address causes
18 * the proxy to terminate (no core) if the client breaks the connection during
19 * the response. Seen on 1.1.8pre4, but never reproduced. May not be related to
20 * the snprintf() bug since requests were simple (GET / HTTP/1.0), but may be
21 * related to missing setsid() (fixed in 1.1.15)
22 * - a proxy with an invalid config will prevent the startup even if disabled.
23 *
24 * ChangeLog has moved to the CHANGELOG file.
25 *
Willy Tarreaubaaee002006-06-26 02:48:02 +020026 */
27
David Carlier7ece0962015-12-08 21:43:09 +000028#define _GNU_SOURCE
Willy Tarreaubaaee002006-06-26 02:48:02 +020029#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <string.h>
33#include <ctype.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020034#include <dirent.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020035#include <sys/stat.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <sys/time.h>
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <netinet/tcp.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42#include <netdb.h>
43#include <fcntl.h>
44#include <errno.h>
45#include <signal.h>
46#include <stdarg.h>
47#include <sys/resource.h>
Tim Duesterhusdfad6a42020-04-18 16:02:47 +020048#include <sys/utsname.h>
Marc-Antoine Perennou992709b2013-02-12 10:53:52 +010049#include <sys/wait.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <time.h>
51#include <syslog.h>
Michael Schererab012dd2013-01-12 18:35:19 +010052#include <grp.h>
Willy Tarreaud10385a2021-10-06 22:22:40 +020053
Willy Tarreau5e03dfa2021-10-06 22:53:51 +020054#ifdef USE_THREAD
55#include <pthread.h>
56#endif
57
Willy Tarreaufc6c0322012-11-16 16:12:27 +010058#ifdef USE_CPU_AFFINITY
Willy Tarreaufc6c0322012-11-16 16:12:27 +010059#include <sched.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000060#if defined(__FreeBSD__) || defined(__DragonFly__)
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020061#include <sys/param.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000062#ifdef __FreeBSD__
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020063#include <sys/cpuset.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000064#endif
David Carlier5e4c8e22019-09-13 05:12:58 +010065#endif
Willy Tarreaufc6c0322012-11-16 16:12:27 +010066#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020067
Willy Tarreau636848a2019-04-15 19:38:50 +020068#if defined(USE_PRCTL)
69#include <sys/prctl.h>
70#endif
71
devnexen@gmail.com21185972021-08-21 09:13:10 +010072#if defined(USE_PROCCTL)
73#include <sys/procctl.h>
74#endif
75
Willy Tarreaubaaee002006-06-26 02:48:02 +020076#ifdef DEBUG_FULL
77#include <assert.h>
78#endif
Tim Duesterhusd6942c82017-11-20 15:58:35 +010079#if defined(USE_SYSTEMD)
80#include <systemd/sd-daemon.h>
81#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020082
Willy Tarreau6c3a6812020-03-06 18:57:15 +010083#include <import/sha1.h>
84
Willy Tarreaub2551052020-06-09 09:07:15 +020085#include <haproxy/acl.h>
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +010086#include <haproxy/action.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020087#include <haproxy/activity.h>
88#include <haproxy/api.h>
89#include <haproxy/arg.h>
90#include <haproxy/auth.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020091#include <haproxy/base64.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020092#include <haproxy/capture-t.h>
Willy Tarreau66243b42021-07-16 15:39:28 +020093#include <haproxy/cfgcond.h>
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +020094#include <haproxy/cfgdiag.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020095#include <haproxy/cfgparse.h>
Willy Tarreauc13ed532020-06-02 10:22:45 +020096#include <haproxy/chunk.h>
Willy Tarreau83487a82020-06-04 20:19:54 +020097#include <haproxy/cli.h>
Willy Tarreau55542642021-10-08 09:33:24 +020098#include <haproxy/clock.h>
Willy Tarreau7ea393d2020-06-04 18:02:10 +020099#include <haproxy/connection.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200100#ifdef USE_CPU_AFFINITY
Amaury Denoyelle982fb532021-04-21 18:39:58 +0200101#include <haproxy/cpuset.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200102#endif
Willy Tarreaueb92deb2020-06-04 10:53:16 +0200103#include <haproxy/dns.h>
Willy Tarreau2741c8c2020-06-02 11:28:02 +0200104#include <haproxy/dynbuf.h>
Willy Tarreau8d366972020-05-27 16:10:29 +0200105#include <haproxy/errors.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200106#include <haproxy/fd.h>
Willy Tarreauc7babd82020-06-04 21:29:29 +0200107#include <haproxy/filters.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200108#include <haproxy/global.h>
Willy Tarreau86416052020-06-04 09:20:54 +0200109#include <haproxy/hlua.h>
Willy Tarreauc761f842020-06-04 11:40:28 +0200110#include <haproxy/http_rules.h>
Willy Tarreau853b2972020-05-27 18:01:47 +0200111#include <haproxy/list.h>
Willy Tarreau213e9902020-06-04 14:58:24 +0200112#include <haproxy/listener.h>
Willy Tarreauaeed4a82020-06-04 22:01:04 +0200113#include <haproxy/log.h>
Willy Tarreaub5abe5b2020-06-04 14:07:37 +0200114#include <haproxy/mworker.h>
Willy Tarreau7a00efb2020-06-02 17:02:59 +0200115#include <haproxy/namespace.h>
Willy Tarreau6131d6a2020-06-02 16:48:09 +0200116#include <haproxy/net_helper.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +0200117#include <haproxy/openssl-compat.h>
Willy Tarreau225a90a2020-06-04 15:06:28 +0200118#include <haproxy/pattern.h>
Willy Tarreau3c2a7c22020-06-04 18:38:21 +0200119#include <haproxy/peers.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200120#include <haproxy/pool.h>
121#include <haproxy/protocol.h>
Willy Tarreaubf3b06b2020-08-26 10:23:40 +0200122#include <haproxy/proto_tcp.h>
Willy Tarreaua264d962020-06-04 22:29:18 +0200123#include <haproxy/proxy.h>
Willy Tarreau7cd8b6e2020-06-02 17:32:26 +0200124#include <haproxy/regex.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200125#include <haproxy/sample.h>
Willy Tarreau1e56f922020-06-04 23:20:13 +0200126#include <haproxy/server.h>
Willy Tarreau48d25b32020-06-04 18:58:52 +0200127#include <haproxy/session.h>
Willy Tarreau3727a8a2020-06-04 17:37:26 +0200128#include <haproxy/signal.h>
Willy Tarreau063d47d2020-08-28 16:29:53 +0200129#include <haproxy/sock.h>
Willy Tarreau25140cc2020-08-28 15:40:33 +0200130#include <haproxy/sock_inet.h>
Willy Tarreau209108d2020-06-04 20:30:20 +0200131#include <haproxy/ssl_sock.h>
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +0200132#include <haproxy/stats-t.h>
Willy Tarreaudfd3de82020-06-04 23:46:14 +0200133#include <haproxy/stream.h>
Willy Tarreaucea0e1b2020-06-04 17:25:40 +0200134#include <haproxy/task.h>
Willy Tarreau3f567e42020-05-28 15:29:19 +0200135#include <haproxy/thread.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200136#include <haproxy/time.h>
137#include <haproxy/tools.h>
138#include <haproxy/uri_auth-t.h>
Willy Tarreaua1718922020-06-04 16:25:31 +0200139#include <haproxy/vars.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200140#include <haproxy/version.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200141
Willy Tarreaubaaee002006-06-26 02:48:02 +0200142
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100143/* array of init calls for older platforms */
144DECLARE_INIT_STAGES;
145
Willy Tarreauf4596402021-04-10 16:53:05 +0200146/* create a read_mostly section to hold variables which are accessed a lot
147 * but which almost never change. The purpose is to isolate them in their
148 * own cache lines where they don't risk to be perturbated by write accesses
149 * to neighbor variables. We need to create an empty aligned variable for
150 * this. The fact that the variable is of size zero means that it will be
151 * eliminated at link time if no other variable uses it, but alignment will
152 * be respected.
153 */
154empty_t __read_mostly_align HA_SECTION("read_mostly") ALIGNED(64);
155
Willy Tarreauf0d3b732021-05-06 16:30:32 +0200156#ifdef BUILD_FEATURES
157const char *build_features = BUILD_FEATURES;
158#else
159const char *build_features = "";
160#endif
161
Willy Tarreau477ecd82010-01-03 21:12:30 +0100162/* list of config files */
163static struct list cfg_cfgfiles = LIST_HEAD_INIT(cfg_cfgfiles);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200164int pid; /* current process id */
165
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100166volatile unsigned long sleeping_thread_mask = 0; /* Threads that are about to sleep in poll() */
Willy Tarreau4b3f27b2020-03-12 17:28:01 +0100167volatile unsigned long stopping_thread_mask = 0; /* Threads acknowledged stopping */
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100168
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169/* global options */
170struct global global = {
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100171 .hard_stop_after = TICK_ETERNITY,
Amaury Denoyelle0f50cb92021-03-26 18:50:33 +0100172 .numa_cpu_mapping = 1,
Willy Tarreau149ab772019-01-26 14:27:06 +0100173 .nbthread = 0,
William Lallemand5f232402012-04-05 18:02:55 +0200174 .req_count = 0,
William Lallemand0f99e342011-10-12 17:50:54 +0200175 .logsrvs = LIST_HEAD_INIT(global.logsrvs),
William Lallemand9d5f5482012-11-07 16:12:57 +0100176 .maxzlibmem = 0,
William Lallemandd85f9172012-11-09 17:05:39 +0100177 .comp_rate_lim = 0,
Emeric Brun850efd52014-01-29 12:24:34 +0100178 .ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED,
Emeric Bruned760922010-10-22 17:59:25 +0200179 .unix_bind = {
180 .ux = {
181 .uid = -1,
182 .gid = -1,
183 .mode = 0,
184 }
185 },
Willy Tarreau27a674e2009-08-17 07:23:33 +0200186 .tune = {
Willy Tarreau7ac908b2019-02-27 12:02:18 +0100187 .options = GTUNE_LISTENER_MQ,
Willy Tarreauc77d3642018-12-12 06:19:42 +0100188 .bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
Christopher Faulet546c4692020-01-22 14:31:21 +0100189 .maxrewrite = MAXREWRITE,
Willy Tarreaua24adf02014-11-27 01:11:56 +0100190 .reserved_bufs = RESERVED_BUFS,
Willy Tarreauf3045d22015-04-29 16:24:50 +0200191 .pattern_cache = DEFAULT_PAT_LRU_SIZE,
Olivier Houchard88698d92019-04-16 19:07:22 +0200192 .pool_low_ratio = 20,
193 .pool_high_ratio = 25,
Christopher Faulet41ba36f2019-07-19 09:36:45 +0200194 .max_http_hdr = MAX_HTTP_HDR,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200195#ifdef USE_OPENSSL
Emeric Brun46635772012-11-14 11:32:56 +0100196 .sslcachesize = SSLCACHESIZE,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200197#endif
William Lallemandf3747832012-11-09 12:33:10 +0100198 .comp_maxlevel = 1,
Willy Tarreau7e312732014-02-12 16:35:14 +0100199#ifdef DEFAULT_IDLE_TIMER
200 .idle_timer = DEFAULT_IDLE_TIMER,
201#else
202 .idle_timer = 1000, /* 1 second */
203#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200204 },
Emeric Brun76d88952012-10-05 15:47:31 +0200205#ifdef USE_OPENSSL
206#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200207 .maxsslconn = DEFAULT_MAXSSLCONN,
208#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200209#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210 /* others NULL OK */
211};
212
213/*********************************************************************/
214
215int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100216int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200217int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100218int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100219int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100220int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500222/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 * or kill. We will send them a signal every 10 ms until we can bind to all
224 * our ports. With 200 retries, that's about 2 seconds.
225 */
226#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227static int *oldpids = NULL;
228static int oldpids_sig; /* use USR1 or TERM */
229
Olivier Houchardf73629d2017-04-05 22:33:04 +0200230/* Path to the unix socket we use to retrieve listener sockets from the old process */
231static const char *old_unixsocket;
232
William Lallemandcb11fd22017-06-01 17:38:52 +0200233int atexit_flag = 0;
234
Willy Tarreaubb545b42010-08-25 12:58:59 +0200235int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236const int zero = 0;
237const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200238const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100240char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200241char *localpeer = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242
William Lallemand00417412020-06-05 14:08:41 +0200243static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200244
William Lallemandbc193052018-09-11 10:06:26 +0200245struct list proc_list = LIST_HEAD_INIT(proc_list);
246
247int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100248unsigned int rlim_fd_cur_at_boot = 0;
249unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200250
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100251/* per-boot randomness */
252unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
253
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200254/* takes the thread config in argument or NULL for any thread */
William Lallemandb3f2be32018-09-11 10:06:18 +0200255static void *run_thread_poll_loop(void *data);
256
Willy Tarreauff055502014-04-28 22:27:06 +0200257/* bitfield of a few warnings to emit just once (WARN_*) */
258unsigned int warned = 0;
259
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200260/* set if experimental features have been used for the current process */
261static unsigned int tainted = 0;
262
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200263unsigned int experimental_directives_allowed = 0;
264
265int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
266 char **errmsg)
267{
268 if (kw->flags & KWF_EXPERIMENTAL) {
269 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200270 memprintf(errmsg, "parsing [%s:%d] : '%s' directive is experimental, must be allowed via a global 'expose-experimental-directives'",
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200271 file, linenum, kw->kw);
272 return 1;
273 }
274 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
275 }
276
277 return 0;
278}
279
William Lallemande7361152018-10-26 14:47:36 +0200280/* master CLI configuration (-S flag) */
281struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100282
283/* These are strings to be reported in the output of "haproxy -vv". They may
284 * either be constants (in which case must_free must be zero) or dynamically
285 * allocated strings to pass to free() on exit, and in this case must_free
286 * must be non-zero.
287 */
288struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
289struct build_opts_str {
290 struct list list;
291 const char *str;
292 int must_free;
293};
294
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295/*********************************************************************/
296/* general purpose functions ***************************************/
297/*********************************************************************/
298
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100299/* used to register some build option strings at boot. Set must_free to
300 * non-zero if the string must be freed upon exit.
301 */
302void hap_register_build_opts(const char *str, int must_free)
303{
304 struct build_opts_str *b;
305
306 b = calloc(1, sizeof(*b));
307 if (!b) {
308 fprintf(stderr, "out of memory\n");
309 exit(1);
310 }
311 b->str = str;
312 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200313 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100314}
315
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200316#define VERSION_MAX_ELTS 7
317
318/* This function splits an haproxy version string into an array of integers.
319 * The syntax of the supported version string is the following:
320 *
321 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
322 *
323 * This validates for example:
324 * 1.2.1-pre2, 1.2.1, 1.2.10.1, 1.3.16-rc1, 1.4-dev3, 1.5-dev18, 1.5-dev18-43
325 * 2.4-dev18-f6818d-20
326 *
327 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
328 * one fixed place in the array. The tags take a numeric value called <e> which
329 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
330 * considered as zero (henxe 1.5 and 1.5.0 are the same).
331 *
332 * The resulting values are:
333 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
334 * 1.2.1 1, 2, 1, 0, 3, 0, 0
335 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
336 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
337 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
338 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
339 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
340 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
341 *
342 * The function returns non-zero if the conversion succeeded, or zero if it
343 * failed.
344 */
345int split_version(const char *version, unsigned int *value)
346{
347 const char *p, *s;
348 char *error;
349 int nelts;
350
351 /* Initialize array with zeroes */
352 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
353 value[nelts] = 0;
354 value[4] = 3;
355
356 p = version;
357
358 /* If the version number is empty, return false */
359 if (*p == '\0')
360 return 0;
361
362 /* Convert first number <a> */
363 value[0] = strtol(p, &error, 10);
364 p = error + 1;
365 if (*error == '\0')
366 return 1;
367 if (*error == '-')
368 goto split_version_tag;
369 if (*error != '.')
370 return 0;
371
372 /* Convert first number <b> */
373 value[1] = strtol(p, &error, 10);
374 p = error + 1;
375 if (*error == '\0')
376 return 1;
377 if (*error == '-')
378 goto split_version_tag;
379 if (*error != '.')
380 return 0;
381
382 /* Convert first number <c> */
383 value[2] = strtol(p, &error, 10);
384 p = error + 1;
385 if (*error == '\0')
386 return 1;
387 if (*error == '-')
388 goto split_version_tag;
389 if (*error != '.')
390 return 0;
391
392 /* Convert first number <d> */
393 value[3] = strtol(p, &error, 10);
394 p = error + 1;
395 if (*error == '\0')
396 return 1;
397 if (*error != '-')
398 return 0;
399
400 split_version_tag:
401 /* Check for commit number */
402 if (*p >= '0' && *p <= '9')
403 goto split_version_commit;
404
405 /* Read tag */
406 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
407 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
408 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
409 else
410 goto split_version_commit;
411
412 /* Convert tag number */
413 value[5] = strtol(p, &error, 10);
414 p = error + 1;
415 if (*error == '\0')
416 return 1;
417 if (*error != '-')
418 return 0;
419
420 split_version_commit:
421 /* Search the last "-" */
422 s = strrchr(p, '-');
423 if (s) {
424 s++;
425 if (*s == '\0')
426 return 0;
427 value[6] = strtol(s, &error, 10);
428 if (*error != '\0')
429 value[6] = 0;
430 return 1;
431 }
432
433 /* convert the version */
434 value[6] = strtol(p, &error, 10);
435 if (*error != '\0')
436 value[6] = 0;
437
438 return 1;
439}
440
441/* This function compares the current haproxy version with an arbitrary version
442 * string. It returns:
443 * -1 : the version in argument is older than the current haproxy version
444 * 0 : the version in argument is the same as the current haproxy version
445 * 1 : the version in argument is newer than the current haproxy version
446 *
447 * Or some errors:
448 * -2 : the current haproxy version is not parsable
449 * -3 : the version in argument is not parsable
450 */
451int compare_current_version(const char *version)
452{
453 unsigned int loc[VERSION_MAX_ELTS];
454 unsigned int mod[VERSION_MAX_ELTS];
455 int i;
456
457 /* split versions */
458 if (!split_version(haproxy_version, loc))
459 return -2;
460 if (!split_version(version, mod))
461 return -3;
462
463 /* compare versions */
464 for (i = 0; i < VERSION_MAX_ELTS; i++) {
465 if (mod[i] < loc[i])
466 return -1;
467 else if (mod[i] > loc[i])
468 return 1;
469 }
470 return 0;
471}
472
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100473static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200474{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200475 struct utsname utsname;
476
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200477 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100478 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100479
480 if (strlen(PRODUCT_URL_BUGS) > 0) {
481 char base_version[20];
482 int dots = 0;
483 char *del;
484
485 /* only retrieve the base version without distro-specific extensions */
486 for (del = haproxy_version; *del; del++) {
487 if (*del == '.')
488 dots++;
489 else if (*del < '0' || *del > '9')
490 break;
491 }
492
493 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
494 if (dots < 2)
495 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
496 else
497 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
498 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200499
500 if (uname(&utsname) == 0) {
501 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200503}
504
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100505static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100506{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100507 struct build_opts_str *item;
508
Willy Tarreau7b066db2007-12-02 11:28:59 +0100509 printf("Build options :"
510#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100511 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100512#endif
513#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100514 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100515#endif
516#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100517 "\n CC = " BUILD_CC
518#endif
519#ifdef BUILD_CFLAGS
520 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100521#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100522#ifdef BUILD_OPTIONS
523 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100524#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100525#ifdef BUILD_DEBUG
526 "\n DEBUG = " BUILD_DEBUG
527#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100528#ifdef BUILD_FEATURES
529 "\n\nFeature list : " BUILD_FEATURES
530#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200531 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100532 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200533 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100534 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200535
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100536 list_for_each_entry(item, &build_opts_list, list) {
537 puts(item->str);
538 }
539
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100540 putchar('\n');
541
Willy Tarreaube5b6852009-10-03 18:57:08 +0200542 list_pollers(stdout);
543 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200544 list_mux_proto(stdout);
545 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100546 list_services(stdout);
547 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100548 list_filters(stdout);
549 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100550}
551
Willy Tarreaubaaee002006-06-26 02:48:02 +0200552/*
553 * This function prints the command line usage and exits
554 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100555static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200556{
557 display_version();
558 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200559 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200560 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200561 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100562 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200563 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreau6e064432012-05-08 15:40:42 +0200564 " -dM[<byte>] poisons memory with <byte> (defaults to 0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200565 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200566 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200567 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100568#if defined(USE_SYSTEMD)
569 " -Ws master-worker mode with systemd notify support.\n"
570#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200571 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200572 " -c check mode : only check config files and exit\n"
Maximilian Maderfc0cceb2021-06-06 00:50:22 +0200573 " -cc check condition : evaluate a condition and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100574 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575 " -m limits the usable amount of memory (in MB)\n"
576 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200577 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200578 " -p writes pids of all children to this file\n"
Willy Tarreaue5733232019-05-22 19:24:06 +0200579#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 " -de disables epoll() usage even when available\n"
581#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200582#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200583 " -dk disables kqueue() usage even when available\n"
584#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200585#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000586 " -dv disables event ports usage even when available\n"
587#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200588#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 " -dp disables poll() usage even when available\n"
590#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200591#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100592 " -dS disables splice usage (broken on old kernels)\n"
593#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200594#if defined(USE_GETADDRINFO)
595 " -dG disables getaddrinfo() usage\n"
596#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000597#if defined(SO_REUSEPORT)
598 " -dR disables SO_REUSEPORT usage\n"
599#endif
Willy Tarreau654726d2021-12-28 15:43:11 +0100600#if defined(HA_HAVE_DUMP_LIBS)
601 " -dL dumps loaded object files after config checks\n"
602#endif
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100603 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100604 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200605 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200606 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200607 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200608 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200609 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100611 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200612 exit(1);
613}
614
615
616
617/*********************************************************************/
618/* more specific functions ***************************************/
619/*********************************************************************/
620
William Lallemand73b85e72017-06-01 17:38:51 +0200621/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
622 * pids the signal was correctly delivered to.
623 */
William Lallemande25473c2019-04-01 11:29:56 +0200624int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200625{
626 int p;
627 int ret = 0;
628 for (p = 0; p < nb_oldpids; p++)
629 if (kill(oldpids[p], sig) == 0)
630 ret++;
631 return ret;
632}
633
William Lallemand75ea0a02017-11-15 19:02:58 +0100634/*
William Lallemand73b85e72017-06-01 17:38:51 +0200635 * remove a pid forom the olpid array and decrease nb_oldpids
636 * return 1 pid was found otherwise return 0
637 */
638
639int delete_oldpid(int pid)
640{
641 int i;
642
643 for (i = 0; i < nb_oldpids; i++) {
644 if (oldpids[i] == pid) {
645 oldpids[i] = oldpids[nb_oldpids - 1];
646 oldpids[nb_oldpids - 1] = 0;
647 nb_oldpids--;
648 return 1;
649 }
650 }
651 return 0;
652}
653
William Lallemand85b0bd92017-06-01 17:38:53 +0200654
William Lallemand73b85e72017-06-01 17:38:51 +0200655/*
656 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800657 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200658 */
William Lallemandfab0fdc2021-11-09 18:01:22 +0100659static void mworker_reexec()
William Lallemand73b85e72017-06-01 17:38:51 +0200660{
William Lallemand00417412020-06-05 14:08:41 +0200661 char **next_argv = NULL;
662 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200663 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200664 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200665 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100666 struct rlimit limit;
William Lallemand2be557f2021-11-24 18:45:37 +0100667 struct mworker_proc *current_child = NULL;
William Lallemand73b85e72017-06-01 17:38:51 +0200668
669 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100670#if defined(USE_SYSTEMD)
671 if (global.tune.options & GTUNE_USE_SYSTEMD)
672 sd_notify(0, "RELOADING=1");
673#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200674 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
675
William Lallemand55a921c2022-01-28 21:17:30 +0100676 mworker_cleanup_proc();
William Lallemandbc193052018-09-11 10:06:26 +0200677 mworker_proc_list_to_env(); /* put the children description in the env */
678
William Lallemandc4810b82021-11-18 10:51:30 +0100679 /* ensure that we close correctly every listeners before reexecuting */
680 mworker_cleanlisteners();
681
William Lallemand7c756a82018-11-26 11:53:40 +0100682 /* during the reload we must ensure that every FDs that can't be
683 * reuse (ie those that are not referenced in the proc_list)
684 * are closed or they will leak. */
685
686 /* close the listeners FD */
687 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200688
William Lallemand67e371e2021-11-25 10:03:44 +0100689 if (fdtab)
690 deinit_pollers();
William Lallemandefd95472021-11-26 14:43:57 +0100691
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500692#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200693 /* close random device FDs */
694 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100695#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100696
Willy Tarreau8dca1952019-03-01 10:21:55 +0100697 /* restore the initial FD limits */
698 limit.rlim_cur = rlim_fd_cur_at_boot;
699 limit.rlim_max = rlim_fd_max_at_boot;
700 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
701 getrlimit(RLIMIT_NOFILE, &limit);
702 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
703 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
704 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
705 }
706
William Lallemand73b85e72017-06-01 17:38:51 +0200707 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200708 while (old_argv[old_argc])
709 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200710
William Lallemand85b0bd92017-06-01 17:38:53 +0200711 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200712 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200713 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200714 if (next_argv == NULL)
715 goto alloc_error;
716
William Lallemand00417412020-06-05 14:08:41 +0200717 /* copy the program name */
718 next_argv[next_argc++] = old_argv[0];
719
720 /* insert the new options just after argv[0] in case we have a -- */
721
William Lallemandbefab9e2021-11-25 00:49:19 +0100722 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
723 /* add -sf <PID>* to argv */
724 if (mworker_child_nb() > 0) {
725 struct mworker_proc *child;
William Lallemand3f128872019-04-01 11:29:59 +0200726
William Lallemandbefab9e2021-11-25 00:49:19 +0100727 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200728
William Lallemandbefab9e2021-11-25 00:49:19 +0100729 list_for_each_entry(child, &proc_list, list) {
730 if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
731 current_child = child;
William Lallemand2be557f2021-11-24 18:45:37 +0100732
William Lallemandbefab9e2021-11-25 00:49:19 +0100733 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
734 continue;
735 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
736 goto alloc_error;
737 msg = NULL;
738 }
William Lallemand73b85e72017-06-01 17:38:51 +0200739 }
William Lallemand2be557f2021-11-24 18:45:37 +0100740
741 if (current_child) {
742 /* add the -x option with the socketpair of the current worker */
743 next_argv[next_argc++] = "-x";
744 if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
745 goto alloc_error;
746 msg = NULL;
747 }
William Lallemand85b0bd92017-06-01 17:38:53 +0200748 }
749
William Lallemand00417412020-06-05 14:08:41 +0200750 /* copy the previous options */
751 for (i = 1; i < old_argc; i++)
752 next_argv[next_argc++] = old_argv[i];
753
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200754 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100755 execvp(next_argv[0], next_argv);
Christopher Faulet767a84b2017-11-24 16:50:31 +0100756 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100757 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100758 return;
759
William Lallemand73b85e72017-06-01 17:38:51 +0200760alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100761 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800762 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200763 return;
764}
765
William Lallemandfab0fdc2021-11-09 18:01:22 +0100766/* reexec haproxy in waitmode */
767static void mworker_reexec_waitmode()
768{
769 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
770 mworker_reexec();
771}
772
773/* reload haproxy and emit a warning */
774void mworker_reload()
775{
William Lallemandad221f42021-11-09 18:43:59 +0100776 struct mworker_proc *child;
William Lallemandefd95472021-11-26 14:43:57 +0100777 struct per_thread_deinit_fct *ptdf;
William Lallemandad221f42021-11-09 18:43:59 +0100778
William Lallemand836bda22021-11-09 18:16:47 +0100779 ha_notice("Reloading HAProxy\n");
William Lallemandad221f42021-11-09 18:43:59 +0100780
William Lallemandefd95472021-11-26 14:43:57 +0100781 /* close the poller FD and the thread waker pipe FD */
782 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
783 ptdf->fct();
784
William Lallemandad221f42021-11-09 18:43:59 +0100785 /* increment the number of reloads */
786 list_for_each_entry(child, &proc_list, list) {
787 child->reloads++;
788 }
789
William Lallemandfab0fdc2021-11-09 18:01:22 +0100790 mworker_reexec();
791}
792
William Lallemandb3f2be32018-09-11 10:06:18 +0200793static void mworker_loop()
794{
795
796#if defined(USE_SYSTEMD)
797 if (global.tune.options & GTUNE_USE_SYSTEMD)
798 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
799#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200800 /* Busy polling makes no sense in the master :-) */
801 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200802
William Lallemandbc193052018-09-11 10:06:26 +0200803
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100804 signal_unregister(SIGTTIN);
805 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100806 signal_unregister(SIGUSR1);
807 signal_unregister(SIGHUP);
808 signal_unregister(SIGQUIT);
809
William Lallemandb3f2be32018-09-11 10:06:18 +0200810 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
811 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100812 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
813 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200814 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
815 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
816 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
817 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
818
819 mworker_unblock_signals();
William Lallemand27f3fa52018-12-06 14:05:20 +0100820 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200821
William Lallemandbc193052018-09-11 10:06:26 +0200822 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
823 some SIGCHLD were lost */
824
William Lallemandb3f2be32018-09-11 10:06:18 +0200825 global.nbthread = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200826
William Lallemand2672eb92018-12-14 15:52:39 +0100827#ifdef USE_THREAD
828 tid_bit = 1;
829 all_threads_mask = 1;
830#endif
831
William Lallemandb3f2be32018-09-11 10:06:18 +0200832 jobs++; /* this is the "master" job, we want to take care of the
833 signals even if there is no listener so the poll loop don't
834 leave */
835
836 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200837 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200838}
William Lallemandcb11fd22017-06-01 17:38:52 +0200839
840/*
841 * Reexec the process in failure mode, instead of exiting
842 */
843void reexec_on_failure()
844{
William Lallemand68836742021-11-10 10:49:06 +0100845 struct mworker_proc *child;
846
William Lallemandcb11fd22017-06-01 17:38:52 +0200847 if (!atexit_flag)
848 return;
William Lallemand68836742021-11-10 10:49:06 +0100849
850 /* get the info of the children in the env */
851 if (mworker_env_to_proc_list() < 0) {
852 exit(EXIT_FAILURE);
853 }
854
855 /* increment the number of failed reloads */
856 list_for_each_entry(child, &proc_list, list) {
857 child->failedreloads++;
858 }
859
Willy Tarreaue08acae2022-01-28 18:40:06 +0100860 /* do not keep unused FDs retrieved from the previous process */
861 sock_drop_unused_old_sockets();
862
William Lallemandfab0fdc2021-11-09 18:01:22 +0100863 usermsgs_clr(NULL);
William Lallemand836bda22021-11-09 18:16:47 +0100864 ha_warning("Loading failure!\n");
William Lallemandfab0fdc2021-11-09 18:01:22 +0100865 mworker_reexec_waitmode();
William Lallemandcb11fd22017-06-01 17:38:52 +0200866}
William Lallemand73b85e72017-06-01 17:38:51 +0200867
868
869/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200870 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
871 * a signal zero to all subscribers. This means that it's as easy as
872 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200873 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100874static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200875{
876 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200877 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100878 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200879}
880
881/*
882 * upon SIGTTOU, we pause everything
883 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100884static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200885{
Willy Tarreau775e0012020-09-24 16:36:26 +0200886 if (protocol_pause_all() & ERR_FATAL) {
887 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200888 ha_warning("%s", msg);
889 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200890 soft_stop();
891 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100892 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200893}
894
895/*
896 * upon SIGTTIN, let's have a soft stop.
897 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100898static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200899{
Willy Tarreau775e0012020-09-24 16:36:26 +0200900 if (protocol_resume_all() & ERR_FATAL) {
901 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 +0200902 ha_warning("%s", msg);
903 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200904 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905}
906
907/*
908 * this function dumps every server's state when the process receives SIGHUP.
909 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100910static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200911{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100912 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913
Christopher Faulet767a84b2017-11-24 16:50:31 +0100914 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200915 while (p) {
916 struct server *s = p->srv;
917
918 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
919 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100920 chunk_printf(&trash,
921 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
922 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200923 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200924 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200925 ha_warning("%s\n", trash.area);
926 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 s = s->next;
928 }
929
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200930 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
931 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100932 chunk_printf(&trash,
933 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
934 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200935 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 +0200936 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100937 chunk_printf(&trash,
938 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
939 p->id,
940 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200941 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 +0200942 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100943 chunk_printf(&trash,
944 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
945 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
946 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200947 p->feconn, p->beconn, p->totpend, p->queue.length, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200949 ha_warning("%s\n", trash.area);
950 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951
952 p = p->next;
953 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954}
955
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100956static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200958 /* dump memory usage then free everything possible */
959 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100960 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961}
962
William Lallemande1340412017-12-28 16:09:36 +0100963/*
964 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
965 * If <fd> < 0, it opens /dev/null and use it to dup
966 *
967 * In the case of chrooting, you have to open /dev/null before the chroot, and
968 * pass the <fd> to this function
969 */
970static void stdio_quiet(int fd)
971{
972 if (fd < 0)
973 fd = open("/dev/null", O_RDWR, 0);
974
975 if (fd > -1) {
976 fclose(stdin);
977 fclose(stdout);
978 fclose(stderr);
979
980 dup2(fd, 0);
981 dup2(fd, 1);
982 dup2(fd, 2);
983 if (fd > 2)
984 close(fd);
985 return;
986 }
987
988 ha_alert("Cannot open /dev/null\n");
989 exit(EXIT_FAILURE);
990}
991
992
Joseph Herlant03420902018-11-15 10:41:50 -0800993/* This function checks if cfg_cfgfiles contains directories.
994 * If it finds one, it adds all the files (and only files) it contains
995 * in cfg_cfgfiles in place of the directory (and removes the directory).
996 * It adds the files in lexical order.
997 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200998 * It doesn't add files with name starting with '.'
999 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001000static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001001{
1002 struct wordlist *wl, *wlb;
1003 char *err = NULL;
1004
1005 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1006 struct stat file_stat;
1007 struct dirent **dir_entries = NULL;
1008 int dir_entries_nb;
1009 int dir_entries_it;
1010
1011 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001012 ha_alert("Cannot open configuration file/directory %s : %s\n",
1013 wl->s,
1014 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001015 exit(1);
1016 }
1017
1018 if (!S_ISDIR(file_stat.st_mode))
1019 continue;
1020
1021 /* from this point wl->s is a directory */
1022
1023 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1024 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001025 ha_alert("Cannot open configuration directory %s : %s\n",
1026 wl->s,
1027 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001028 exit(1);
1029 }
1030
1031 /* for each element in the directory wl->s */
1032 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1033 struct dirent *dir_entry = dir_entries[dir_entries_it];
1034 char *filename = NULL;
1035 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1036
1037 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001038 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001039 */
1040 if (dir_entry->d_name[0] == '.' ||
1041 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1042 goto next_dir_entry;
1043
1044 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001045 ha_alert("Cannot load configuration files %s : out of memory.\n",
1046 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001047 exit(1);
1048 }
1049
1050 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001051 ha_alert("Cannot open configuration file %s : %s\n",
1052 wl->s,
1053 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001054 exit(1);
1055 }
1056
1057 /* don't add anything else than regular file in cfg_cfgfiles
1058 * this way we avoid loops
1059 */
1060 if (!S_ISREG(file_stat.st_mode))
1061 goto next_dir_entry;
1062
1063 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001064 ha_alert("Cannot load configuration files %s : %s\n",
1065 filename,
1066 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001067 exit(1);
1068 }
1069
1070next_dir_entry:
1071 free(filename);
1072 free(dir_entry);
1073 }
1074
1075 free(dir_entries);
1076
1077 /* remove the current directory (wl) from cfg_cfgfiles */
1078 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001079 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001080 free(wl);
1081 }
1082
1083 free(err);
1084}
1085
Willy Tarreaubaaee002006-06-26 02:48:02 +02001086/*
William Lallemand73b85e72017-06-01 17:38:51 +02001087 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001088 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001089 * Return an allocated copy of argv
1090 */
1091
1092static char **copy_argv(int argc, char **argv)
1093{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001094 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001095
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001096 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001097 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001098 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001099 return NULL;
1100 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001101 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001102
William Lallemanddf6c5a82020-06-04 17:40:23 +02001103 /* first copy argv[0] */
1104 *newargv++ = *argv++;
1105 argc--;
1106
1107 while (argc > 0) {
1108 if (**argv != '-') {
1109 /* non options are copied but will fail in the argument parser */
1110 *newargv++ = *argv++;
1111 argc--;
1112
1113 } else {
1114 char *flag;
1115
1116 flag = *argv + 1;
1117
1118 if (flag[0] == '-' && flag[1] == 0) {
1119 /* "--\0" copy every arguments till the end of argv */
1120 *newargv++ = *argv++;
1121 argc--;
1122
1123 while (argc > 0) {
1124 *newargv++ = *argv++;
1125 argc--;
1126 }
1127 } else {
1128 switch (*flag) {
1129 case 's':
1130 /* -sf / -st and their parameters are ignored */
1131 if (flag[1] == 'f' || flag[1] == 't') {
1132 argc--;
1133 argv++;
1134 /* The list can't contain a negative value since the only
1135 way to know the end of this list is by looking for the
1136 next option or the end of the options */
1137 while (argc > 0 && argv[0][0] != '-') {
1138 argc--;
1139 argv++;
1140 }
William Lallemand398da622020-09-02 16:12:23 +02001141 } else {
1142 argc--;
1143 argv++;
1144
William Lallemanddf6c5a82020-06-04 17:40:23 +02001145 }
1146 break;
1147
1148 case 'x':
1149 /* this option and its parameter are ignored */
1150 argc--;
1151 argv++;
1152 if (argc > 0) {
1153 argc--;
1154 argv++;
1155 }
1156 break;
1157
1158 case 'C':
1159 case 'n':
1160 case 'm':
1161 case 'N':
1162 case 'L':
1163 case 'f':
1164 case 'p':
1165 case 'S':
1166 /* these options have only 1 parameter which must be copied and can start with a '-' */
1167 *newargv++ = *argv++;
1168 argc--;
1169 if (argc == 0)
1170 goto error;
1171 *newargv++ = *argv++;
1172 argc--;
1173 break;
1174 default:
1175 /* for other options just copy them without parameters, this is also done
1176 * for options like "--foo", but this will fail in the argument parser.
1177 * */
1178 *newargv++ = *argv++;
1179 argc--;
1180 break;
1181 }
William Lallemand73b85e72017-06-01 17:38:51 +02001182 }
1183 }
William Lallemand73b85e72017-06-01 17:38:51 +02001184 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001185
William Lallemanddf6c5a82020-06-04 17:40:23 +02001186 return retargv;
1187
1188error:
1189 free(retargv);
1190 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001191}
1192
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001193
1194/* Performs basic random seed initialization. The main issue with this is that
1195 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1196 * which means that there will only be 4 billion possible random sequences once
1197 * srandom() is called, regardless of the internal state. Not calling it is
1198 * even worse as we'll always produce the same randoms sequences. What we do
1199 * here is to create an initial sequence from various entropy sources, hash it
1200 * using SHA1 and keep the resulting 160 bits available globally.
1201 *
1202 * We initialize the current process with the first 32 bits before starting the
1203 * polling loop, where all this will be changed to have process specific and
1204 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001205 *
1206 * Before starting threads, it's still possible to call random() as srandom()
1207 * is initialized from this, but after threads and/or processes are started,
1208 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001209 */
1210static void ha_random_boot(char *const *argv)
1211{
1212 unsigned char message[256];
1213 unsigned char *m = message;
1214 struct timeval tv;
1215 blk_SHA_CTX ctx;
1216 unsigned long l;
1217 int fd;
1218 int i;
1219
1220 /* start with current time as pseudo-random seed */
1221 gettimeofday(&tv, NULL);
1222 write_u32(m, tv.tv_sec); m += 4;
1223 write_u32(m, tv.tv_usec); m += 4;
1224
1225 /* PID and PPID add some OS-based randomness */
1226 write_u16(m, getpid()); m += 2;
1227 write_u16(m, getppid()); m += 2;
1228
1229 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1230 fd = open("/dev/urandom", O_RDONLY);
1231 if (fd >= 0) {
1232 i = read(fd, m, 20);
1233 if (i > 0)
1234 m += i;
1235 close(fd);
1236 }
1237
1238 /* take up to 160 bits bytes from openssl (non-blocking) */
1239#ifdef USE_OPENSSL
1240 if (RAND_bytes(m, 20) == 1)
1241 m += 20;
1242#endif
1243
1244 /* take 160 bits from existing random in case it was already initialized */
1245 for (i = 0; i < 5; i++) {
1246 write_u32(m, random());
1247 m += 4;
1248 }
1249
1250 /* stack address (benefit form operating system's ASLR) */
1251 l = (unsigned long)&m;
1252 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1253
1254 /* argv address (benefit form operating system's ASLR) */
1255 l = (unsigned long)&argv;
1256 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1257
1258 /* use tv_usec again after all the operations above */
1259 gettimeofday(&tv, NULL);
1260 write_u32(m, tv.tv_usec); m += 4;
1261
1262 /*
1263 * At this point, ~84-92 bytes have been used
1264 */
1265
1266 /* finish with the hostname */
1267 strncpy((char *)m, hostname, message + sizeof(message) - m);
1268 m += strlen(hostname);
1269
1270 /* total message length */
1271 l = m - message;
1272
1273 memset(&ctx, 0, sizeof(ctx));
1274 blk_SHA1_Init(&ctx);
1275 blk_SHA1_Update(&ctx, message, l);
1276 blk_SHA1_Final(boot_seed, &ctx);
1277
1278 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001279 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001280}
1281
Willy Tarreau5a023f02019-03-01 14:19:31 +01001282/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1283 * setting, and returns it. It may return -1 meaning "unlimited" if some
1284 * unlimited proxies have been found and the global.maxconn value is not yet
1285 * set. It may also return a value greater than maxconn if it's not yet set.
1286 * Note that a value of zero means there is no need for pipes. -1 is never
1287 * returned if global.maxconn is valid.
1288 */
1289static int compute_ideal_maxpipes()
1290{
1291 struct proxy *cur;
1292 int nbfe = 0, nbbe = 0;
1293 int unlimited = 0;
1294 int pipes;
1295 int max;
1296
1297 for (cur = proxies_list; cur; cur = cur->next) {
1298 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1299 if (cur->cap & PR_CAP_FE) {
1300 max = cur->maxconn;
1301 nbfe += max;
1302 if (!max) {
1303 unlimited = 1;
1304 break;
1305 }
1306 }
1307 if (cur->cap & PR_CAP_BE) {
1308 max = cur->fullconn ? cur->fullconn : global.maxconn;
1309 nbbe += max;
1310 if (!max) {
1311 unlimited = 1;
1312 break;
1313 }
1314 }
1315 }
1316 }
1317
1318 pipes = MAX(nbfe, nbbe);
1319 if (global.maxconn) {
1320 if (pipes > global.maxconn || unlimited)
1321 pipes = global.maxconn;
1322 } else if (unlimited) {
1323 pipes = -1;
1324 }
1325
1326 return pipes >= 4 ? pipes / 4 : pipes;
1327}
1328
Willy Tarreauac350932019-03-01 15:43:14 +01001329/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1330 * rlimits and computes an ideal maxconn. It's meant to be called only when
1331 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001332 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1333 * default 100) is returned as it is expected that it will even run on tight
1334 * environments, and will maintain compatibility with previous packages that
1335 * used to rely on this value as the default one. The system will emit a
1336 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001337 */
1338static int compute_ideal_maxconn()
1339{
1340 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1341 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1342 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001343 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001344 int maxconn;
1345
1346 /* we have to take into account these elements :
1347 * - number of engine_fds, which inflates the number of FD needed per
1348 * connection by this number.
1349 * - number of pipes per connection on average : for the unlimited
1350 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1351 * fixed value of 2*pipes.
1352 * - two FDs per connection
1353 */
1354
1355 /* subtract listeners and checks */
1356 remain -= global.maxsock;
1357
Willy Tarreau3f200852019-03-14 19:13:17 +01001358 /* one epoll_fd/kqueue_fd per thread */
1359 remain -= global.nbthread;
1360
1361 /* one wake-up pipe (2 fd) per thread */
1362 remain -= 2 * global.nbthread;
1363
Willy Tarreauac350932019-03-01 15:43:14 +01001364 /* Fixed pipes values : we only subtract them if they're not larger
1365 * than the remaining FDs because pipes are optional.
1366 */
1367 if (pipes >= 0 && pipes * 2 < remain)
1368 remain -= pipes * 2;
1369
1370 if (pipes < 0) {
1371 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1372 * = maxconn * (2 + 0.5 + engine_fds)
1373 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1374 */
1375 maxconn = 2 * remain / (5 + 2 * engine_fds);
1376 } else {
1377 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1378 * = maxconn * (2 + engine_fds)
1379 */
1380 maxconn = remain / (2 + engine_fds);
1381 }
1382
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001383 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001384}
1385
Willy Tarreaua409f302020-03-10 17:08:53 +01001386/* computes the estimated maxsock value for the given maxconn based on the
1387 * possibly set global.maxpipes and existing partial global.maxsock. It may
1388 * temporarily change global.maxconn for the time needed to propagate the
1389 * computations, and will reset it.
1390 */
1391static int compute_ideal_maxsock(int maxconn)
1392{
1393 int maxpipes = global.maxpipes;
1394 int maxsock = global.maxsock;
1395
1396
1397 if (!maxpipes) {
1398 int old_maxconn = global.maxconn;
1399
1400 global.maxconn = maxconn;
1401 maxpipes = compute_ideal_maxpipes();
1402 global.maxconn = old_maxconn;
1403 }
1404
1405 maxsock += maxconn * 2; /* each connection needs two sockets */
1406 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1407 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1408 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1409
1410 /* compute fd used by async engines */
1411 if (global.ssl_used_async_engines) {
1412 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1413
1414 maxsock += maxconn * sides * global.ssl_used_async_engines;
1415 }
1416 return maxsock;
1417}
1418
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001419/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001420 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1421 * value is accepted, non-zero otherwise. This is used to determine if an
1422 * automatic limit may be applied or not. When it is not, the caller knows that
1423 * the highest we can do is the rlim_max at boot. In case of error, we return
1424 * that the setting is possible, so that we defer the error processing to the
1425 * final stage in charge of enforcing this.
1426 */
1427static int check_if_maxsock_permitted(int maxsock)
1428{
1429 struct rlimit orig_limit, test_limit;
1430 int ret;
1431
1432 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1433 return 1;
1434
1435 /* don't go further if we can't even set to what we have */
1436 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1437 return 1;
1438
1439 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1440 test_limit.rlim_cur = test_limit.rlim_max;
1441 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1442
1443 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1444 return 1;
1445
1446 return ret == 0;
1447}
1448
Amaury Denoyelle484454d2021-05-05 16:18:45 +02001449void mark_tainted(const enum tainted_flags flag)
1450{
1451 HA_ATOMIC_OR(&tainted, flag);
1452}
1453
1454unsigned int get_tainted()
1455{
1456 int tainted_state;
1457 HA_ATOMIC_STORE(&tainted_state, tainted);
1458 return tainted_state;
1459}
Willy Tarreau304e17e2020-03-10 17:54:54 +01001460
William Lallemand73b85e72017-06-01 17:38:51 +02001461/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462 * This function initializes all the necessary variables. It only returns
1463 * if everything is OK. If something fails, it exits.
1464 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001465static void init(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001466{
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467 int arg_mode = 0; /* MODE_DEBUG, ... */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468 char *tmp;
1469 char *cfg_pidfile = NULL;
Willy Tarreau058e9072009-07-20 09:30:05 +02001470 int err_code = 0;
Maxime de Roucy0f503922016-05-13 23:52:55 +02001471 char *err_msg = NULL;
Willy Tarreau477ecd82010-01-03 21:12:30 +01001472 struct wordlist *wl;
Kevinm48936af2010-12-22 16:08:21 +00001473 char *progname;
Willy Tarreau576132e2011-09-10 19:26:56 +02001474 char *change_dir = NULL;
Christopher Fauletd7c91962015-04-30 11:48:27 +02001475 struct proxy *px;
Willy Tarreaue6945732016-12-21 19:57:00 +01001476 struct post_check_fct *pcf;
Willy Tarreauac350932019-03-01 15:43:14 +01001477 int ideal_maxconn;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001478 char *check_condition = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001479
Christopher Faulete3a5e352017-10-24 13:53:54 +02001480 global.mode = MODE_STARTING;
William Lallemand00417412020-06-05 14:08:41 +02001481 old_argv = copy_argv(argc, argv);
1482 if (!old_argv) {
William Lallemanddf6c5a82020-06-04 17:40:23 +02001483 ha_alert("failed to copy argv.\n");
1484 exit(1);
1485 }
William Lallemand73b85e72017-06-01 17:38:51 +02001486
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001487 if (!init_trash_buffers(1)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001488 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet748919a2017-07-26 14:59:46 +02001489 exit(1);
1490 }
David du Colombier7af46052012-05-16 14:16:48 +02001491
Emeric Brun2b920a12010-09-23 18:30:22 +02001492 /* NB: POSIX does not make it mandatory for gethostname() to NULL-terminate
1493 * the string in case of truncation, and at least FreeBSD appears not to do
1494 * it.
1495 */
1496 memset(hostname, 0, sizeof(hostname));
1497 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001498
1499 if ((localpeer = strdup(hostname)) == NULL) {
1500 ha_alert("Cannot allocate memory for local peer.\n");
1501 exit(EXIT_FAILURE);
1502 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001503 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Emeric Brun2b920a12010-09-23 18:30:22 +02001504
William Lallemand24c928c2020-01-14 17:58:18 +01001505 /* we were in mworker mode, we should restart in mworker mode */
1506 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1507 global.mode |= MODE_MWORKER;
1508
Willy Tarreaubaaee002006-06-26 02:48:02 +02001509 /*
1510 * Initialize the previously static variables.
1511 */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001512
Willy Tarreau173d9952018-01-26 21:48:23 +01001513 totalconn = actconn = listeners = stopping = 0;
Cyril Bonté203ec5a2017-03-23 22:44:13 +01001514 killed = 0;
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001515
Willy Tarreaubaaee002006-06-26 02:48:02 +02001516
1517#ifdef HAPROXY_MEMMAX
Willy Tarreau70060452015-12-14 12:46:07 +01001518 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001519#endif
1520
Benoit GARNIERb413c2a2016-03-27 11:08:03 +02001521 tzset();
Willy Tarreau55542642021-10-08 09:33:24 +02001522 clock_init_process_date();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001523 start_date = now;
1524
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001525 ha_random_boot(argv);
Willy Tarreau84310e22014-02-14 11:59:04 +01001526
Willy Tarreau8ed669b2013-01-11 15:49:37 +01001527 if (init_acl() != 0)
1528 exit(1);
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001529
Amaury Denoyellec593bcd2021-05-19 15:35:29 +02001530#ifdef USE_OPENSSL
1531 /* Initialize the random generator.
1532 * Must be called before chroot for access to /dev/urandom
1533 */
1534 if (!ssl_initialize_random()) {
1535 ha_alert("OpenSSL random data generator initialization failed.\n");
1536 exit(1);
1537 }
1538#endif
1539
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001540 /* Initialise lua. */
1541 hlua_init();
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001542
Christopher Fauletff2613e2016-11-09 11:36:17 +01001543 /* Initialize process vars */
Willy Tarreaub7bfcb32021-08-31 08:13:25 +02001544 vars_init_head(&proc_vars, SCOPE_PROC);
Christopher Fauletff2613e2016-11-09 11:36:17 +01001545
Willy Tarreau43b78992009-01-25 15:42:27 +01001546 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001547#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001548 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001549#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001550#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001551 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001552#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001553#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001554 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001555#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001556#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001557 global.tune.options |= GTUNE_USE_EVPORTS;
1558#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001559#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001560 global.tune.options |= GTUNE_USE_SPLICE;
1561#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001562#if defined(USE_GETADDRINFO)
1563 global.tune.options |= GTUNE_USE_GAI;
1564#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001565#if defined(SO_REUSEPORT)
1566 global.tune.options |= GTUNE_USE_REUSEPORT;
1567#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001568#ifdef USE_THREAD
1569 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1570#endif
William Dauchya5194602020-03-28 19:29:58 +01001571 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001572
1573 pid = getpid();
1574 progname = *argv;
1575 while ((tmp = strchr(progname, '/')) != NULL)
1576 progname = tmp + 1;
1577
Kevinm48936af2010-12-22 16:08:21 +00001578 /* the process name is used for the logs only */
Eric Salama7cea6062020-10-02 11:58:19 +02001579 chunk_initlen(&global.log_tag, strdup(progname), strlen(progname), strlen(progname));
1580 if (b_orig(&global.log_tag) == NULL) {
1581 chunk_destroy(&global.log_tag);
1582 ha_alert("Cannot allocate memory for log_tag.\n");
1583 exit(EXIT_FAILURE);
1584 }
Kevinm48936af2010-12-22 16:08:21 +00001585
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 argc--; argv++;
1587 while (argc > 0) {
1588 char *flag;
1589
1590 if (**argv == '-') {
1591 flag = *argv+1;
1592
1593 /* 1 arg */
1594 if (*flag == 'v') {
1595 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001596 if (flag[1] == 'v') /* -vv */
1597 display_build_opts();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 exit(0);
1599 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001600#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001602 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001604#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001606 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001608#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001609 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001610 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001611#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001612#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001613 else if (*flag == 'd' && flag[1] == 'v')
1614 global.tune.options &= ~GTUNE_USE_EVPORTS;
1615#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001616#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001617 else if (*flag == 'd' && flag[1] == 'S')
1618 global.tune.options &= ~GTUNE_USE_SPLICE;
1619#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001620#if defined(USE_GETADDRINFO)
1621 else if (*flag == 'd' && flag[1] == 'G')
1622 global.tune.options &= ~GTUNE_USE_GAI;
1623#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001624#if defined(SO_REUSEPORT)
1625 else if (*flag == 'd' && flag[1] == 'R')
1626 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1627#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001628 else if (*flag == 'd' && flag[1] == 'V')
1629 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001630 else if (*flag == 'V')
1631 arg_mode |= MODE_VERBOSE;
1632 else if (*flag == 'd' && flag[1] == 'b')
1633 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001634 else if (*flag == 'd' && flag[1] == 'D')
1635 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001636 else if (*flag == 'd' && flag[1] == 'W')
1637 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreau6e064432012-05-08 15:40:42 +02001638 else if (*flag == 'd' && flag[1] == 'M')
1639 mem_poison_byte = flag[2] ? strtol(flag + 2, NULL, 0) : 'P';
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001640 else if (*flag == 'd' && flag[1] == 'r')
1641 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreau654726d2021-12-28 15:43:11 +01001642#if defined(HA_HAVE_DUMP_LIBS)
1643 else if (*flag == 'd' && flag[1] == 'L')
1644 arg_mode |= MODE_DUMP_LIBS;
1645#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001646 else if (*flag == 'd')
1647 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001648 else if (*flag == 'c' && flag[1] == 'c') {
1649 arg_mode |= MODE_CHECK_CONDITION;
1650 argv++;
1651 argc--;
1652 check_condition = *argv;
1653 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001654 else if (*flag == 'c')
1655 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001656 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001657 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001658 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001659 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001660#if defined(USE_SYSTEMD)
1661 global.tune.options |= GTUNE_USE_SYSTEMD;
1662#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001663 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 +01001664 usage(progname);
1665#endif
1666 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001667 else if (*flag == 'W')
1668 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001669 else if (*flag == 'q')
1670 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001671 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001672 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001673 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001674 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001675 }
William Lallemand4fc09692017-06-19 16:37:19 +02001676 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001677 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001678 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001679
Olivier Houchardf73629d2017-04-05 22:33:04 +02001680 argv++;
1681 argc--;
1682 }
William Lallemande7361152018-10-26 14:47:36 +02001683 else if (*flag == 'S') {
1684 struct wordlist *c;
1685
William Lallemanda6b32492020-06-04 23:49:20 +02001686 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001687 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1688 usage(progname);
1689 }
1690 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1691 ha_alert("Cannot allocate memory\n");
1692 exit(EXIT_FAILURE);
1693 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001694 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001695
1696 argv++;
1697 argc--;
1698 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001699 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1700 /* list of pids to finish ('f') or terminate ('t') */
1701
1702 if (flag[1] == 'f')
1703 oldpids_sig = SIGUSR1; /* finish then exit */
1704 else
1705 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001706 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001707 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001708 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1709 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001710 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001711 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001713 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001714 errno = 0;
1715 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1716 if (errno) {
1717 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1718 flag,
1719 *argv, strerror(errno));
1720 exit(1);
1721 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001722 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001723 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001724 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1725 flag, endptr);
1726 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001727 }
Chris Lane236062f2018-02-05 23:15:44 +00001728 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001729 if (oldpids[nb_oldpids] <= 0)
1730 usage(progname);
1731 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001732 }
1733 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001734 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1735 /* now that's a cfgfile list */
1736 argv++; argc--;
1737 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001738 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001739 ha_alert("Cannot load configuration file/directory %s : %s\n",
1740 *argv,
1741 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001742 exit(1);
1743 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001744 argv++; argc--;
1745 }
1746 break;
1747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001748 else { /* >=2 args */
1749 argv++; argc--;
1750 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001751 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001752
1753 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001754 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001755 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001756 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001757 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001758 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001759 free(localpeer);
1760 if ((localpeer = strdup(*argv)) == NULL) {
1761 ha_alert("Cannot allocate memory for local peer.\n");
1762 exit(EXIT_FAILURE);
1763 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001764 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001765 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001766 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001767 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001768 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001769 ha_alert("Cannot load configuration file/directory %s : %s\n",
1770 *argv,
1771 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001772 exit(1);
1773 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001774 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775 case 'p' : cfg_pidfile = *argv; break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001776 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001777 }
1778 }
1779 }
1780 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001781 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001782 argv++; argc--;
1783 }
1784
Christopher Faulete3a5e352017-10-24 13:53:54 +02001785 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001786 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Willy Tarreau654726d2021-12-28 15:43:11 +01001787 | MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001788
William Lallemand944e6192018-11-21 15:48:31 +01001789 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001790 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001791 global.mode |= MODE_MWORKER_WAIT;
1792 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001793 }
1794
Willy Tarreau26146192021-07-21 10:01:36 +02001795 if ((global.mode & (MODE_MWORKER | MODE_CHECK | MODE_CHECK_CONDITION)) == MODE_MWORKER &&
1796 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001797 atexit_flag = 1;
1798 atexit(reexec_on_failure);
1799 }
1800
Willy Tarreau576132e2011-09-10 19:26:56 +02001801 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001802 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001803 exit(1);
1804 }
1805
Willy Tarreaubaaee002006-06-26 02:48:02 +02001806 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001807
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001808#ifdef USE_CPU_AFFINITY
1809 {
1810 int i;
Willy Tarreau44ea6312021-06-15 08:57:56 +02001811 ha_cpuset_zero(&cpu_map.proc);
1812 ha_cpuset_zero(&cpu_map.proc_t1);
Willy Tarreau26f42a02021-05-14 08:26:38 +02001813 for (i = 0; i < MAX_THREADS; ++i) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02001814 ha_cpuset_zero(&cpu_map.thread[i]);
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001815 }
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001816 }
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001817#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001818
Amaury Denoyelle11124302021-06-04 18:22:08 +02001819 usermsgs_clr("config");
1820
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001821 if (global.mode & MODE_CHECK_CONDITION) {
1822 int result;
1823
1824 uint32_t err;
1825 const char *errptr;
1826 char *errmsg = NULL;
1827
1828 char *args[MAX_LINE_ARGS+1];
1829 int arg = sizeof(args) / sizeof(*args);
1830 size_t outlen = strlen(check_condition) + 1;
Willy Tarreauc8194c32021-07-16 16:38:58 +02001831 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001832
1833 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02001834 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001835 &errptr);
1836
1837 if (err & PARSE_ERR_QUOTE) {
1838 ha_alert("Syntax Error in condition: Unmatched quote.\n");
1839 exit(2);
1840 }
1841
1842 if (err & PARSE_ERR_HEX) {
1843 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
1844 exit(2);
1845 }
1846
1847 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
1848 ha_alert("Error in condition: Line too long.\n");
1849 exit(2);
1850 }
1851
Willy Tarreauc8194c32021-07-16 16:38:58 +02001852 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001853 ha_alert("Error in condition: Too many words.\n");
1854 exit(2);
1855 }
1856
1857 if (err) {
1858 ha_alert("Unhandled error in condition, please report this to the developers.\n");
1859 exit(2);
1860 }
1861
Willy Tarreauc8194c32021-07-16 16:38:58 +02001862 /* remerge all words into a single expression */
1863 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
1864 ;
1865
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001866 result = cfg_eval_condition(args, &errmsg, &errptr);
1867
1868 if (result < 0) {
1869 if (errmsg)
1870 ha_alert("Failed to evaluate condition: %s\n", errmsg);
1871
1872 exit(2);
1873 }
1874
1875 exit(result ? 0 : 1);
1876 }
1877
William Lallemand944e6192018-11-21 15:48:31 +01001878 /* in wait mode, we don't try to read the configuration files */
1879 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001880 char *env_cfgfiles = NULL;
1881 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001882
William Lallemand944e6192018-11-21 15:48:31 +01001883 /* handle cfgfiles that are actually directories */
1884 cfgfiles_expand_directories();
1885
1886 if (LIST_ISEMPTY(&cfg_cfgfiles))
1887 usage(progname);
1888
1889
1890 list_for_each_entry(wl, &cfg_cfgfiles, list) {
1891 int ret;
1892
Christopher Faulet4e366822021-01-12 18:57:38 +01001893 if (env_err == 0) {
1894 if (!memprintf(&env_cfgfiles, "%s%s%s",
1895 (env_cfgfiles ? env_cfgfiles : ""),
1896 (env_cfgfiles ? ";" : ""), wl->s))
1897 env_err = 1;
1898 }
William Lallemand7b302d82019-05-20 11:15:37 +02001899
William Lallemand944e6192018-11-21 15:48:31 +01001900 ret = readcfgfile(wl->s);
1901 if (ret == -1) {
1902 ha_alert("Could not open configuration file %s : %s\n",
1903 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01001904 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001905 exit(1);
1906 }
1907 if (ret & (ERR_ABORT|ERR_FATAL))
1908 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
1909 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01001910 if (err_code & ERR_ABORT) {
1911 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001912 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01001913 }
Willy Tarreauc4382422009-12-06 13:10:44 +01001914 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001915
William Lallemand944e6192018-11-21 15:48:31 +01001916 /* do not try to resolve arguments nor to spot inconsistencies when
1917 * the configuration contains fatal errors caused by files not found
1918 * or failed memory allocations.
1919 */
1920 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1921 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01001922 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001923 exit(1);
1924 }
Christopher Faulet4e366822021-01-12 18:57:38 +01001925 if (env_err) {
1926 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
1927 exit(1);
1928 }
1929 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
1930 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02001931
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02001932 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001933 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01001934 struct mworker_proc *tmproc;
1935
William Lallemand482f9a92019-04-12 16:15:00 +02001936 setenv("HAPROXY_MWORKER", "1", 1);
1937
William Lallemand16dd1b32018-11-19 18:46:18 +01001938 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
1939
William Lallemand56be0e02022-01-28 21:11:41 +01001940 tmproc = mworker_proc_new();
William Lallemand16dd1b32018-11-19 18:46:18 +01001941 if (!tmproc) {
1942 ha_alert("Cannot allocate process structures.\n");
1943 exit(EXIT_FAILURE);
1944 }
William Lallemand8f7069a2019-04-12 16:09:23 +02001945 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01001946 tmproc->pid = pid;
1947 tmproc->timestamp = start_date.tv_sec;
William Lallemand16dd1b32018-11-19 18:46:18 +01001948 proc_self = tmproc;
1949
Willy Tarreau2b718102021-04-21 07:32:39 +02001950 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01001951 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001952
William Lallemand56be0e02022-01-28 21:11:41 +01001953 tmproc = mworker_proc_new();
Willy Tarreau6185a032021-06-15 08:02:06 +02001954 if (!tmproc) {
1955 ha_alert("Cannot allocate process structures.\n");
1956 exit(EXIT_FAILURE);
1957 }
Willy Tarreau6185a032021-06-15 08:02:06 +02001958 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
William Lallemandce83b4a2018-10-26 14:47:30 +02001959
Willy Tarreau6185a032021-06-15 08:02:06 +02001960 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
1961 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02001962 }
Willy Tarreau6185a032021-06-15 08:02:06 +02001963
1964 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01001965 }
1966 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
1967 struct wordlist *it, *c;
1968
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02001969 /* get the info of the children in the env */
1970 if (mworker_env_to_proc_list() < 0) {
1971 exit(EXIT_FAILURE);
1972 }
William Lallemande7361152018-10-26 14:47:36 +02001973
William Lallemand550db6d2018-11-06 17:37:12 +01001974 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02001975
William Lallemand550db6d2018-11-06 17:37:12 +01001976 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02001977 ha_alert("Can't create the master's CLI.\n");
1978 exit(EXIT_FAILURE);
1979 }
William Lallemande7361152018-10-26 14:47:36 +02001980
William Lallemand550db6d2018-11-06 17:37:12 +01001981 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
1982
1983 if (mworker_cli_proxy_new_listener(c->s) < 0) {
1984 ha_alert("Can't create the master's CLI.\n");
1985 exit(EXIT_FAILURE);
1986 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001987 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01001988 free(c->s);
1989 free(c);
1990 }
1991 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001992 }
1993
Eric Salama5ba83352021-03-16 15:11:17 +01001994 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
1995 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
1996 }
1997
Christopher Faulet27c8d202021-10-13 09:50:53 +02001998 /* destroy unreferenced defaults proxies */
1999 proxy_destroy_all_unref_defaults();
2000
Willy Tarreaue90904d2021-02-12 14:08:31 +01002001
Willy Tarreaubb925012009-07-23 13:36:36 +02002002 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02002003 for (px = proxies_list; px; px = px->next) {
2004 struct server *srv;
2005 struct post_proxy_check_fct *ppcf;
2006 struct post_server_check_fct *pscf;
2007
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002008 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002009 continue;
2010
Christopher Fauletc1692962019-08-12 09:51:07 +02002011 list_for_each_entry(pscf, &post_server_check_list, list) {
2012 for (srv = px->srv; srv; srv = srv->next)
2013 err_code |= pscf->fct(srv);
2014 }
2015 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2016 err_code |= ppcf->fct(px);
2017 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002018 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002019 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002020 exit(1);
2021 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002022
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002023 err_code |= pattern_finalize_config();
2024 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2025 ha_alert("Failed to finalize pattern config.\n");
2026 exit(1);
2027 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002028
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002029 if (global.rlimit_memmax_all)
2030 global.rlimit_memmax = global.rlimit_memmax_all;
2031
Willy Tarreaue5733232019-05-22 19:24:06 +02002032#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002033 err_code |= netns_init();
2034 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002035 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002036 exit(1);
2037 }
2038#endif
2039
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002040 /* Apply server states */
2041 apply_server_state();
2042
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002043 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002044 srv_compute_all_admin_states(px);
2045
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002046 /* Apply servers' configured address */
2047 err_code |= srv_init_addr();
2048 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002049 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002050 exit(1);
2051 }
2052
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002053 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2054 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2055 exit(1);
2056 }
2057
Willy Tarreau654726d2021-12-28 15:43:11 +01002058#if defined(HA_HAVE_DUMP_LIBS)
2059 if (global.mode & MODE_DUMP_LIBS) {
2060 qfprintf(stdout, "List of loaded object files:\n");
2061 chunk_reset(&trash);
2062 if (dump_libs(&trash, 0))
2063 printf("%s", trash.area);
2064 }
2065#endif
2066
Willy Tarreaubaaee002006-06-26 02:48:02 +02002067 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002068 struct peers *pr;
2069 struct proxy *px;
2070
Willy Tarreaubebd2122020-04-15 16:06:11 +02002071 if (warned & WARN_ANY)
2072 qfprintf(stdout, "Warnings were found.\n");
2073
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002074 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002075 if (pr->peers_fe)
2076 break;
2077
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002078 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002079 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002080 break;
2081
Emeric Brunbc5c8212021-08-13 09:32:50 +02002082 if (!px) {
2083 /* We may only have log-forward section */
2084 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002085 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002086 break;
2087 }
2088
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002089 if (pr || px) {
2090 /* At least one peer or one listener has been found */
2091 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002092 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002093 }
2094 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2095 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002096 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002097
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002098 if (global.mode & MODE_DIAG) {
2099 cfg_run_diagnostics();
2100 }
2101
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002102 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002103 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002104
Willy Tarreaue6945732016-12-21 19:57:00 +01002105 list_for_each_entry(pcf, &post_check_list, list) {
2106 err_code |= pcf->fct();
2107 if (err_code & (ERR_ABORT|ERR_FATAL))
2108 exit(1);
2109 }
2110
Willy Tarreaubaaee002006-06-26 02:48:02 +02002111 if (cfg_maxconn > 0)
2112 global.maxconn = cfg_maxconn;
2113
Willy Tarreau4975d142021-03-13 11:00:33 +01002114 if (global.cli_fe)
2115 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002116
2117 if (cfg_peers) {
2118 /* peers also need to bypass global maxconn */
2119 struct peers *p = cfg_peers;
2120
2121 for (p = cfg_peers; p; p = p->next)
2122 if (p->peers_fe)
2123 global.maxsock += p->peers_fe->maxconn;
2124 }
2125
Willy Tarreaubaaee002006-06-26 02:48:02 +02002126 if (cfg_pidfile) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002127 free(global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002128 global.pidfile = strdup(cfg_pidfile);
2129 }
2130
Willy Tarreaud0256482015-01-15 21:45:22 +01002131 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002132 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2133 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2134 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2135 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002136 *
2137 * If memmax is set, then it depends on which values are set. If
2138 * maxsslconn is set, we use memmax to determine how many cleartext
2139 * connections may be added, and set maxconn to the sum of the two.
2140 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2141 * the remaining amount of memory between memmax and the cleartext
2142 * connections. If neither are set, then it is considered that all
2143 * connections are SSL-capable, and maxconn is computed based on this,
2144 * then maxsslconn accordingly. We need to know if SSL is used on the
2145 * frontends, backends, or both, because when it's used on both sides,
2146 * we need twice the value for maxsslconn, but we only count the
2147 * handshake once since it is not performed on the two sides at the
2148 * same time (frontend-side is terminated before backend-side begins).
2149 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002150 * ssl_handshake_cost during its initialization. In any case, if
2151 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2152 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002153 */
Willy Tarreauac350932019-03-01 15:43:14 +01002154 ideal_maxconn = compute_ideal_maxconn();
2155
Willy Tarreaud0256482015-01-15 21:45:22 +01002156 if (!global.rlimit_memmax) {
2157 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002158 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002159 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2160 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2161 }
2162 }
2163#ifdef USE_OPENSSL
2164 else if (!global.maxconn && !global.maxsslconn &&
2165 (global.ssl_used_frontend || global.ssl_used_backend)) {
2166 /* memmax is set, compute everything automatically. Here we want
2167 * to ensure that all SSL connections will be served. We take
2168 * care of the number of sides where SSL is used, and consider
2169 * the worst case : SSL used on both sides and doing a handshake
2170 * simultaneously. Note that we can't have more than maxconn
2171 * handshakes at a time by definition, so for the worst case of
2172 * two SSL conns per connection, we count a single handshake.
2173 */
2174 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2175 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002176 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002177
2178 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2179 mem -= global.maxzlibmem;
2180 mem = mem * MEM_USABLE_RATIO;
2181
Willy Tarreau304e17e2020-03-10 17:54:54 +01002182 /* Principle: we test once to set maxconn according to the free
2183 * memory. If it results in values the system rejects, we try a
2184 * second time by respecting rlim_fd_max. If it fails again, we
2185 * go back to the initial value and will let the final code
2186 * dealing with rlimit report the error. That's up to 3 attempts.
2187 */
2188 do {
2189 global.maxconn = mem /
2190 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2191 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2192 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002193
Willy Tarreau304e17e2020-03-10 17:54:54 +01002194 if (retried == 1)
2195 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2196 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002197#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002198 if (global.maxconn > SYSTEM_MAXCONN)
2199 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002200#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002201 global.maxsslconn = sides * global.maxconn;
2202
2203 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2204 break;
2205 } while (retried++ < 2);
2206
Willy Tarreaud0256482015-01-15 21:45:22 +01002207 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2208 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2209 global.maxconn, global.maxsslconn);
2210 }
2211 else if (!global.maxsslconn &&
2212 (global.ssl_used_frontend || global.ssl_used_backend)) {
2213 /* memmax and maxconn are known, compute maxsslconn automatically.
2214 * maxsslconn being forced, we don't know how many of it will be
2215 * on each side if both sides are being used. The worst case is
2216 * when all connections use only one SSL instance because
2217 * handshakes may be on two sides at the same time.
2218 */
2219 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2220 int64_t mem = global.rlimit_memmax * 1048576ULL;
2221 int64_t sslmem;
2222
2223 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2224 mem -= global.maxzlibmem;
2225 mem = mem * MEM_USABLE_RATIO;
2226
Willy Tarreau87b09662015-04-03 00:22:06 +02002227 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002228 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2229 global.maxsslconn = round_2dig(global.maxsslconn);
2230
2231 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002232 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2233 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2234 "without SSL is %d, but %d was found and SSL is in use.\n",
2235 global.rlimit_memmax,
2236 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2237 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002238 exit(1);
2239 }
2240
2241 if (global.maxsslconn > sides * global.maxconn)
2242 global.maxsslconn = sides * global.maxconn;
2243
2244 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2245 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2246 }
2247#endif
2248 else if (!global.maxconn) {
2249 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2250 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2251 int64_t mem = global.rlimit_memmax * 1048576ULL;
2252 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002253 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002254
2255 if (global.ssl_used_frontend || global.ssl_used_backend)
2256 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2257
2258 mem -= global.maxzlibmem;
2259 mem = mem * MEM_USABLE_RATIO;
2260
2261 clearmem = mem;
2262 if (sides)
2263 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2264
Willy Tarreau304e17e2020-03-10 17:54:54 +01002265 /* Principle: we test once to set maxconn according to the free
2266 * memory. If it results in values the system rejects, we try a
2267 * second time by respecting rlim_fd_max. If it fails again, we
2268 * go back to the initial value and will let the final code
2269 * dealing with rlimit report the error. That's up to 3 attempts.
2270 */
2271 do {
2272 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2273 if (retried == 1)
2274 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2275 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002276#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002277 if (global.maxconn > SYSTEM_MAXCONN)
2278 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002279#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002280
Willy Tarreau304e17e2020-03-10 17:54:54 +01002281 if (clearmem <= 0 || !global.maxconn) {
2282 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2283 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2284 "is %d, but %d was found.\n",
2285 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002286 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002287 global.maxsslconn);
2288 exit(1);
2289 }
2290
2291 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2292 break;
2293 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002294
2295 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2296 if (sides && global.maxsslconn > sides * global.maxconn) {
2297 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2298 "to be limited to %d. Better reduce global.maxsslconn to get more "
2299 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2300 }
2301 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2302 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002303 }
2304
Willy Tarreaua409f302020-03-10 17:08:53 +01002305 global.maxsock = compute_ideal_maxsock(global.maxconn);
2306 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002307 if (!global.maxpipes)
2308 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002309
Olivier Houchard88698d92019-04-16 19:07:22 +02002310 /* update connection pool thresholds */
2311 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2312 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2313
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002314 proxy_adjust_all_maxconn();
2315
Willy Tarreau1db37712007-06-03 17:16:49 +02002316 if (global.tune.maxpollevents <= 0)
2317 global.tune.maxpollevents = MAX_POLL_EVENTS;
2318
Willy Tarreau060a7612021-03-10 11:06:26 +01002319 if (global.tune.runqueue_depth <= 0) {
2320 /* tests on various thread counts from 1 to 64 have shown an
2321 * optimal queue depth following roughly 1/sqrt(threads).
2322 */
2323 int s = my_flsl(global.nbthread);
2324 s += (global.nbthread / s); // roughly twice the sqrt.
2325 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2326 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002327
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002328 if (global.tune.recv_enough == 0)
2329 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2330
Willy Tarreau27a674e2009-08-17 07:23:33 +02002331 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2332 global.tune.maxrewrite = global.tune.bufsize / 2;
2333
Amaury Denoyelle11124302021-06-04 18:22:08 +02002334 usermsgs_clr(NULL);
2335
Willy Tarreaubaaee002006-06-26 02:48:02 +02002336 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2337 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002338 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002339 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2340 }
2341
William Lallemand095ba4c2017-06-01 17:38:50 +02002342 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002343 /* command line daemon mode inhibits foreground and debug modes mode */
2344 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002345 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002346 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002347
2348 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002349
William Lallemand095ba4c2017-06-01 17:38:50 +02002350 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002351 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002352 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 }
2354
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002355 if (global.nbthread < 1)
2356 global.nbthread = 1;
2357
Christopher Faulet3ef26392017-08-29 16:46:57 +02002358 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002359 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002360 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002361 exit(1);
2362 }
2363
Christopher Faulet96d44832017-11-14 22:02:30 +01002364 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002365 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002366 exit(1);
2367 }
2368
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002369 /*
2370 * Note: we could register external pollers here.
2371 * Built-in pollers have been registered before main().
2372 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002373
Willy Tarreau43b78992009-01-25 15:42:27 +01002374 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002375 disable_poller("kqueue");
2376
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002377 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2378 disable_poller("evports");
2379
Willy Tarreau43b78992009-01-25 15:42:27 +01002380 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002381 disable_poller("epoll");
2382
Willy Tarreau43b78992009-01-25 15:42:27 +01002383 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002384 disable_poller("poll");
2385
Willy Tarreau43b78992009-01-25 15:42:27 +01002386 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002387 disable_poller("select");
2388
2389 /* Note: we could disable any poller by name here */
2390
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002391 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002392 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002393 fprintf(stderr, "\n");
2394 list_filters(stderr);
2395 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002396
Willy Tarreau4f60f162007-04-08 16:39:58 +02002397 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002398 ha_alert("No polling mechanism available.\n"
2399 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2400 " is too low on this platform to support maxconn and the number of listeners\n"
2401 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2402 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2403 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2404 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2405 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2406 " check build settings using 'haproxy -vv'.\n\n",
2407 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002408 exit(1);
2409 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002410 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2411 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002412 }
2413
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002414 if (!global.node)
2415 global.node = strdup(hostname);
2416
Willy Tarreau02b092f2020-10-07 18:36:54 +02002417 /* stop disabled proxies */
2418 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002419 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002420 stop_proxy(px);
2421 }
2422
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002423 if (!hlua_post_init())
2424 exit(1);
Thomas Holmes6abded42015-05-12 16:23:58 +01002425
Maxime de Roucy0f503922016-05-13 23:52:55 +02002426 free(err_msg);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002427}
2428
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002429void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002431 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002432 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002433 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002434 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002435 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002436 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002437 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002438 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002439 struct per_thread_init_fct *tif, *tifb;
2440 struct per_thread_deinit_fct *tdf, *tdfb;
2441 struct per_thread_alloc_fct *taf, *tafb;
2442 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002443 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002444 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002445 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002446 int cur_fd;
2447
2448 /* At this point the listeners state is weird:
2449 * - most listeners are still bound and referenced in their protocol
2450 * - some might be zombies that are not in their proto anymore, but
2451 * still appear in their proxy's listeners with a valid FD.
2452 * - some might be stopped and still appear in their proxy as FD #-1
2453 * - among all of them, some might be inherited hence shared and we're
2454 * not allowed to pause them or whatever, we must just close them.
2455 * - finally some are not listeners (pipes, logs, stdout, etc) and
2456 * must be left intact.
2457 *
2458 * The safe way to proceed is to unbind (and close) whatever is not yet
2459 * unbound so that no more receiver/listener remains alive. Then close
2460 * remaining listener FDs, which correspond to zombie listeners (those
2461 * belonging to disabled proxies that were in another process).
2462 * objt_listener() would be cleaner here but not converted yet.
2463 */
2464 protocol_unbind_all();
2465
2466 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002467 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002468 continue;
2469
Willy Tarreaua74cb382020-10-15 21:29:49 +02002470 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002471 struct listener *l = fdtab[cur_fd].owner;
2472
2473 BUG_ON(l->state != LI_INIT);
2474 unbind_listener(l);
2475 }
2476 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002477
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002478 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002479 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002480 /* build a list of unique uri_auths */
2481 if (!ua)
2482 ua = p->uri_auth;
2483 else {
2484 /* check if p->uri_auth is unique */
2485 for (uap = ua; uap; uap=uap->next)
2486 if (uap == p->uri_auth)
2487 break;
2488
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002489 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002490 /* add it, if it is */
2491 p->uri_auth->next = ua;
2492 ua = p->uri_auth;
2493 }
William Lallemand0f99e342011-10-12 17:50:54 +02002494 }
2495
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002496 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002497 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002498 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002500
Christopher Faulet27c8d202021-10-13 09:50:53 +02002501 /* destroy all referenced defaults proxies */
2502 proxy_destroy_all_unref_defaults();
2503
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002504 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002505 struct stat_scope *scope, *scopep;
2506
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002507 uap = ua;
2508 ua = ua->next;
2509
Willy Tarreaua534fea2008-08-03 12:19:50 +02002510 free(uap->uri_prefix);
2511 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002512 free(uap->node);
2513 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002514
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002515 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002516 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002517
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002518 scope = uap->scope;
2519 while (scope) {
2520 scopep = scope;
2521 scope = scope->next;
2522
2523 free(scopep->px_id);
2524 free(scopep);
2525 }
2526
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002527 free(uap);
2528 }
2529
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002530 userlist_free(userlist);
2531
David Carlier834cb2e2015-09-25 12:02:25 +01002532 cfg_unregister_sections();
2533
Christopher Faulet0132d062017-07-26 15:33:35 +02002534 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002535
Willy Tarreau05554e62016-12-21 20:46:26 +01002536 list_for_each_entry(pdf, &post_deinit_list, list)
2537 pdf->fct();
2538
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002539 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002540 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002541 ha_free(&global.chroot);
2542 ha_free(&global.pidfile);
2543 ha_free(&global.node);
2544 ha_free(&global.desc);
2545 ha_free(&oldpids);
2546 ha_free(&old_argv);
2547 ha_free(&localpeer);
2548 ha_free(&global.server_state_base);
2549 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002550 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002551 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002552
William Lallemand0f99e342011-10-12 17:50:54 +02002553 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002554 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002555 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002556 free(log);
2557 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002558 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002559 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002560 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002561 free(wl);
2562 }
2563
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002564 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2565 if (bol->must_free)
2566 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002567 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002568 free(bol);
2569 }
2570
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002571 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002572 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002573 free(pxdf);
2574 }
2575
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002576 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002577 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002578 free(pdf);
2579 }
2580
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002581 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002582 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002583 free(srvdf);
2584 }
2585
Tim Duesterhusfc854942020-09-10 19:46:42 +02002586 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002587 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002588 free(pcf);
2589 }
2590
Tim Duesterhus34bef072020-07-04 11:49:50 +02002591 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002592 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002593 free(pscf);
2594 }
2595
Tim Duesterhus53508d62020-09-10 19:46:40 +02002596 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002597 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002598 free(ppcf);
2599 }
2600
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002601 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002602 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002603 free(tif);
2604 }
2605
2606 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002607 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002608 free(tdf);
2609 }
2610
2611 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002612 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002613 free(taf);
2614 }
2615
2616 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002617 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002618 free(tff);
2619 }
2620
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002621 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002622 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002623 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002624} /* end deinit() */
2625
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002626__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002627{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002628 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002629 deinit();
2630 exit(status);
2631}
William Lallemand72160322018-11-06 17:37:16 +01002632
Willy Tarreau918ff602011-07-25 16:33:49 +02002633/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002634void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002635{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002636 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002637
Willy Tarreau55542642021-10-08 09:33:24 +02002638 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002639 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002640 wake_expired_tasks();
2641
William Lallemand1aab50b2018-06-07 09:46:01 +02002642 /* check if we caught some signals and process them in the
2643 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002644 if (signal_queue_len && tid == 0) {
2645 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002646 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002647 }
2648
2649 /* Process a few tasks */
2650 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002651
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002652 /* also stop if we failed to cleanly stop all tasks */
2653 if (killed > 1)
2654 break;
2655
Willy Tarreau10146c92015-04-13 20:44:19 +02002656 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002657 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002658 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002659 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002660 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002661 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2662 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002663 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002664 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002665 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002666 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002667 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002668 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002669
Willy Tarreau4f46a352020-03-23 09:27:28 +01002670 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002671 int i;
2672
2673 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002674 /* stop muxes before acknowledging stopping */
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002675 if (!(stopping_thread_mask & tid_bit)) {
2676 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2677 wake = 1;
2678 }
2679
Willy Tarreau1db42732021-04-06 11:44:07 +02002680 if (_HA_ATOMIC_OR_FETCH(&stopping_thread_mask, tid_bit) == tid_bit) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002681 /* notify all threads that stopping was just set */
2682 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002683 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002684 wake_thread(i);
2685 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002686 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002687
2688 /* stop when there's nothing left to do */
2689 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002690 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2691 /* wake all threads waiting on jobs==0 */
2692 for (i = 0; i < global.nbthread; i++)
2693 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2694 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002695 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002696 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002697 }
2698
Willy Tarreauc49ba522019-12-11 08:12:23 +01002699 /* If we have to sleep, measure how long */
2700 next = wake ? TICK_ETERNITY : next_timer_expiry();
2701
Willy Tarreau58b458d2008-06-29 22:40:23 +02002702 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002703 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002704
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002705 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002706 }
2707}
2708
Christopher Faulet1d17c102017-08-29 15:38:48 +02002709static void *run_thread_poll_loop(void *data)
2710{
Willy Tarreau082b6282019-05-22 14:42:12 +02002711 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002712 struct per_thread_init_fct *ptif;
2713 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002714 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002715 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002716 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2717 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002718
Willy Tarreau43ab05b2021-09-28 09:43:11 +02002719 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02002720 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02002721 clock_set_local_source();
Willy Tarreau91e6df02019-05-03 17:21:18 +02002722
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002723 /* Now, initialize one thread init at a time. This is better since
2724 * some init code is a bit tricky and may release global resources
2725 * after reallocating them locally. This will also ensure there is
2726 * no race on file descriptors allocation.
2727 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002728#ifdef USE_THREAD
2729 pthread_mutex_lock(&init_mutex);
2730#endif
2731 /* The first thread must set the number of threads left */
2732 if (!init_left)
2733 init_left = global.nbthread;
2734 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002735
Willy Tarreau55542642021-10-08 09:33:24 +02002736 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002737
Willy Tarreau082b6282019-05-22 14:42:12 +02002738 /* per-thread alloc calls performed here are not allowed to snoop on
2739 * other threads, so they are free to initialize at their own rhythm
2740 * as long as they act as if they were alone. None of them may rely
2741 * on resources initialized by the other ones.
2742 */
2743 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2744 if (!ptaf->fct()) {
2745 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002746#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002747 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002748#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02002749 exit(1);
2750 }
2751 }
2752
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002753 /* per-thread init calls performed here are not allowed to snoop on
2754 * other threads, so they are free to initialize at their own rhythm
2755 * as long as they act as if they were alone.
2756 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002757 list_for_each_entry(ptif, &per_thread_init_list, list) {
2758 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002759 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002760#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002761 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002762#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002763 exit(1);
2764 }
2765 }
2766
Willy Tarreau71092822019-06-10 09:51:04 +02002767 /* enabling protocols will result in fd_insert() calls to be performed,
2768 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002769 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002770 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002771 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002772 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002773
Willy Tarreau34a150c2019-06-11 09:16:41 +02002774#ifdef USE_THREAD
2775 pthread_cond_broadcast(&init_cond);
2776 pthread_mutex_unlock(&init_mutex);
2777
2778 /* now wait for other threads to finish starting */
2779 pthread_mutex_lock(&init_mutex);
2780 while (init_left)
2781 pthread_cond_wait(&init_cond, &init_mutex);
2782 pthread_mutex_unlock(&init_mutex);
2783#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002784
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002785#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2786 /* Let's refrain from using setuid executables. This way the impact of
2787 * an eventual vulnerability in a library remains limited. It may
2788 * impact external checks but who cares about them anyway ? In the
2789 * worst case it's possible to disable the option. Obviously we do this
2790 * in workers only. We can't hard-fail on this one as it really is
2791 * implementation dependent though we're interested in feedback, hence
2792 * the warning.
2793 */
2794 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2795 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002796 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 +01002797 ha_warning("Failed to disable setuid, please report to developers with detailed "
2798 "information about your operating system. You can silence this warning "
2799 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2800 }
2801 }
2802#endif
2803
Willy Tarreaud96f1122019-12-03 07:07:36 +01002804#if defined(RLIMIT_NPROC)
2805 /* all threads have started, it's now time to prevent any new thread
2806 * or process from starting. Obviously we do this in workers only. We
2807 * can't hard-fail on this one as it really is implementation dependent
2808 * though we're interested in feedback, hence the warning.
2809 */
2810 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2811 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2812 static int warn_fail;
2813
Willy Tarreau18515722021-04-06 11:57:41 +02002814 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002815 ha_warning("Failed to disable forks, please report to developers with detailed "
2816 "information about your operating system. You can silence this warning "
2817 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2818 }
2819 }
2820#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002821 run_poll_loop();
2822
2823 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2824 ptdf->fct();
2825
Willy Tarreau082b6282019-05-22 14:42:12 +02002826 list_for_each_entry(ptff, &per_thread_free_list, list)
2827 ptff->fct();
2828
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002829#ifdef USE_THREAD
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002830 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002831 if (tid > 0)
2832 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002833#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002834 return NULL;
2835}
Christopher Faulet1d17c102017-08-29 15:38:48 +02002836
William Dauchyf9af9d72019-11-17 15:47:16 +01002837/* set uid/gid depending on global settings */
2838static void set_identity(const char *program_name)
2839{
2840 if (global.gid) {
2841 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
2842 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
2843 " without 'uid'/'user' is generally useless.\n", program_name);
2844
2845 if (setgid(global.gid) == -1) {
2846 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
2847 protocol_unbind_all();
2848 exit(1);
2849 }
2850 }
2851
2852 if (global.uid && setuid(global.uid) == -1) {
2853 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
2854 protocol_unbind_all();
2855 exit(1);
2856 }
2857}
2858
Willy Tarreaubaaee002006-06-26 02:48:02 +02002859int main(int argc, char **argv)
2860{
2861 int err, retry;
2862 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02002863 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02002864 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
2865
2866 /* Catch forced CFLAGS that miss 2-complement integer overflow */
2867 if (intovf + 0x7FFFFFFF >= intovf) {
2868 fprintf(stderr,
2869 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
2870 "The source code was miscompiled by the compiler, which usually indicates that\n"
2871 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
2872 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
2873 "and INSTALL files to decide on the best way to pass your local build options.\n"
2874 "\nBuild options :"
2875#ifdef BUILD_TARGET
2876 "\n TARGET = " BUILD_TARGET
2877#endif
2878#ifdef BUILD_CPU
2879 "\n CPU = " BUILD_CPU
2880#endif
2881#ifdef BUILD_CC
2882 "\n CC = " BUILD_CC
2883#endif
2884#ifdef BUILD_CFLAGS
2885 "\n CFLAGS = " BUILD_CFLAGS
2886#endif
2887#ifdef BUILD_OPTIONS
2888 "\n OPTIONS = " BUILD_OPTIONS
2889#endif
2890#ifdef BUILD_DEBUG
2891 "\n DEBUG = " BUILD_DEBUG
2892#endif
2893 "\n\n");
2894 return 1;
2895 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896
Olivier Houchard5fa300d2018-02-03 15:15:21 +01002897 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01002898
Willy Tarreaubf696402019-03-01 10:09:28 +01002899 /* take a copy of initial limits before we possibly change them */
2900 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02002901
2902 if (limit.rlim_max == RLIM_INFINITY)
2903 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01002904 rlim_fd_cur_at_boot = limit.rlim_cur;
2905 rlim_fd_max_at_boot = limit.rlim_max;
2906
Willy Tarreau5794fb02018-11-25 18:43:29 +01002907 /* process all initcalls in order of potential dependency */
2908 RUN_INITCALLS(STG_PREPARE);
2909 RUN_INITCALLS(STG_LOCK);
2910 RUN_INITCALLS(STG_ALLOC);
2911 RUN_INITCALLS(STG_POOL);
2912 RUN_INITCALLS(STG_REGISTER);
2913 RUN_INITCALLS(STG_INIT);
2914
Emeric Bruncf20bf12010-10-22 16:06:11 +02002915 init(argc, argv);
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002916 signal_register_fct(SIGQUIT, dump, SIGQUIT);
2917 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
2918 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02002919 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002920
Willy Tarreaue437c442010-03-17 18:02:46 +01002921 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
2922 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
2923 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002924 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002925 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002926
Willy Tarreaudc23a922011-02-16 11:10:36 +01002927 /* ulimits */
2928 if (!global.rlimit_nofile)
2929 global.rlimit_nofile = global.maxsock;
2930
2931 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01002932 limit.rlim_cur = global.rlimit_nofile;
2933 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
2934
Willy Tarreaudc23a922011-02-16 11:10:36 +01002935 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02002936 getrlimit(RLIMIT_NOFILE, &limit);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002937 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2938 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
2939 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002940 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002941 }
2942 else {
2943 /* try to set it to the max possible at least */
2944 limit.rlim_cur = limit.rlim_max;
2945 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
2946 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02002947
William Dauchya5194602020-03-28 19:29:58 +01002948 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002949 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
2950 global.rlimit_nofile = limit.rlim_cur;
2951 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01002952 }
2953 }
2954
2955 if (global.rlimit_memmax) {
2956 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01002957 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01002958#ifdef RLIMIT_AS
2959 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002960 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2961 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2962 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002963 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002964 }
2965 else
William Dauchya5194602020-03-28 19:29:58 +01002966 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002967 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002968 }
2969#else
2970 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002971 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2972 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2973 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002974 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002975 }
2976 else
William Dauchya5194602020-03-28 19:29:58 +01002977 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002978 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002979 }
2980#endif
2981 }
2982
William Lallemandf82afbb2022-01-07 18:19:42 +01002983 /* Try to get the listeners FD from the previous process using
2984 * _getsocks on the stat socket, it must never been done in wait mode
2985 * and check mode
2986 */
2987 if (old_unixsocket &&
2988 !(global.mode & (MODE_MWORKER_WAIT|MODE_CHECK|MODE_CHECK_CONDITION))) {
William Lallemand85b0bd92017-06-01 17:38:53 +02002989 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02002990 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002991 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02002992 if (!(global.mode & MODE_MWORKER))
2993 exit(1);
2994 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02002995 }
2996 }
William Lallemand85b0bd92017-06-01 17:38:53 +02002997
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 /* We will loop at most 100 times with 10 ms delay each time.
2999 * That's at most 1 second. We only send a signal to old pids
3000 * if we cannot grab at least one port.
3001 */
3002 retry = MAX_START_RETRIES;
3003 err = ERR_NONE;
3004 while (retry >= 0) {
3005 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003006 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003007 /* exit the loop on no error or fatal error */
3008 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003009 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003010 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003011 break;
3012
3013 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3014 * listening sockets. So on those platforms, it would be wiser to
3015 * simply send SIGUSR1, which will not be undoable.
3016 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003017 if (tell_old_pids(SIGTTOU) == 0) {
3018 /* no need to wait if we can't contact old pids */
3019 retry = 0;
3020 continue;
3021 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003022 /* give some time to old processes to stop listening */
3023 w.tv_sec = 0;
3024 w.tv_usec = 10*1000;
3025 select(0, NULL, NULL, NULL, &w);
3026 retry--;
3027 }
3028
Willy Tarreaue91bff22020-09-02 11:11:43 +02003029 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003030 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003031 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003032 if (retry != MAX_START_RETRIES && nb_oldpids) {
3033 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003034 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003035 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003036 exit(1);
3037 }
3038
William Lallemand944e6192018-11-21 15:48:31 +01003039 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003040 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 /* Note: we don't have to send anything to the old pids because we
3042 * never stopped them. */
3043 exit(1);
3044 }
3045
Willy Tarreaue91bff22020-09-02 11:11:43 +02003046 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003047 * the previous process gave us, we don't need them anymore
3048 */
Willy Tarreaub5101162022-01-28 18:28:18 +01003049 sock_drop_unused_old_sockets();
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
William Lallemand5d71a6b2021-11-09 15:25:31 +01003205 ha_notice("New worker (%d) forked\n", 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
David CARLIERdf91cbd2022-01-06 18:53:50 +00003226#if defined(CPUSET_USE_CPUSET) || defined(__DragonFly__)
David CARLIERbb10dad2022-01-08 09:59:38 +00003227 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003228 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
David CARLIERdf91cbd2022-01-06 18:53:50 +00003229#elif defined(__FreeBSD__)
David CARLIERbb10dad2022-01-08 09:59:38 +00003230 struct hap_cpuset *set = &cpu_map.proc;
David CARLIERdf91cbd2022-01-06 18:53:50 +00003231 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, 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)) {
William Lallemandfab0fdc2021-11-09 18:01:22 +01003246 master = 1;
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003247
3248 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3249 (global.mode & MODE_DAEMON)) {
3250 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003251 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3252 stdio_quiet(-1);
3253
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003254 global.mode &= ~MODE_VERBOSE;
3255 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003256 }
3257
William Lallemandfab0fdc2021-11-09 18:01:22 +01003258 if (global.mode & MODE_MWORKER_WAIT) {
3259 /* only the wait mode handles the master CLI */
3260 mworker_loop();
3261 } else {
3262
3263 /* if not in wait mode, reload in wait mode to free the memory */
William Lallemand836bda22021-11-09 18:16:47 +01003264 ha_notice("Loading success.\n");
William Lallemand68836742021-11-10 10:49:06 +01003265 proc_self->failedreloads = 0; /* reset the number of failure */
William Lallemandfab0fdc2021-11-09 18:01:22 +01003266 mworker_reexec_waitmode();
3267 }
William Lallemand1499b9b2017-06-07 15:04:47 +02003268 /* should never get there */
3269 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003270 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003271#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003272 ssl_free_dh();
3273#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003274 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003275 }
3276
William Lallemandcb11fd22017-06-01 17:38:52 +02003277 /* child must never use the atexit function */
3278 atexit_flag = 0;
3279
William Lallemandbc193052018-09-11 10:06:26 +02003280 /* close useless master sockets */
3281 if (global.mode & MODE_MWORKER) {
3282 struct mworker_proc *child, *it;
3283 master = 0;
3284
William Lallemand309dc9a2018-10-26 14:47:45 +02003285 mworker_cli_proxy_stop();
3286
William Lallemandbc193052018-09-11 10:06:26 +02003287 /* free proc struct of other processes */
3288 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003289 /* close the FD of the master side for all
3290 * workers, we don't need to close the worker
3291 * side of other workers since it's done with
3292 * the bind_proc */
William Lallemand7e018782022-01-28 21:56:24 +01003293 if (child->ipc_fd[0] >= 0) {
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003294 close(child->ipc_fd[0]);
William Lallemand7e018782022-01-28 21:56:24 +01003295 child->ipc_fd[0] = -1;
3296 }
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003297 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandce83b4a2018-10-26 14:47:30 +02003298 child->reloads == 0) {
3299 /* keep this struct if this is our pid */
3300 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003301 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003302 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003303 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003304 mworker_free_child(child);
3305 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003306 }
3307 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003308
William Lallemande1340412017-12-28 16:09:36 +01003309 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3310 devnullfd = open("/dev/null", O_RDWR, 0);
3311 if (devnullfd < 0) {
3312 ha_alert("Cannot open /dev/null\n");
3313 exit(EXIT_FAILURE);
3314 }
3315 }
3316
William Lallemand095ba4c2017-06-01 17:38:50 +02003317 /* Must chroot and setgid/setuid in the children */
3318 /* chroot if needed */
3319 if (global.chroot != NULL) {
3320 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003321 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003322 if (nb_oldpids)
3323 tell_old_pids(SIGTTIN);
3324 protocol_unbind_all();
3325 exit(1);
3326 }
3327 }
3328
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003329 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003330 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003331
William Lallemand7f80eb22017-05-26 18:19:55 +02003332 /* pass through every cli socket, and check if it's bound to
3333 * the current process and if it exposes listeners sockets.
3334 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3335 * */
3336
Willy Tarreau4975d142021-03-13 11:00:33 +01003337 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003338 struct bind_conf *bind_conf;
3339
Willy Tarreau4975d142021-03-13 11:00:33 +01003340 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003341 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003342 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3343 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003344 }
3345 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003346 }
3347
William Lallemand2e8fad92018-11-13 16:18:23 +01003348 /*
3349 * This is only done in daemon mode because we might want the
3350 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3351 * we should now close the 3 first FDs to ensure that we can
3352 * detach from the TTY. We MUST NOT do it in other cases since
3353 * it would have already be done, and 0-2 would have been
3354 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003356 if ((global.mode & MODE_DAEMON) &&
3357 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003359 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003360 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003361 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3362 }
3363 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003364 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3365 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003366 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003367 }
3368
William Dauchye039f262019-11-17 15:47:15 +01003369 /* try our best to re-enable core dumps depending on system capabilities.
3370 * What is addressed here :
3371 * - remove file size limits
3372 * - remove core size limits
3373 * - mark the process dumpable again if it lost it due to user/group
3374 */
3375 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3376 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3377
3378#if defined(RLIMIT_FSIZE)
3379 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3380 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3381 ha_alert("[%s.main()] Failed to set the raise the maximum "
3382 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003383 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003384 }
3385 else
3386 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003387 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003388 }
3389#endif
3390
3391#if defined(RLIMIT_CORE)
3392 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3393 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3394 ha_alert("[%s.main()] Failed to set the raise the core "
3395 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003396 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003397 }
3398 else
3399 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003400 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003401 }
3402#endif
3403
3404#if defined(USE_PRCTL)
3405 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3406 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3407 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003408#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003409 {
3410 int traceable = PROC_TRACE_CTL_ENABLE;
3411 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3412 ha_warning("[%s.main()] Failed to set the traceable flag, "
3413 "no core will be dumped.\n", argv[0]);
3414 }
William Dauchye039f262019-11-17 15:47:15 +01003415#endif
3416 }
3417
Christopher Faulete3a5e352017-10-24 13:53:54 +02003418 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003419 reset_usermsgs_ctx();
3420
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003421 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003422 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003423
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003424 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003425 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003426
3427 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003428 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003429
3430 /* wait for all threads to terminate */
3431 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003432
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003433 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434}
3435
Willy Tarreaubaaee002006-06-26 02:48:02 +02003436/*
3437 * Local variables:
3438 * c-indent-level: 8
3439 * c-basic-offset: 8
3440 * End:
3441 */