blob: 094a8393a16946bdf8407e6f3497971dc27c5c91 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
Willy Tarreaua5357cd2021-05-09 06:14:25 +02002 * HAProxy : High Availability-enabled HTTP/TCP proxy
Willy Tarreau421ed392021-01-06 17:41:32 +01003 * Copyright 2000-2021 Willy Tarreau <willy@haproxy.org>.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
Ilya Shipitsin46a030c2020-07-05 16:36:08 +050010 * Please refer to RFC7230 - RFC7235 information about HTTP protocol, and
11 * RFC6265 for information about cookies usage. More generally, the IETF HTTP
Willy Tarreaubaaee002006-06-26 02:48:02 +020012 * Working Group's web site should be consulted for protocol related changes :
13 *
14 * http://ftp.ics.uci.edu/pub/ietf/http/
15 *
16 * Pending bugs (may be not fixed because never reproduced) :
17 * - solaris only : sometimes, an HTTP proxy with only a dispatch address causes
18 * the proxy to terminate (no core) if the client breaks the connection during
19 * the response. Seen on 1.1.8pre4, but never reproduced. May not be related to
20 * the snprintf() bug since requests were simple (GET / HTTP/1.0), but may be
21 * related to missing setsid() (fixed in 1.1.15)
22 * - a proxy with an invalid config will prevent the startup even if disabled.
23 *
24 * ChangeLog has moved to the CHANGELOG file.
25 *
Willy Tarreaubaaee002006-06-26 02:48:02 +020026 */
27
David Carlier7ece0962015-12-08 21:43:09 +000028#define _GNU_SOURCE
Willy Tarreaubaaee002006-06-26 02:48:02 +020029#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <string.h>
33#include <ctype.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020034#include <dirent.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020035#include <sys/stat.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <sys/time.h>
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <netinet/tcp.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42#include <netdb.h>
43#include <fcntl.h>
44#include <errno.h>
45#include <signal.h>
46#include <stdarg.h>
47#include <sys/resource.h>
Tim Duesterhusdfad6a42020-04-18 16:02:47 +020048#include <sys/utsname.h>
Marc-Antoine Perennou992709b2013-02-12 10:53:52 +010049#include <sys/wait.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <time.h>
51#include <syslog.h>
Michael Schererab012dd2013-01-12 18:35:19 +010052#include <grp.h>
Willy Tarreaud10385a2021-10-06 22:22:40 +020053
Willy Tarreau5e03dfa2021-10-06 22:53:51 +020054#ifdef USE_THREAD
55#include <pthread.h>
56#endif
57
Willy Tarreaufc6c0322012-11-16 16:12:27 +010058#ifdef USE_CPU_AFFINITY
Willy Tarreaufc6c0322012-11-16 16:12:27 +010059#include <sched.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000060#if defined(__FreeBSD__) || defined(__DragonFly__)
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020061#include <sys/param.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000062#ifdef __FreeBSD__
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020063#include <sys/cpuset.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000064#endif
David Carlier5e4c8e22019-09-13 05:12:58 +010065#endif
Willy Tarreaufc6c0322012-11-16 16:12:27 +010066#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020067
Willy Tarreau636848a2019-04-15 19:38:50 +020068#if defined(USE_PRCTL)
69#include <sys/prctl.h>
70#endif
71
devnexen@gmail.com21185972021-08-21 09:13:10 +010072#if defined(USE_PROCCTL)
73#include <sys/procctl.h>
74#endif
75
Willy Tarreaubaaee002006-06-26 02:48:02 +020076#ifdef DEBUG_FULL
77#include <assert.h>
78#endif
Tim Duesterhusd6942c82017-11-20 15:58:35 +010079#if defined(USE_SYSTEMD)
80#include <systemd/sd-daemon.h>
81#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020082
Willy Tarreau6c3a6812020-03-06 18:57:15 +010083#include <import/sha1.h>
84
Willy Tarreaub2551052020-06-09 09:07:15 +020085#include <haproxy/acl.h>
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +010086#include <haproxy/action.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020087#include <haproxy/activity.h>
88#include <haproxy/api.h>
89#include <haproxy/arg.h>
90#include <haproxy/auth.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020091#include <haproxy/base64.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020092#include <haproxy/capture-t.h>
Willy Tarreau66243b42021-07-16 15:39:28 +020093#include <haproxy/cfgcond.h>
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +020094#include <haproxy/cfgdiag.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020095#include <haproxy/cfgparse.h>
Willy Tarreauc13ed532020-06-02 10:22:45 +020096#include <haproxy/chunk.h>
Willy Tarreau83487a82020-06-04 20:19:54 +020097#include <haproxy/cli.h>
Willy Tarreau55542642021-10-08 09:33:24 +020098#include <haproxy/clock.h>
Willy Tarreau7ea393d2020-06-04 18:02:10 +020099#include <haproxy/connection.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200100#ifdef USE_CPU_AFFINITY
Amaury Denoyelle982fb532021-04-21 18:39:58 +0200101#include <haproxy/cpuset.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200102#endif
Willy Tarreaueb92deb2020-06-04 10:53:16 +0200103#include <haproxy/dns.h>
Willy Tarreau2741c8c2020-06-02 11:28:02 +0200104#include <haproxy/dynbuf.h>
Willy Tarreau8d366972020-05-27 16:10:29 +0200105#include <haproxy/errors.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200106#include <haproxy/fd.h>
Willy Tarreauc7babd82020-06-04 21:29:29 +0200107#include <haproxy/filters.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200108#include <haproxy/global.h>
Willy Tarreau86416052020-06-04 09:20:54 +0200109#include <haproxy/hlua.h>
Willy Tarreauc761f842020-06-04 11:40:28 +0200110#include <haproxy/http_rules.h>
Willy Tarreau853b2972020-05-27 18:01:47 +0200111#include <haproxy/list.h>
Willy Tarreau213e9902020-06-04 14:58:24 +0200112#include <haproxy/listener.h>
Willy Tarreauaeed4a82020-06-04 22:01:04 +0200113#include <haproxy/log.h>
Willy Tarreaub5abe5b2020-06-04 14:07:37 +0200114#include <haproxy/mworker.h>
Willy Tarreau7a00efb2020-06-02 17:02:59 +0200115#include <haproxy/namespace.h>
Willy Tarreau6131d6a2020-06-02 16:48:09 +0200116#include <haproxy/net_helper.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +0200117#include <haproxy/openssl-compat.h>
Willy Tarreau225a90a2020-06-04 15:06:28 +0200118#include <haproxy/pattern.h>
Willy Tarreau3c2a7c22020-06-04 18:38:21 +0200119#include <haproxy/peers.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200120#include <haproxy/pool.h>
121#include <haproxy/protocol.h>
Willy Tarreaubf3b06b2020-08-26 10:23:40 +0200122#include <haproxy/proto_tcp.h>
Willy Tarreaua264d962020-06-04 22:29:18 +0200123#include <haproxy/proxy.h>
Willy Tarreau7cd8b6e2020-06-02 17:32:26 +0200124#include <haproxy/regex.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200125#include <haproxy/sample.h>
Willy Tarreau1e56f922020-06-04 23:20:13 +0200126#include <haproxy/server.h>
Willy Tarreau48d25b32020-06-04 18:58:52 +0200127#include <haproxy/session.h>
Willy Tarreau3727a8a2020-06-04 17:37:26 +0200128#include <haproxy/signal.h>
Willy Tarreau063d47d2020-08-28 16:29:53 +0200129#include <haproxy/sock.h>
Willy Tarreau25140cc2020-08-28 15:40:33 +0200130#include <haproxy/sock_inet.h>
Willy Tarreau209108d2020-06-04 20:30:20 +0200131#include <haproxy/ssl_sock.h>
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +0200132#include <haproxy/stats-t.h>
Willy Tarreaudfd3de82020-06-04 23:46:14 +0200133#include <haproxy/stream.h>
Willy Tarreaucea0e1b2020-06-04 17:25:40 +0200134#include <haproxy/task.h>
Willy Tarreau3f567e42020-05-28 15:29:19 +0200135#include <haproxy/thread.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200136#include <haproxy/time.h>
137#include <haproxy/tools.h>
138#include <haproxy/uri_auth-t.h>
Willy Tarreaua1718922020-06-04 16:25:31 +0200139#include <haproxy/vars.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200140#include <haproxy/version.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200141
Willy Tarreaubaaee002006-06-26 02:48:02 +0200142
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100143/* array of init calls for older platforms */
144DECLARE_INIT_STAGES;
145
Willy Tarreauf4596402021-04-10 16:53:05 +0200146/* create a read_mostly section to hold variables which are accessed a lot
147 * but which almost never change. The purpose is to isolate them in their
148 * own cache lines where they don't risk to be perturbated by write accesses
149 * to neighbor variables. We need to create an empty aligned variable for
150 * this. The fact that the variable is of size zero means that it will be
151 * eliminated at link time if no other variable uses it, but alignment will
152 * be respected.
153 */
154empty_t __read_mostly_align HA_SECTION("read_mostly") ALIGNED(64);
155
Willy Tarreauf0d3b732021-05-06 16:30:32 +0200156#ifdef BUILD_FEATURES
157const char *build_features = BUILD_FEATURES;
158#else
159const char *build_features = "";
160#endif
161
Willy Tarreau477ecd82010-01-03 21:12:30 +0100162/* list of config files */
163static struct list cfg_cfgfiles = LIST_HEAD_INIT(cfg_cfgfiles);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200164int pid; /* current process id */
165
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100166volatile unsigned long sleeping_thread_mask = 0; /* Threads that are about to sleep in poll() */
Willy Tarreau4b3f27b2020-03-12 17:28:01 +0100167volatile unsigned long stopping_thread_mask = 0; /* Threads acknowledged stopping */
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100168
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169/* global options */
170struct global global = {
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100171 .hard_stop_after = TICK_ETERNITY,
Amaury Denoyelle0f50cb92021-03-26 18:50:33 +0100172 .numa_cpu_mapping = 1,
Willy Tarreau149ab772019-01-26 14:27:06 +0100173 .nbthread = 0,
William Lallemand5f232402012-04-05 18:02:55 +0200174 .req_count = 0,
William Lallemand0f99e342011-10-12 17:50:54 +0200175 .logsrvs = LIST_HEAD_INIT(global.logsrvs),
William Lallemand9d5f5482012-11-07 16:12:57 +0100176 .maxzlibmem = 0,
William Lallemandd85f9172012-11-09 17:05:39 +0100177 .comp_rate_lim = 0,
Emeric Brun850efd52014-01-29 12:24:34 +0100178 .ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED,
Emeric Bruned760922010-10-22 17:59:25 +0200179 .unix_bind = {
180 .ux = {
181 .uid = -1,
182 .gid = -1,
183 .mode = 0,
184 }
185 },
Willy Tarreau27a674e2009-08-17 07:23:33 +0200186 .tune = {
Willy Tarreau7ac908b2019-02-27 12:02:18 +0100187 .options = GTUNE_LISTENER_MQ,
Willy Tarreauc77d3642018-12-12 06:19:42 +0100188 .bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
Christopher Faulet546c4692020-01-22 14:31:21 +0100189 .maxrewrite = MAXREWRITE,
Willy Tarreaua24adf02014-11-27 01:11:56 +0100190 .reserved_bufs = RESERVED_BUFS,
Willy Tarreauf3045d22015-04-29 16:24:50 +0200191 .pattern_cache = DEFAULT_PAT_LRU_SIZE,
Olivier Houchard88698d92019-04-16 19:07:22 +0200192 .pool_low_ratio = 20,
193 .pool_high_ratio = 25,
Christopher Faulet41ba36f2019-07-19 09:36:45 +0200194 .max_http_hdr = MAX_HTTP_HDR,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200195#ifdef USE_OPENSSL
Emeric Brun46635772012-11-14 11:32:56 +0100196 .sslcachesize = SSLCACHESIZE,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200197#endif
William Lallemandf3747832012-11-09 12:33:10 +0100198 .comp_maxlevel = 1,
Willy Tarreau7e312732014-02-12 16:35:14 +0100199#ifdef DEFAULT_IDLE_TIMER
200 .idle_timer = DEFAULT_IDLE_TIMER,
201#else
202 .idle_timer = 1000, /* 1 second */
203#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200204 },
Emeric Brun76d88952012-10-05 15:47:31 +0200205#ifdef USE_OPENSSL
206#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200207 .maxsslconn = DEFAULT_MAXSSLCONN,
208#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200209#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210 /* others NULL OK */
211};
212
213/*********************************************************************/
214
215int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100216int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200217int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100218int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100219int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100220int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500222/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 * or kill. We will send them a signal every 10 ms until we can bind to all
224 * our ports. With 200 retries, that's about 2 seconds.
225 */
226#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227static int *oldpids = NULL;
228static int oldpids_sig; /* use USR1 or TERM */
229
Olivier Houchardf73629d2017-04-05 22:33:04 +0200230/* Path to the unix socket we use to retrieve listener sockets from the old process */
231static const char *old_unixsocket;
232
William Lallemandcb11fd22017-06-01 17:38:52 +0200233int atexit_flag = 0;
234
Willy Tarreaubb545b42010-08-25 12:58:59 +0200235int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236const int zero = 0;
237const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200238const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100240char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200241char *localpeer = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242
William Lallemand00417412020-06-05 14:08:41 +0200243static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200244
William Lallemandbc193052018-09-11 10:06:26 +0200245struct list proc_list = LIST_HEAD_INIT(proc_list);
246
247int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100248unsigned int rlim_fd_cur_at_boot = 0;
249unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200250
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100251/* per-boot randomness */
252unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
253
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200254/* takes the thread config in argument or NULL for any thread */
William Lallemandb3f2be32018-09-11 10:06:18 +0200255static void *run_thread_poll_loop(void *data);
256
Willy Tarreauff055502014-04-28 22:27:06 +0200257/* bitfield of a few warnings to emit just once (WARN_*) */
258unsigned int warned = 0;
259
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200260/* set if experimental features have been used for the current process */
261static unsigned int tainted = 0;
262
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200263unsigned int experimental_directives_allowed = 0;
264
265int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
266 char **errmsg)
267{
268 if (kw->flags & KWF_EXPERIMENTAL) {
269 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200270 memprintf(errmsg, "parsing [%s:%d] : '%s' directive is experimental, must be allowed via a global 'expose-experimental-directives'",
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200271 file, linenum, kw->kw);
272 return 1;
273 }
274 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
275 }
276
277 return 0;
278}
279
William Lallemande7361152018-10-26 14:47:36 +0200280/* master CLI configuration (-S flag) */
281struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100282
283/* These are strings to be reported in the output of "haproxy -vv". They may
284 * either be constants (in which case must_free must be zero) or dynamically
285 * allocated strings to pass to free() on exit, and in this case must_free
286 * must be non-zero.
287 */
288struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
289struct build_opts_str {
290 struct list list;
291 const char *str;
292 int must_free;
293};
294
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295/*********************************************************************/
296/* general purpose functions ***************************************/
297/*********************************************************************/
298
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100299/* used to register some build option strings at boot. Set must_free to
300 * non-zero if the string must be freed upon exit.
301 */
302void hap_register_build_opts(const char *str, int must_free)
303{
304 struct build_opts_str *b;
305
306 b = calloc(1, sizeof(*b));
307 if (!b) {
308 fprintf(stderr, "out of memory\n");
309 exit(1);
310 }
311 b->str = str;
312 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200313 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100314}
315
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200316#define VERSION_MAX_ELTS 7
317
318/* This function splits an haproxy version string into an array of integers.
319 * The syntax of the supported version string is the following:
320 *
321 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
322 *
323 * This validates for example:
324 * 1.2.1-pre2, 1.2.1, 1.2.10.1, 1.3.16-rc1, 1.4-dev3, 1.5-dev18, 1.5-dev18-43
325 * 2.4-dev18-f6818d-20
326 *
327 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
328 * one fixed place in the array. The tags take a numeric value called <e> which
329 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
330 * considered as zero (henxe 1.5 and 1.5.0 are the same).
331 *
332 * The resulting values are:
333 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
334 * 1.2.1 1, 2, 1, 0, 3, 0, 0
335 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
336 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
337 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
338 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
339 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
340 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
341 *
342 * The function returns non-zero if the conversion succeeded, or zero if it
343 * failed.
344 */
345int split_version(const char *version, unsigned int *value)
346{
347 const char *p, *s;
348 char *error;
349 int nelts;
350
351 /* Initialize array with zeroes */
352 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
353 value[nelts] = 0;
354 value[4] = 3;
355
356 p = version;
357
358 /* If the version number is empty, return false */
359 if (*p == '\0')
360 return 0;
361
362 /* Convert first number <a> */
363 value[0] = strtol(p, &error, 10);
364 p = error + 1;
365 if (*error == '\0')
366 return 1;
367 if (*error == '-')
368 goto split_version_tag;
369 if (*error != '.')
370 return 0;
371
372 /* Convert first number <b> */
373 value[1] = strtol(p, &error, 10);
374 p = error + 1;
375 if (*error == '\0')
376 return 1;
377 if (*error == '-')
378 goto split_version_tag;
379 if (*error != '.')
380 return 0;
381
382 /* Convert first number <c> */
383 value[2] = strtol(p, &error, 10);
384 p = error + 1;
385 if (*error == '\0')
386 return 1;
387 if (*error == '-')
388 goto split_version_tag;
389 if (*error != '.')
390 return 0;
391
392 /* Convert first number <d> */
393 value[3] = strtol(p, &error, 10);
394 p = error + 1;
395 if (*error == '\0')
396 return 1;
397 if (*error != '-')
398 return 0;
399
400 split_version_tag:
401 /* Check for commit number */
402 if (*p >= '0' && *p <= '9')
403 goto split_version_commit;
404
405 /* Read tag */
406 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
407 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
408 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
409 else
410 goto split_version_commit;
411
412 /* Convert tag number */
413 value[5] = strtol(p, &error, 10);
414 p = error + 1;
415 if (*error == '\0')
416 return 1;
417 if (*error != '-')
418 return 0;
419
420 split_version_commit:
421 /* Search the last "-" */
422 s = strrchr(p, '-');
423 if (s) {
424 s++;
425 if (*s == '\0')
426 return 0;
427 value[6] = strtol(s, &error, 10);
428 if (*error != '\0')
429 value[6] = 0;
430 return 1;
431 }
432
433 /* convert the version */
434 value[6] = strtol(p, &error, 10);
435 if (*error != '\0')
436 value[6] = 0;
437
438 return 1;
439}
440
441/* This function compares the current haproxy version with an arbitrary version
442 * string. It returns:
443 * -1 : the version in argument is older than the current haproxy version
444 * 0 : the version in argument is the same as the current haproxy version
445 * 1 : the version in argument is newer than the current haproxy version
446 *
447 * Or some errors:
448 * -2 : the current haproxy version is not parsable
449 * -3 : the version in argument is not parsable
450 */
451int compare_current_version(const char *version)
452{
453 unsigned int loc[VERSION_MAX_ELTS];
454 unsigned int mod[VERSION_MAX_ELTS];
455 int i;
456
457 /* split versions */
458 if (!split_version(haproxy_version, loc))
459 return -2;
460 if (!split_version(version, mod))
461 return -3;
462
463 /* compare versions */
464 for (i = 0; i < VERSION_MAX_ELTS; i++) {
465 if (mod[i] < loc[i])
466 return -1;
467 else if (mod[i] > loc[i])
468 return 1;
469 }
470 return 0;
471}
472
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100473static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200474{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200475 struct utsname utsname;
476
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200477 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100478 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100479
480 if (strlen(PRODUCT_URL_BUGS) > 0) {
481 char base_version[20];
482 int dots = 0;
483 char *del;
484
485 /* only retrieve the base version without distro-specific extensions */
486 for (del = haproxy_version; *del; del++) {
487 if (*del == '.')
488 dots++;
489 else if (*del < '0' || *del > '9')
490 break;
491 }
492
493 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
494 if (dots < 2)
495 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
496 else
497 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
498 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200499
500 if (uname(&utsname) == 0) {
501 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200503}
504
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100505static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100506{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100507 struct build_opts_str *item;
508
Willy Tarreau7b066db2007-12-02 11:28:59 +0100509 printf("Build options :"
510#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100511 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100512#endif
513#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100514 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100515#endif
516#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100517 "\n CC = " BUILD_CC
518#endif
519#ifdef BUILD_CFLAGS
520 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100521#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100522#ifdef BUILD_OPTIONS
523 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100524#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100525#ifdef BUILD_DEBUG
526 "\n DEBUG = " BUILD_DEBUG
527#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100528#ifdef BUILD_FEATURES
529 "\n\nFeature list : " BUILD_FEATURES
530#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200531 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100532 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200533 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100534 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200535
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100536 list_for_each_entry(item, &build_opts_list, list) {
537 puts(item->str);
538 }
539
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100540 putchar('\n');
541
Willy Tarreaube5b6852009-10-03 18:57:08 +0200542 list_pollers(stdout);
543 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200544 list_mux_proto(stdout);
545 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100546 list_services(stdout);
547 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100548 list_filters(stdout);
549 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100550}
551
Willy Tarreaubaaee002006-06-26 02:48:02 +0200552/*
553 * This function prints the command line usage and exits
554 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100555static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200556{
557 display_version();
558 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200559 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200560 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200561 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100562 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200563 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreau6e064432012-05-08 15:40:42 +0200564 " -dM[<byte>] poisons memory with <byte> (defaults to 0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200565 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200566 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200567 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100568#if defined(USE_SYSTEMD)
569 " -Ws master-worker mode with systemd notify support.\n"
570#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200571 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200572 " -c check mode : only check config files and exit\n"
Maximilian Maderfc0cceb2021-06-06 00:50:22 +0200573 " -cc check condition : evaluate a condition and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100574 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575 " -m limits the usable amount of memory (in MB)\n"
576 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200577 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200578 " -p writes pids of all children to this file\n"
Willy Tarreaue5733232019-05-22 19:24:06 +0200579#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 " -de disables epoll() usage even when available\n"
581#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200582#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200583 " -dk disables kqueue() usage even when available\n"
584#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200585#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000586 " -dv disables event ports usage even when available\n"
587#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200588#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 " -dp disables poll() usage even when available\n"
590#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200591#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100592 " -dS disables splice usage (broken on old kernels)\n"
593#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200594#if defined(USE_GETADDRINFO)
595 " -dG disables getaddrinfo() usage\n"
596#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000597#if defined(SO_REUSEPORT)
598 " -dR disables SO_REUSEPORT usage\n"
599#endif
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100600 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100601 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200602 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200603 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200604 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200605 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200606 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100608 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200609 exit(1);
610}
611
612
613
614/*********************************************************************/
615/* more specific functions ***************************************/
616/*********************************************************************/
617
William Lallemand73b85e72017-06-01 17:38:51 +0200618/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
619 * pids the signal was correctly delivered to.
620 */
William Lallemande25473c2019-04-01 11:29:56 +0200621int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200622{
623 int p;
624 int ret = 0;
625 for (p = 0; p < nb_oldpids; p++)
626 if (kill(oldpids[p], sig) == 0)
627 ret++;
628 return ret;
629}
630
William Lallemand75ea0a02017-11-15 19:02:58 +0100631/*
William Lallemand73b85e72017-06-01 17:38:51 +0200632 * remove a pid forom the olpid array and decrease nb_oldpids
633 * return 1 pid was found otherwise return 0
634 */
635
636int delete_oldpid(int pid)
637{
638 int i;
639
640 for (i = 0; i < nb_oldpids; i++) {
641 if (oldpids[i] == pid) {
642 oldpids[i] = oldpids[nb_oldpids - 1];
643 oldpids[nb_oldpids - 1] = 0;
644 nb_oldpids--;
645 return 1;
646 }
647 }
648 return 0;
649}
650
William Lallemand85b0bd92017-06-01 17:38:53 +0200651
William Lallemand73b85e72017-06-01 17:38:51 +0200652/*
653 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800654 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200655 */
William Lallemandfab0fdc2021-11-09 18:01:22 +0100656static void mworker_reexec()
William Lallemand73b85e72017-06-01 17:38:51 +0200657{
William Lallemand00417412020-06-05 14:08:41 +0200658 char **next_argv = NULL;
659 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200660 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200661 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200662 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100663 struct rlimit limit;
William Lallemand7c756a82018-11-26 11:53:40 +0100664 struct per_thread_deinit_fct *ptdf;
William Lallemand2be557f2021-11-24 18:45:37 +0100665 struct mworker_proc *current_child = NULL;
William Lallemand73b85e72017-06-01 17:38:51 +0200666
667 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100668#if defined(USE_SYSTEMD)
669 if (global.tune.options & GTUNE_USE_SYSTEMD)
670 sd_notify(0, "RELOADING=1");
671#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200672 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
673
William Lallemandbc193052018-09-11 10:06:26 +0200674 mworker_proc_list_to_env(); /* put the children description in the env */
675
William Lallemandc4810b82021-11-18 10:51:30 +0100676 /* ensure that we close correctly every listeners before reexecuting */
677 mworker_cleanlisteners();
678
William Lallemand7c756a82018-11-26 11:53:40 +0100679 /* during the reload we must ensure that every FDs that can't be
680 * reuse (ie those that are not referenced in the proc_list)
681 * are closed or they will leak. */
682
683 /* close the listeners FD */
684 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200685
William Lallemand67e371e2021-11-25 10:03:44 +0100686 /* close the poller FD and the thread waker pipe FD */
687 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
688 ptdf->fct();
689 if (fdtab)
690 deinit_pollers();
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500691#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200692 /* close random device FDs */
693 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100694#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100695
Willy Tarreau8dca1952019-03-01 10:21:55 +0100696 /* restore the initial FD limits */
697 limit.rlim_cur = rlim_fd_cur_at_boot;
698 limit.rlim_max = rlim_fd_max_at_boot;
699 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
700 getrlimit(RLIMIT_NOFILE, &limit);
701 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
702 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
703 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
704 }
705
William Lallemand73b85e72017-06-01 17:38:51 +0200706 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200707 while (old_argv[old_argc])
708 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200709
William Lallemand85b0bd92017-06-01 17:38:53 +0200710 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200711 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200712 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200713 if (next_argv == NULL)
714 goto alloc_error;
715
William Lallemand00417412020-06-05 14:08:41 +0200716 /* copy the program name */
717 next_argv[next_argc++] = old_argv[0];
718
719 /* insert the new options just after argv[0] in case we have a -- */
720
William Lallemandbefab9e2021-11-25 00:49:19 +0100721 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
722 /* add -sf <PID>* to argv */
723 if (mworker_child_nb() > 0) {
724 struct mworker_proc *child;
William Lallemand3f128872019-04-01 11:29:59 +0200725
William Lallemandbefab9e2021-11-25 00:49:19 +0100726 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200727
William Lallemandbefab9e2021-11-25 00:49:19 +0100728 list_for_each_entry(child, &proc_list, list) {
729 if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
730 current_child = child;
William Lallemand2be557f2021-11-24 18:45:37 +0100731
William Lallemandbefab9e2021-11-25 00:49:19 +0100732 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
733 continue;
734 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
735 goto alloc_error;
736 msg = NULL;
737 }
William Lallemand73b85e72017-06-01 17:38:51 +0200738 }
William Lallemand2be557f2021-11-24 18:45:37 +0100739
740 if (current_child) {
741 /* add the -x option with the socketpair of the current worker */
742 next_argv[next_argc++] = "-x";
743 if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
744 goto alloc_error;
745 msg = NULL;
746 }
William Lallemand85b0bd92017-06-01 17:38:53 +0200747 }
748
William Lallemand00417412020-06-05 14:08:41 +0200749 /* copy the previous options */
750 for (i = 1; i < old_argc; i++)
751 next_argv[next_argc++] = old_argv[i];
752
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200753 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100754 execvp(next_argv[0], next_argv);
Christopher Faulet767a84b2017-11-24 16:50:31 +0100755 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100756 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100757 return;
758
William Lallemand73b85e72017-06-01 17:38:51 +0200759alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100760 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800761 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200762 return;
763}
764
William Lallemandfab0fdc2021-11-09 18:01:22 +0100765/* reexec haproxy in waitmode */
766static void mworker_reexec_waitmode()
767{
768 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
769 mworker_reexec();
770}
771
772/* reload haproxy and emit a warning */
773void mworker_reload()
774{
William Lallemandad221f42021-11-09 18:43:59 +0100775 struct mworker_proc *child;
776
William Lallemand836bda22021-11-09 18:16:47 +0100777 ha_notice("Reloading HAProxy\n");
William Lallemandad221f42021-11-09 18:43:59 +0100778
779 /* increment the number of reloads */
780 list_for_each_entry(child, &proc_list, list) {
781 child->reloads++;
782 }
783
William Lallemandfab0fdc2021-11-09 18:01:22 +0100784 mworker_reexec();
785}
786
William Lallemandb3f2be32018-09-11 10:06:18 +0200787static void mworker_loop()
788{
789
790#if defined(USE_SYSTEMD)
791 if (global.tune.options & GTUNE_USE_SYSTEMD)
792 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
793#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200794 /* Busy polling makes no sense in the master :-) */
795 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200796
William Lallemandbc193052018-09-11 10:06:26 +0200797
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100798 signal_unregister(SIGTTIN);
799 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100800 signal_unregister(SIGUSR1);
801 signal_unregister(SIGHUP);
802 signal_unregister(SIGQUIT);
803
William Lallemandb3f2be32018-09-11 10:06:18 +0200804 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
805 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100806 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
807 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200808 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
809 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
810 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
811 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
812
813 mworker_unblock_signals();
William Lallemand27f3fa52018-12-06 14:05:20 +0100814 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200815
William Lallemandbc193052018-09-11 10:06:26 +0200816 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
817 some SIGCHLD were lost */
818
William Lallemandb3f2be32018-09-11 10:06:18 +0200819 global.nbthread = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200820
William Lallemand2672eb92018-12-14 15:52:39 +0100821#ifdef USE_THREAD
822 tid_bit = 1;
823 all_threads_mask = 1;
824#endif
825
William Lallemandb3f2be32018-09-11 10:06:18 +0200826 jobs++; /* this is the "master" job, we want to take care of the
827 signals even if there is no listener so the poll loop don't
828 leave */
829
830 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200831 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200832}
William Lallemandcb11fd22017-06-01 17:38:52 +0200833
834/*
835 * Reexec the process in failure mode, instead of exiting
836 */
837void reexec_on_failure()
838{
William Lallemand68836742021-11-10 10:49:06 +0100839 struct mworker_proc *child;
840
William Lallemandcb11fd22017-06-01 17:38:52 +0200841 if (!atexit_flag)
842 return;
William Lallemand68836742021-11-10 10:49:06 +0100843
844 /* get the info of the children in the env */
845 if (mworker_env_to_proc_list() < 0) {
846 exit(EXIT_FAILURE);
847 }
848
849 /* increment the number of failed reloads */
850 list_for_each_entry(child, &proc_list, list) {
851 child->failedreloads++;
852 }
853
William Lallemandfab0fdc2021-11-09 18:01:22 +0100854 usermsgs_clr(NULL);
William Lallemand836bda22021-11-09 18:16:47 +0100855 ha_warning("Loading failure!\n");
William Lallemandfab0fdc2021-11-09 18:01:22 +0100856 mworker_reexec_waitmode();
William Lallemandcb11fd22017-06-01 17:38:52 +0200857}
William Lallemand73b85e72017-06-01 17:38:51 +0200858
859
860/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200861 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
862 * a signal zero to all subscribers. This means that it's as easy as
863 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200864 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100865static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200866{
867 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200868 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100869 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200870}
871
872/*
873 * upon SIGTTOU, we pause everything
874 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100875static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200876{
Willy Tarreau775e0012020-09-24 16:36:26 +0200877 if (protocol_pause_all() & ERR_FATAL) {
878 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200879 ha_warning("%s", msg);
880 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200881 soft_stop();
882 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100883 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200884}
885
886/*
887 * upon SIGTTIN, let's have a soft stop.
888 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100889static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200890{
Willy Tarreau775e0012020-09-24 16:36:26 +0200891 if (protocol_resume_all() & ERR_FATAL) {
892 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 +0200893 ha_warning("%s", msg);
894 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200895 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200896}
897
898/*
899 * this function dumps every server's state when the process receives SIGHUP.
900 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100901static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100903 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904
Christopher Faulet767a84b2017-11-24 16:50:31 +0100905 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906 while (p) {
907 struct server *s = p->srv;
908
909 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
910 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100911 chunk_printf(&trash,
912 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
913 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200914 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200915 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200916 ha_warning("%s\n", trash.area);
917 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 s = s->next;
919 }
920
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200921 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
922 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100923 chunk_printf(&trash,
924 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
925 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200926 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 +0200927 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100928 chunk_printf(&trash,
929 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
930 p->id,
931 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200932 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 +0200933 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100934 chunk_printf(&trash,
935 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
936 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
937 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200938 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 +0200939 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200940 ha_warning("%s\n", trash.area);
941 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942
943 p = p->next;
944 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945}
946
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100947static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200949 /* dump memory usage then free everything possible */
950 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100951 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200952}
953
William Lallemande1340412017-12-28 16:09:36 +0100954/*
955 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
956 * If <fd> < 0, it opens /dev/null and use it to dup
957 *
958 * In the case of chrooting, you have to open /dev/null before the chroot, and
959 * pass the <fd> to this function
960 */
961static void stdio_quiet(int fd)
962{
963 if (fd < 0)
964 fd = open("/dev/null", O_RDWR, 0);
965
966 if (fd > -1) {
967 fclose(stdin);
968 fclose(stdout);
969 fclose(stderr);
970
971 dup2(fd, 0);
972 dup2(fd, 1);
973 dup2(fd, 2);
974 if (fd > 2)
975 close(fd);
976 return;
977 }
978
979 ha_alert("Cannot open /dev/null\n");
980 exit(EXIT_FAILURE);
981}
982
983
Joseph Herlant03420902018-11-15 10:41:50 -0800984/* This function checks if cfg_cfgfiles contains directories.
985 * If it finds one, it adds all the files (and only files) it contains
986 * in cfg_cfgfiles in place of the directory (and removes the directory).
987 * It adds the files in lexical order.
988 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200989 * It doesn't add files with name starting with '.'
990 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100991static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200992{
993 struct wordlist *wl, *wlb;
994 char *err = NULL;
995
996 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
997 struct stat file_stat;
998 struct dirent **dir_entries = NULL;
999 int dir_entries_nb;
1000 int dir_entries_it;
1001
1002 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001003 ha_alert("Cannot open configuration file/directory %s : %s\n",
1004 wl->s,
1005 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001006 exit(1);
1007 }
1008
1009 if (!S_ISDIR(file_stat.st_mode))
1010 continue;
1011
1012 /* from this point wl->s is a directory */
1013
1014 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1015 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001016 ha_alert("Cannot open configuration directory %s : %s\n",
1017 wl->s,
1018 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001019 exit(1);
1020 }
1021
1022 /* for each element in the directory wl->s */
1023 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1024 struct dirent *dir_entry = dir_entries[dir_entries_it];
1025 char *filename = NULL;
1026 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1027
1028 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001029 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001030 */
1031 if (dir_entry->d_name[0] == '.' ||
1032 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1033 goto next_dir_entry;
1034
1035 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001036 ha_alert("Cannot load configuration files %s : out of memory.\n",
1037 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001038 exit(1);
1039 }
1040
1041 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001042 ha_alert("Cannot open configuration file %s : %s\n",
1043 wl->s,
1044 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001045 exit(1);
1046 }
1047
1048 /* don't add anything else than regular file in cfg_cfgfiles
1049 * this way we avoid loops
1050 */
1051 if (!S_ISREG(file_stat.st_mode))
1052 goto next_dir_entry;
1053
1054 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001055 ha_alert("Cannot load configuration files %s : %s\n",
1056 filename,
1057 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001058 exit(1);
1059 }
1060
1061next_dir_entry:
1062 free(filename);
1063 free(dir_entry);
1064 }
1065
1066 free(dir_entries);
1067
1068 /* remove the current directory (wl) from cfg_cfgfiles */
1069 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001070 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001071 free(wl);
1072 }
1073
1074 free(err);
1075}
1076
Willy Tarreaubaaee002006-06-26 02:48:02 +02001077/*
William Lallemand73b85e72017-06-01 17:38:51 +02001078 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001079 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001080 * Return an allocated copy of argv
1081 */
1082
1083static char **copy_argv(int argc, char **argv)
1084{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001085 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001086
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001087 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001088 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001089 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001090 return NULL;
1091 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001092 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001093
William Lallemanddf6c5a82020-06-04 17:40:23 +02001094 /* first copy argv[0] */
1095 *newargv++ = *argv++;
1096 argc--;
1097
1098 while (argc > 0) {
1099 if (**argv != '-') {
1100 /* non options are copied but will fail in the argument parser */
1101 *newargv++ = *argv++;
1102 argc--;
1103
1104 } else {
1105 char *flag;
1106
1107 flag = *argv + 1;
1108
1109 if (flag[0] == '-' && flag[1] == 0) {
1110 /* "--\0" copy every arguments till the end of argv */
1111 *newargv++ = *argv++;
1112 argc--;
1113
1114 while (argc > 0) {
1115 *newargv++ = *argv++;
1116 argc--;
1117 }
1118 } else {
1119 switch (*flag) {
1120 case 's':
1121 /* -sf / -st and their parameters are ignored */
1122 if (flag[1] == 'f' || flag[1] == 't') {
1123 argc--;
1124 argv++;
1125 /* The list can't contain a negative value since the only
1126 way to know the end of this list is by looking for the
1127 next option or the end of the options */
1128 while (argc > 0 && argv[0][0] != '-') {
1129 argc--;
1130 argv++;
1131 }
William Lallemand398da622020-09-02 16:12:23 +02001132 } else {
1133 argc--;
1134 argv++;
1135
William Lallemanddf6c5a82020-06-04 17:40:23 +02001136 }
1137 break;
1138
1139 case 'x':
1140 /* this option and its parameter are ignored */
1141 argc--;
1142 argv++;
1143 if (argc > 0) {
1144 argc--;
1145 argv++;
1146 }
1147 break;
1148
1149 case 'C':
1150 case 'n':
1151 case 'm':
1152 case 'N':
1153 case 'L':
1154 case 'f':
1155 case 'p':
1156 case 'S':
1157 /* these options have only 1 parameter which must be copied and can start with a '-' */
1158 *newargv++ = *argv++;
1159 argc--;
1160 if (argc == 0)
1161 goto error;
1162 *newargv++ = *argv++;
1163 argc--;
1164 break;
1165 default:
1166 /* for other options just copy them without parameters, this is also done
1167 * for options like "--foo", but this will fail in the argument parser.
1168 * */
1169 *newargv++ = *argv++;
1170 argc--;
1171 break;
1172 }
William Lallemand73b85e72017-06-01 17:38:51 +02001173 }
1174 }
William Lallemand73b85e72017-06-01 17:38:51 +02001175 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001176
William Lallemanddf6c5a82020-06-04 17:40:23 +02001177 return retargv;
1178
1179error:
1180 free(retargv);
1181 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001182}
1183
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001184
1185/* Performs basic random seed initialization. The main issue with this is that
1186 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1187 * which means that there will only be 4 billion possible random sequences once
1188 * srandom() is called, regardless of the internal state. Not calling it is
1189 * even worse as we'll always produce the same randoms sequences. What we do
1190 * here is to create an initial sequence from various entropy sources, hash it
1191 * using SHA1 and keep the resulting 160 bits available globally.
1192 *
1193 * We initialize the current process with the first 32 bits before starting the
1194 * polling loop, where all this will be changed to have process specific and
1195 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001196 *
1197 * Before starting threads, it's still possible to call random() as srandom()
1198 * is initialized from this, but after threads and/or processes are started,
1199 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001200 */
1201static void ha_random_boot(char *const *argv)
1202{
1203 unsigned char message[256];
1204 unsigned char *m = message;
1205 struct timeval tv;
1206 blk_SHA_CTX ctx;
1207 unsigned long l;
1208 int fd;
1209 int i;
1210
1211 /* start with current time as pseudo-random seed */
1212 gettimeofday(&tv, NULL);
1213 write_u32(m, tv.tv_sec); m += 4;
1214 write_u32(m, tv.tv_usec); m += 4;
1215
1216 /* PID and PPID add some OS-based randomness */
1217 write_u16(m, getpid()); m += 2;
1218 write_u16(m, getppid()); m += 2;
1219
1220 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1221 fd = open("/dev/urandom", O_RDONLY);
1222 if (fd >= 0) {
1223 i = read(fd, m, 20);
1224 if (i > 0)
1225 m += i;
1226 close(fd);
1227 }
1228
1229 /* take up to 160 bits bytes from openssl (non-blocking) */
1230#ifdef USE_OPENSSL
1231 if (RAND_bytes(m, 20) == 1)
1232 m += 20;
1233#endif
1234
1235 /* take 160 bits from existing random in case it was already initialized */
1236 for (i = 0; i < 5; i++) {
1237 write_u32(m, random());
1238 m += 4;
1239 }
1240
1241 /* stack address (benefit form operating system's ASLR) */
1242 l = (unsigned long)&m;
1243 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1244
1245 /* argv address (benefit form operating system's ASLR) */
1246 l = (unsigned long)&argv;
1247 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1248
1249 /* use tv_usec again after all the operations above */
1250 gettimeofday(&tv, NULL);
1251 write_u32(m, tv.tv_usec); m += 4;
1252
1253 /*
1254 * At this point, ~84-92 bytes have been used
1255 */
1256
1257 /* finish with the hostname */
1258 strncpy((char *)m, hostname, message + sizeof(message) - m);
1259 m += strlen(hostname);
1260
1261 /* total message length */
1262 l = m - message;
1263
1264 memset(&ctx, 0, sizeof(ctx));
1265 blk_SHA1_Init(&ctx);
1266 blk_SHA1_Update(&ctx, message, l);
1267 blk_SHA1_Final(boot_seed, &ctx);
1268
1269 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001270 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001271}
1272
Willy Tarreau5a023f02019-03-01 14:19:31 +01001273/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1274 * setting, and returns it. It may return -1 meaning "unlimited" if some
1275 * unlimited proxies have been found and the global.maxconn value is not yet
1276 * set. It may also return a value greater than maxconn if it's not yet set.
1277 * Note that a value of zero means there is no need for pipes. -1 is never
1278 * returned if global.maxconn is valid.
1279 */
1280static int compute_ideal_maxpipes()
1281{
1282 struct proxy *cur;
1283 int nbfe = 0, nbbe = 0;
1284 int unlimited = 0;
1285 int pipes;
1286 int max;
1287
1288 for (cur = proxies_list; cur; cur = cur->next) {
1289 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1290 if (cur->cap & PR_CAP_FE) {
1291 max = cur->maxconn;
1292 nbfe += max;
1293 if (!max) {
1294 unlimited = 1;
1295 break;
1296 }
1297 }
1298 if (cur->cap & PR_CAP_BE) {
1299 max = cur->fullconn ? cur->fullconn : global.maxconn;
1300 nbbe += max;
1301 if (!max) {
1302 unlimited = 1;
1303 break;
1304 }
1305 }
1306 }
1307 }
1308
1309 pipes = MAX(nbfe, nbbe);
1310 if (global.maxconn) {
1311 if (pipes > global.maxconn || unlimited)
1312 pipes = global.maxconn;
1313 } else if (unlimited) {
1314 pipes = -1;
1315 }
1316
1317 return pipes >= 4 ? pipes / 4 : pipes;
1318}
1319
Willy Tarreauac350932019-03-01 15:43:14 +01001320/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1321 * rlimits and computes an ideal maxconn. It's meant to be called only when
1322 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001323 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1324 * default 100) is returned as it is expected that it will even run on tight
1325 * environments, and will maintain compatibility with previous packages that
1326 * used to rely on this value as the default one. The system will emit a
1327 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001328 */
1329static int compute_ideal_maxconn()
1330{
1331 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1332 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1333 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001334 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001335 int maxconn;
1336
1337 /* we have to take into account these elements :
1338 * - number of engine_fds, which inflates the number of FD needed per
1339 * connection by this number.
1340 * - number of pipes per connection on average : for the unlimited
1341 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1342 * fixed value of 2*pipes.
1343 * - two FDs per connection
1344 */
1345
1346 /* subtract listeners and checks */
1347 remain -= global.maxsock;
1348
Willy Tarreau3f200852019-03-14 19:13:17 +01001349 /* one epoll_fd/kqueue_fd per thread */
1350 remain -= global.nbthread;
1351
1352 /* one wake-up pipe (2 fd) per thread */
1353 remain -= 2 * global.nbthread;
1354
Willy Tarreauac350932019-03-01 15:43:14 +01001355 /* Fixed pipes values : we only subtract them if they're not larger
1356 * than the remaining FDs because pipes are optional.
1357 */
1358 if (pipes >= 0 && pipes * 2 < remain)
1359 remain -= pipes * 2;
1360
1361 if (pipes < 0) {
1362 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1363 * = maxconn * (2 + 0.5 + engine_fds)
1364 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1365 */
1366 maxconn = 2 * remain / (5 + 2 * engine_fds);
1367 } else {
1368 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1369 * = maxconn * (2 + engine_fds)
1370 */
1371 maxconn = remain / (2 + engine_fds);
1372 }
1373
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001374 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001375}
1376
Willy Tarreaua409f302020-03-10 17:08:53 +01001377/* computes the estimated maxsock value for the given maxconn based on the
1378 * possibly set global.maxpipes and existing partial global.maxsock. It may
1379 * temporarily change global.maxconn for the time needed to propagate the
1380 * computations, and will reset it.
1381 */
1382static int compute_ideal_maxsock(int maxconn)
1383{
1384 int maxpipes = global.maxpipes;
1385 int maxsock = global.maxsock;
1386
1387
1388 if (!maxpipes) {
1389 int old_maxconn = global.maxconn;
1390
1391 global.maxconn = maxconn;
1392 maxpipes = compute_ideal_maxpipes();
1393 global.maxconn = old_maxconn;
1394 }
1395
1396 maxsock += maxconn * 2; /* each connection needs two sockets */
1397 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1398 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1399 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1400
1401 /* compute fd used by async engines */
1402 if (global.ssl_used_async_engines) {
1403 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1404
1405 maxsock += maxconn * sides * global.ssl_used_async_engines;
1406 }
1407 return maxsock;
1408}
1409
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001410/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001411 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1412 * value is accepted, non-zero otherwise. This is used to determine if an
1413 * automatic limit may be applied or not. When it is not, the caller knows that
1414 * the highest we can do is the rlim_max at boot. In case of error, we return
1415 * that the setting is possible, so that we defer the error processing to the
1416 * final stage in charge of enforcing this.
1417 */
1418static int check_if_maxsock_permitted(int maxsock)
1419{
1420 struct rlimit orig_limit, test_limit;
1421 int ret;
1422
1423 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1424 return 1;
1425
1426 /* don't go further if we can't even set to what we have */
1427 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1428 return 1;
1429
1430 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1431 test_limit.rlim_cur = test_limit.rlim_max;
1432 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1433
1434 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1435 return 1;
1436
1437 return ret == 0;
1438}
1439
Amaury Denoyelle484454d2021-05-05 16:18:45 +02001440void mark_tainted(const enum tainted_flags flag)
1441{
1442 HA_ATOMIC_OR(&tainted, flag);
1443}
1444
1445unsigned int get_tainted()
1446{
1447 int tainted_state;
1448 HA_ATOMIC_STORE(&tainted_state, tainted);
1449 return tainted_state;
1450}
Willy Tarreau304e17e2020-03-10 17:54:54 +01001451
William Lallemand73b85e72017-06-01 17:38:51 +02001452/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02001453 * This function initializes all the necessary variables. It only returns
1454 * if everything is OK. If something fails, it exits.
1455 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001456static void init(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457{
Willy Tarreaubaaee002006-06-26 02:48:02 +02001458 int arg_mode = 0; /* MODE_DEBUG, ... */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459 char *tmp;
1460 char *cfg_pidfile = NULL;
Willy Tarreau058e9072009-07-20 09:30:05 +02001461 int err_code = 0;
Maxime de Roucy0f503922016-05-13 23:52:55 +02001462 char *err_msg = NULL;
Willy Tarreau477ecd82010-01-03 21:12:30 +01001463 struct wordlist *wl;
Kevinm48936af2010-12-22 16:08:21 +00001464 char *progname;
Willy Tarreau576132e2011-09-10 19:26:56 +02001465 char *change_dir = NULL;
Christopher Fauletd7c91962015-04-30 11:48:27 +02001466 struct proxy *px;
Willy Tarreaue6945732016-12-21 19:57:00 +01001467 struct post_check_fct *pcf;
Willy Tarreauac350932019-03-01 15:43:14 +01001468 int ideal_maxconn;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001469 char *check_condition = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470
Christopher Faulete3a5e352017-10-24 13:53:54 +02001471 global.mode = MODE_STARTING;
William Lallemand00417412020-06-05 14:08:41 +02001472 old_argv = copy_argv(argc, argv);
1473 if (!old_argv) {
William Lallemanddf6c5a82020-06-04 17:40:23 +02001474 ha_alert("failed to copy argv.\n");
1475 exit(1);
1476 }
William Lallemand73b85e72017-06-01 17:38:51 +02001477
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001478 if (!init_trash_buffers(1)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001479 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet748919a2017-07-26 14:59:46 +02001480 exit(1);
1481 }
David du Colombier7af46052012-05-16 14:16:48 +02001482
Emeric Brun2b920a12010-09-23 18:30:22 +02001483 /* NB: POSIX does not make it mandatory for gethostname() to NULL-terminate
1484 * the string in case of truncation, and at least FreeBSD appears not to do
1485 * it.
1486 */
1487 memset(hostname, 0, sizeof(hostname));
1488 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001489
1490 if ((localpeer = strdup(hostname)) == NULL) {
1491 ha_alert("Cannot allocate memory for local peer.\n");
1492 exit(EXIT_FAILURE);
1493 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001494 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Emeric Brun2b920a12010-09-23 18:30:22 +02001495
William Lallemand24c928c2020-01-14 17:58:18 +01001496 /* we were in mworker mode, we should restart in mworker mode */
1497 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1498 global.mode |= MODE_MWORKER;
1499
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500 /*
1501 * Initialize the previously static variables.
1502 */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001503
Willy Tarreau173d9952018-01-26 21:48:23 +01001504 totalconn = actconn = listeners = stopping = 0;
Cyril Bonté203ec5a2017-03-23 22:44:13 +01001505 killed = 0;
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001506
Willy Tarreaubaaee002006-06-26 02:48:02 +02001507
1508#ifdef HAPROXY_MEMMAX
Willy Tarreau70060452015-12-14 12:46:07 +01001509 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001510#endif
1511
Benoit GARNIERb413c2a2016-03-27 11:08:03 +02001512 tzset();
Willy Tarreau55542642021-10-08 09:33:24 +02001513 clock_init_process_date();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001514 start_date = now;
1515
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001516 ha_random_boot(argv);
Willy Tarreau84310e22014-02-14 11:59:04 +01001517
Willy Tarreau8ed669b2013-01-11 15:49:37 +01001518 if (init_acl() != 0)
1519 exit(1);
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001520
Amaury Denoyellec593bcd2021-05-19 15:35:29 +02001521#ifdef USE_OPENSSL
1522 /* Initialize the random generator.
1523 * Must be called before chroot for access to /dev/urandom
1524 */
1525 if (!ssl_initialize_random()) {
1526 ha_alert("OpenSSL random data generator initialization failed.\n");
1527 exit(1);
1528 }
1529#endif
1530
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001531 /* Initialise lua. */
1532 hlua_init();
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001533
Christopher Fauletff2613e2016-11-09 11:36:17 +01001534 /* Initialize process vars */
Willy Tarreaub7bfcb32021-08-31 08:13:25 +02001535 vars_init_head(&proc_vars, SCOPE_PROC);
Christopher Fauletff2613e2016-11-09 11:36:17 +01001536
Willy Tarreau43b78992009-01-25 15:42:27 +01001537 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001538#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001539 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001540#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001541#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001542 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001543#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001544#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001545 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001546#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001547#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001548 global.tune.options |= GTUNE_USE_EVPORTS;
1549#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001550#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001551 global.tune.options |= GTUNE_USE_SPLICE;
1552#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001553#if defined(USE_GETADDRINFO)
1554 global.tune.options |= GTUNE_USE_GAI;
1555#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001556#if defined(SO_REUSEPORT)
1557 global.tune.options |= GTUNE_USE_REUSEPORT;
1558#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001559#ifdef USE_THREAD
1560 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1561#endif
William Dauchya5194602020-03-28 19:29:58 +01001562 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563
1564 pid = getpid();
1565 progname = *argv;
1566 while ((tmp = strchr(progname, '/')) != NULL)
1567 progname = tmp + 1;
1568
Kevinm48936af2010-12-22 16:08:21 +00001569 /* the process name is used for the logs only */
Eric Salama7cea6062020-10-02 11:58:19 +02001570 chunk_initlen(&global.log_tag, strdup(progname), strlen(progname), strlen(progname));
1571 if (b_orig(&global.log_tag) == NULL) {
1572 chunk_destroy(&global.log_tag);
1573 ha_alert("Cannot allocate memory for log_tag.\n");
1574 exit(EXIT_FAILURE);
1575 }
Kevinm48936af2010-12-22 16:08:21 +00001576
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577 argc--; argv++;
1578 while (argc > 0) {
1579 char *flag;
1580
1581 if (**argv == '-') {
1582 flag = *argv+1;
1583
1584 /* 1 arg */
1585 if (*flag == 'v') {
1586 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001587 if (flag[1] == 'v') /* -vv */
1588 display_build_opts();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589 exit(0);
1590 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001591#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001593 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001595#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001597 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001599#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001600 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001601 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001602#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001603#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001604 else if (*flag == 'd' && flag[1] == 'v')
1605 global.tune.options &= ~GTUNE_USE_EVPORTS;
1606#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001607#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001608 else if (*flag == 'd' && flag[1] == 'S')
1609 global.tune.options &= ~GTUNE_USE_SPLICE;
1610#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001611#if defined(USE_GETADDRINFO)
1612 else if (*flag == 'd' && flag[1] == 'G')
1613 global.tune.options &= ~GTUNE_USE_GAI;
1614#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001615#if defined(SO_REUSEPORT)
1616 else if (*flag == 'd' && flag[1] == 'R')
1617 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1618#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001619 else if (*flag == 'd' && flag[1] == 'V')
1620 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001621 else if (*flag == 'V')
1622 arg_mode |= MODE_VERBOSE;
1623 else if (*flag == 'd' && flag[1] == 'b')
1624 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001625 else if (*flag == 'd' && flag[1] == 'D')
1626 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001627 else if (*flag == 'd' && flag[1] == 'W')
1628 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreau6e064432012-05-08 15:40:42 +02001629 else if (*flag == 'd' && flag[1] == 'M')
1630 mem_poison_byte = flag[2] ? strtol(flag + 2, NULL, 0) : 'P';
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001631 else if (*flag == 'd' && flag[1] == 'r')
1632 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001633 else if (*flag == 'd')
1634 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001635 else if (*flag == 'c' && flag[1] == 'c') {
1636 arg_mode |= MODE_CHECK_CONDITION;
1637 argv++;
1638 argc--;
1639 check_condition = *argv;
1640 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001641 else if (*flag == 'c')
1642 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001643 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001644 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001645 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001646 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001647#if defined(USE_SYSTEMD)
1648 global.tune.options |= GTUNE_USE_SYSTEMD;
1649#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001650 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 +01001651 usage(progname);
1652#endif
1653 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001654 else if (*flag == 'W')
1655 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 else if (*flag == 'q')
1657 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001658 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001659 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001660 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001661 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001662 }
William Lallemand4fc09692017-06-19 16:37:19 +02001663 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001664 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001665 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001666
Olivier Houchardf73629d2017-04-05 22:33:04 +02001667 argv++;
1668 argc--;
1669 }
William Lallemande7361152018-10-26 14:47:36 +02001670 else if (*flag == 'S') {
1671 struct wordlist *c;
1672
William Lallemanda6b32492020-06-04 23:49:20 +02001673 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001674 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1675 usage(progname);
1676 }
1677 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1678 ha_alert("Cannot allocate memory\n");
1679 exit(EXIT_FAILURE);
1680 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001681 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001682
1683 argv++;
1684 argc--;
1685 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1687 /* list of pids to finish ('f') or terminate ('t') */
1688
1689 if (flag[1] == 'f')
1690 oldpids_sig = SIGUSR1; /* finish then exit */
1691 else
1692 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001693 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001694 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001695 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1696 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001697 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001698 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001699 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001700 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001701 errno = 0;
1702 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1703 if (errno) {
1704 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1705 flag,
1706 *argv, strerror(errno));
1707 exit(1);
1708 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001709 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001710 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001711 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1712 flag, endptr);
1713 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001714 }
Chris Lane236062f2018-02-05 23:15:44 +00001715 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001716 if (oldpids[nb_oldpids] <= 0)
1717 usage(progname);
1718 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001719 }
1720 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001721 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1722 /* now that's a cfgfile list */
1723 argv++; argc--;
1724 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001725 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001726 ha_alert("Cannot load configuration file/directory %s : %s\n",
1727 *argv,
1728 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001729 exit(1);
1730 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001731 argv++; argc--;
1732 }
1733 break;
1734 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001735 else { /* >=2 args */
1736 argv++; argc--;
1737 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001738 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739
1740 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001741 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001742 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001743 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001744 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001745 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001746 free(localpeer);
1747 if ((localpeer = strdup(*argv)) == NULL) {
1748 ha_alert("Cannot allocate memory for local peer.\n");
1749 exit(EXIT_FAILURE);
1750 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001751 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001752 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001753 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001754 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001755 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001756 ha_alert("Cannot load configuration file/directory %s : %s\n",
1757 *argv,
1758 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001759 exit(1);
1760 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001761 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001762 case 'p' : cfg_pidfile = *argv; break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001763 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001764 }
1765 }
1766 }
1767 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001768 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001769 argv++; argc--;
1770 }
1771
Christopher Faulete3a5e352017-10-24 13:53:54 +02001772 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001773 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001774 | MODE_DIAG | MODE_CHECK_CONDITION));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001775
William Lallemand944e6192018-11-21 15:48:31 +01001776 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001777 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001778 global.mode |= MODE_MWORKER_WAIT;
1779 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001780 }
1781
Willy Tarreau26146192021-07-21 10:01:36 +02001782 if ((global.mode & (MODE_MWORKER | MODE_CHECK | MODE_CHECK_CONDITION)) == MODE_MWORKER &&
1783 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001784 atexit_flag = 1;
1785 atexit(reexec_on_failure);
1786 }
1787
Willy Tarreau576132e2011-09-10 19:26:56 +02001788 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001789 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001790 exit(1);
1791 }
1792
Willy Tarreaubaaee002006-06-26 02:48:02 +02001793 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001794
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001795#ifdef USE_CPU_AFFINITY
1796 {
1797 int i;
Willy Tarreau44ea6312021-06-15 08:57:56 +02001798 ha_cpuset_zero(&cpu_map.proc);
1799 ha_cpuset_zero(&cpu_map.proc_t1);
Willy Tarreau26f42a02021-05-14 08:26:38 +02001800 for (i = 0; i < MAX_THREADS; ++i) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02001801 ha_cpuset_zero(&cpu_map.thread[i]);
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001802 }
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001803 }
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001804#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001805
Amaury Denoyelle11124302021-06-04 18:22:08 +02001806 usermsgs_clr("config");
1807
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001808 if (global.mode & MODE_CHECK_CONDITION) {
1809 int result;
1810
1811 uint32_t err;
1812 const char *errptr;
1813 char *errmsg = NULL;
1814
1815 char *args[MAX_LINE_ARGS+1];
1816 int arg = sizeof(args) / sizeof(*args);
1817 size_t outlen = strlen(check_condition) + 1;
Willy Tarreauc8194c32021-07-16 16:38:58 +02001818 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001819
1820 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02001821 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001822 &errptr);
1823
1824 if (err & PARSE_ERR_QUOTE) {
1825 ha_alert("Syntax Error in condition: Unmatched quote.\n");
1826 exit(2);
1827 }
1828
1829 if (err & PARSE_ERR_HEX) {
1830 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
1831 exit(2);
1832 }
1833
1834 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
1835 ha_alert("Error in condition: Line too long.\n");
1836 exit(2);
1837 }
1838
Willy Tarreauc8194c32021-07-16 16:38:58 +02001839 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001840 ha_alert("Error in condition: Too many words.\n");
1841 exit(2);
1842 }
1843
1844 if (err) {
1845 ha_alert("Unhandled error in condition, please report this to the developers.\n");
1846 exit(2);
1847 }
1848
Willy Tarreauc8194c32021-07-16 16:38:58 +02001849 /* remerge all words into a single expression */
1850 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
1851 ;
1852
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001853 result = cfg_eval_condition(args, &errmsg, &errptr);
1854
1855 if (result < 0) {
1856 if (errmsg)
1857 ha_alert("Failed to evaluate condition: %s\n", errmsg);
1858
1859 exit(2);
1860 }
1861
1862 exit(result ? 0 : 1);
1863 }
1864
William Lallemand944e6192018-11-21 15:48:31 +01001865 /* in wait mode, we don't try to read the configuration files */
1866 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001867 char *env_cfgfiles = NULL;
1868 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001869
William Lallemand944e6192018-11-21 15:48:31 +01001870 /* handle cfgfiles that are actually directories */
1871 cfgfiles_expand_directories();
1872
1873 if (LIST_ISEMPTY(&cfg_cfgfiles))
1874 usage(progname);
1875
1876
1877 list_for_each_entry(wl, &cfg_cfgfiles, list) {
1878 int ret;
1879
Christopher Faulet4e366822021-01-12 18:57:38 +01001880 if (env_err == 0) {
1881 if (!memprintf(&env_cfgfiles, "%s%s%s",
1882 (env_cfgfiles ? env_cfgfiles : ""),
1883 (env_cfgfiles ? ";" : ""), wl->s))
1884 env_err = 1;
1885 }
William Lallemand7b302d82019-05-20 11:15:37 +02001886
William Lallemand944e6192018-11-21 15:48:31 +01001887 ret = readcfgfile(wl->s);
1888 if (ret == -1) {
1889 ha_alert("Could not open configuration file %s : %s\n",
1890 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01001891 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001892 exit(1);
1893 }
1894 if (ret & (ERR_ABORT|ERR_FATAL))
1895 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
1896 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01001897 if (err_code & ERR_ABORT) {
1898 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001899 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01001900 }
Willy Tarreauc4382422009-12-06 13:10:44 +01001901 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001902
William Lallemand944e6192018-11-21 15:48:31 +01001903 /* do not try to resolve arguments nor to spot inconsistencies when
1904 * the configuration contains fatal errors caused by files not found
1905 * or failed memory allocations.
1906 */
1907 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1908 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01001909 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001910 exit(1);
1911 }
Christopher Faulet4e366822021-01-12 18:57:38 +01001912 if (env_err) {
1913 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
1914 exit(1);
1915 }
1916 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
1917 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02001918
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02001919 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001920 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01001921 struct mworker_proc *tmproc;
1922
William Lallemand482f9a92019-04-12 16:15:00 +02001923 setenv("HAPROXY_MWORKER", "1", 1);
1924
William Lallemand16dd1b32018-11-19 18:46:18 +01001925 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
1926
William Lallemandf3a86832019-04-01 11:29:58 +02001927 tmproc = calloc(1, sizeof(*tmproc));
William Lallemand16dd1b32018-11-19 18:46:18 +01001928 if (!tmproc) {
1929 ha_alert("Cannot allocate process structures.\n");
1930 exit(EXIT_FAILURE);
1931 }
William Lallemand8f7069a2019-04-12 16:09:23 +02001932 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand68836742021-11-10 10:49:06 +01001933 tmproc->failedreloads = 0;
William Lallemand16dd1b32018-11-19 18:46:18 +01001934 tmproc->reloads = 0;
William Lallemand16dd1b32018-11-19 18:46:18 +01001935 tmproc->pid = pid;
1936 tmproc->timestamp = start_date.tv_sec;
1937 tmproc->ipc_fd[0] = -1;
1938 tmproc->ipc_fd[1] = -1;
1939
1940 proc_self = tmproc;
1941
Willy Tarreau2b718102021-04-21 07:32:39 +02001942 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01001943 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001944
Willy Tarreau6185a032021-06-15 08:02:06 +02001945 tmproc = calloc(1, sizeof(*tmproc));
1946 if (!tmproc) {
1947 ha_alert("Cannot allocate process structures.\n");
1948 exit(EXIT_FAILURE);
1949 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001950
Willy Tarreau6185a032021-06-15 08:02:06 +02001951 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
1952 tmproc->pid = -1;
William Lallemand68836742021-11-10 10:49:06 +01001953 tmproc->failedreloads = 0;
Willy Tarreau6185a032021-06-15 08:02:06 +02001954 tmproc->reloads = 0;
1955 tmproc->timestamp = -1;
Willy Tarreau6185a032021-06-15 08:02:06 +02001956 tmproc->ipc_fd[0] = -1;
1957 tmproc->ipc_fd[1] = -1;
William Lallemandce83b4a2018-10-26 14:47:30 +02001958
Willy Tarreau6185a032021-06-15 08:02:06 +02001959 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
1960 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02001961 }
Willy Tarreau6185a032021-06-15 08:02:06 +02001962
1963 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01001964 }
1965 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
1966 struct wordlist *it, *c;
1967
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02001968 /* get the info of the children in the env */
1969 if (mworker_env_to_proc_list() < 0) {
1970 exit(EXIT_FAILURE);
1971 }
William Lallemande7361152018-10-26 14:47:36 +02001972
William Lallemand550db6d2018-11-06 17:37:12 +01001973 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02001974
William Lallemand550db6d2018-11-06 17:37:12 +01001975 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02001976 ha_alert("Can't create the master's CLI.\n");
1977 exit(EXIT_FAILURE);
1978 }
William Lallemande7361152018-10-26 14:47:36 +02001979
William Lallemand550db6d2018-11-06 17:37:12 +01001980 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
1981
1982 if (mworker_cli_proxy_new_listener(c->s) < 0) {
1983 ha_alert("Can't create the master's CLI.\n");
1984 exit(EXIT_FAILURE);
1985 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001986 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01001987 free(c->s);
1988 free(c);
1989 }
1990 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001991 }
1992
Eric Salama5ba83352021-03-16 15:11:17 +01001993 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
1994 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
1995 }
1996
Christopher Faulet27c8d202021-10-13 09:50:53 +02001997 /* destroy unreferenced defaults proxies */
1998 proxy_destroy_all_unref_defaults();
1999
Willy Tarreaue90904d2021-02-12 14:08:31 +01002000
Willy Tarreaubb925012009-07-23 13:36:36 +02002001 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02002002 for (px = proxies_list; px; px = px->next) {
2003 struct server *srv;
2004 struct post_proxy_check_fct *ppcf;
2005 struct post_server_check_fct *pscf;
2006
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002007 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002008 continue;
2009
Christopher Fauletc1692962019-08-12 09:51:07 +02002010 list_for_each_entry(pscf, &post_server_check_list, list) {
2011 for (srv = px->srv; srv; srv = srv->next)
2012 err_code |= pscf->fct(srv);
2013 }
2014 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2015 err_code |= ppcf->fct(px);
2016 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002017 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002018 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002019 exit(1);
2020 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002021
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002022 err_code |= pattern_finalize_config();
2023 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2024 ha_alert("Failed to finalize pattern config.\n");
2025 exit(1);
2026 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002027
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002028 if (global.rlimit_memmax_all)
2029 global.rlimit_memmax = global.rlimit_memmax_all;
2030
Willy Tarreaue5733232019-05-22 19:24:06 +02002031#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002032 err_code |= netns_init();
2033 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002034 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002035 exit(1);
2036 }
2037#endif
2038
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002039 /* Apply server states */
2040 apply_server_state();
2041
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002042 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002043 srv_compute_all_admin_states(px);
2044
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002045 /* Apply servers' configured address */
2046 err_code |= srv_init_addr();
2047 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002048 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002049 exit(1);
2050 }
2051
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002052 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2053 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2054 exit(1);
2055 }
2056
Willy Tarreaubaaee002006-06-26 02:48:02 +02002057 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002058 struct peers *pr;
2059 struct proxy *px;
2060
Willy Tarreaubebd2122020-04-15 16:06:11 +02002061 if (warned & WARN_ANY)
2062 qfprintf(stdout, "Warnings were found.\n");
2063
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002064 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002065 if (pr->peers_fe)
2066 break;
2067
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002068 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002069 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002070 break;
2071
Emeric Brunbc5c8212021-08-13 09:32:50 +02002072 if (!px) {
2073 /* We may only have log-forward section */
2074 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002075 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002076 break;
2077 }
2078
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002079 if (pr || px) {
2080 /* At least one peer or one listener has been found */
2081 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002082 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002083 }
2084 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2085 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002086 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002087
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002088 if (global.mode & MODE_DIAG) {
2089 cfg_run_diagnostics();
2090 }
2091
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002092 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002093 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002094
Willy Tarreaue6945732016-12-21 19:57:00 +01002095 list_for_each_entry(pcf, &post_check_list, list) {
2096 err_code |= pcf->fct();
2097 if (err_code & (ERR_ABORT|ERR_FATAL))
2098 exit(1);
2099 }
2100
Willy Tarreaubaaee002006-06-26 02:48:02 +02002101 if (cfg_maxconn > 0)
2102 global.maxconn = cfg_maxconn;
2103
Willy Tarreau4975d142021-03-13 11:00:33 +01002104 if (global.cli_fe)
2105 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002106
2107 if (cfg_peers) {
2108 /* peers also need to bypass global maxconn */
2109 struct peers *p = cfg_peers;
2110
2111 for (p = cfg_peers; p; p = p->next)
2112 if (p->peers_fe)
2113 global.maxsock += p->peers_fe->maxconn;
2114 }
2115
Willy Tarreaubaaee002006-06-26 02:48:02 +02002116 if (cfg_pidfile) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002117 free(global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002118 global.pidfile = strdup(cfg_pidfile);
2119 }
2120
Willy Tarreaud0256482015-01-15 21:45:22 +01002121 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002122 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2123 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2124 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2125 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002126 *
2127 * If memmax is set, then it depends on which values are set. If
2128 * maxsslconn is set, we use memmax to determine how many cleartext
2129 * connections may be added, and set maxconn to the sum of the two.
2130 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2131 * the remaining amount of memory between memmax and the cleartext
2132 * connections. If neither are set, then it is considered that all
2133 * connections are SSL-capable, and maxconn is computed based on this,
2134 * then maxsslconn accordingly. We need to know if SSL is used on the
2135 * frontends, backends, or both, because when it's used on both sides,
2136 * we need twice the value for maxsslconn, but we only count the
2137 * handshake once since it is not performed on the two sides at the
2138 * same time (frontend-side is terminated before backend-side begins).
2139 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002140 * ssl_handshake_cost during its initialization. In any case, if
2141 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2142 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002143 */
Willy Tarreauac350932019-03-01 15:43:14 +01002144 ideal_maxconn = compute_ideal_maxconn();
2145
Willy Tarreaud0256482015-01-15 21:45:22 +01002146 if (!global.rlimit_memmax) {
2147 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002148 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002149 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2150 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2151 }
2152 }
2153#ifdef USE_OPENSSL
2154 else if (!global.maxconn && !global.maxsslconn &&
2155 (global.ssl_used_frontend || global.ssl_used_backend)) {
2156 /* memmax is set, compute everything automatically. Here we want
2157 * to ensure that all SSL connections will be served. We take
2158 * care of the number of sides where SSL is used, and consider
2159 * the worst case : SSL used on both sides and doing a handshake
2160 * simultaneously. Note that we can't have more than maxconn
2161 * handshakes at a time by definition, so for the worst case of
2162 * two SSL conns per connection, we count a single handshake.
2163 */
2164 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2165 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002166 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002167
2168 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2169 mem -= global.maxzlibmem;
2170 mem = mem * MEM_USABLE_RATIO;
2171
Willy Tarreau304e17e2020-03-10 17:54:54 +01002172 /* Principle: we test once to set maxconn according to the free
2173 * memory. If it results in values the system rejects, we try a
2174 * second time by respecting rlim_fd_max. If it fails again, we
2175 * go back to the initial value and will let the final code
2176 * dealing with rlimit report the error. That's up to 3 attempts.
2177 */
2178 do {
2179 global.maxconn = mem /
2180 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2181 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2182 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002183
Willy Tarreau304e17e2020-03-10 17:54:54 +01002184 if (retried == 1)
2185 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2186 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002187#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002188 if (global.maxconn > SYSTEM_MAXCONN)
2189 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002190#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002191 global.maxsslconn = sides * global.maxconn;
2192
2193 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2194 break;
2195 } while (retried++ < 2);
2196
Willy Tarreaud0256482015-01-15 21:45:22 +01002197 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2198 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2199 global.maxconn, global.maxsslconn);
2200 }
2201 else if (!global.maxsslconn &&
2202 (global.ssl_used_frontend || global.ssl_used_backend)) {
2203 /* memmax and maxconn are known, compute maxsslconn automatically.
2204 * maxsslconn being forced, we don't know how many of it will be
2205 * on each side if both sides are being used. The worst case is
2206 * when all connections use only one SSL instance because
2207 * handshakes may be on two sides at the same time.
2208 */
2209 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2210 int64_t mem = global.rlimit_memmax * 1048576ULL;
2211 int64_t sslmem;
2212
2213 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2214 mem -= global.maxzlibmem;
2215 mem = mem * MEM_USABLE_RATIO;
2216
Willy Tarreau87b09662015-04-03 00:22:06 +02002217 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002218 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2219 global.maxsslconn = round_2dig(global.maxsslconn);
2220
2221 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002222 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2223 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2224 "without SSL is %d, but %d was found and SSL is in use.\n",
2225 global.rlimit_memmax,
2226 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2227 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002228 exit(1);
2229 }
2230
2231 if (global.maxsslconn > sides * global.maxconn)
2232 global.maxsslconn = sides * global.maxconn;
2233
2234 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2235 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2236 }
2237#endif
2238 else if (!global.maxconn) {
2239 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2240 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2241 int64_t mem = global.rlimit_memmax * 1048576ULL;
2242 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002243 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002244
2245 if (global.ssl_used_frontend || global.ssl_used_backend)
2246 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2247
2248 mem -= global.maxzlibmem;
2249 mem = mem * MEM_USABLE_RATIO;
2250
2251 clearmem = mem;
2252 if (sides)
2253 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2254
Willy Tarreau304e17e2020-03-10 17:54:54 +01002255 /* Principle: we test once to set maxconn according to the free
2256 * memory. If it results in values the system rejects, we try a
2257 * second time by respecting rlim_fd_max. If it fails again, we
2258 * go back to the initial value and will let the final code
2259 * dealing with rlimit report the error. That's up to 3 attempts.
2260 */
2261 do {
2262 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2263 if (retried == 1)
2264 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2265 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002266#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002267 if (global.maxconn > SYSTEM_MAXCONN)
2268 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002269#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002270
Willy Tarreau304e17e2020-03-10 17:54:54 +01002271 if (clearmem <= 0 || !global.maxconn) {
2272 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2273 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2274 "is %d, but %d was found.\n",
2275 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002276 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002277 global.maxsslconn);
2278 exit(1);
2279 }
2280
2281 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2282 break;
2283 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002284
2285 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2286 if (sides && global.maxsslconn > sides * global.maxconn) {
2287 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2288 "to be limited to %d. Better reduce global.maxsslconn to get more "
2289 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2290 }
2291 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2292 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002293 }
2294
Willy Tarreaua409f302020-03-10 17:08:53 +01002295 global.maxsock = compute_ideal_maxsock(global.maxconn);
2296 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002297 if (!global.maxpipes)
2298 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002299
Olivier Houchard88698d92019-04-16 19:07:22 +02002300 /* update connection pool thresholds */
2301 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2302 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2303
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002304 proxy_adjust_all_maxconn();
2305
Willy Tarreau1db37712007-06-03 17:16:49 +02002306 if (global.tune.maxpollevents <= 0)
2307 global.tune.maxpollevents = MAX_POLL_EVENTS;
2308
Willy Tarreau060a7612021-03-10 11:06:26 +01002309 if (global.tune.runqueue_depth <= 0) {
2310 /* tests on various thread counts from 1 to 64 have shown an
2311 * optimal queue depth following roughly 1/sqrt(threads).
2312 */
2313 int s = my_flsl(global.nbthread);
2314 s += (global.nbthread / s); // roughly twice the sqrt.
2315 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2316 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002317
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002318 if (global.tune.recv_enough == 0)
2319 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2320
Willy Tarreau27a674e2009-08-17 07:23:33 +02002321 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2322 global.tune.maxrewrite = global.tune.bufsize / 2;
2323
Amaury Denoyelle11124302021-06-04 18:22:08 +02002324 usermsgs_clr(NULL);
2325
Willy Tarreaubaaee002006-06-26 02:48:02 +02002326 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2327 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002328 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002329 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2330 }
2331
William Lallemand095ba4c2017-06-01 17:38:50 +02002332 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002333 /* command line daemon mode inhibits foreground and debug modes mode */
2334 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002335 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002336 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002337
2338 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339
William Lallemand095ba4c2017-06-01 17:38:50 +02002340 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002341 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002342 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002343 }
2344
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002345 if (global.nbthread < 1)
2346 global.nbthread = 1;
2347
Christopher Faulet3ef26392017-08-29 16:46:57 +02002348 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002349 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002350 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002351 exit(1);
2352 }
2353
Christopher Faulet96d44832017-11-14 22:02:30 +01002354 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002355 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002356 exit(1);
2357 }
2358
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002359 /*
2360 * Note: we could register external pollers here.
2361 * Built-in pollers have been registered before main().
2362 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002363
Willy Tarreau43b78992009-01-25 15:42:27 +01002364 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002365 disable_poller("kqueue");
2366
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002367 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2368 disable_poller("evports");
2369
Willy Tarreau43b78992009-01-25 15:42:27 +01002370 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002371 disable_poller("epoll");
2372
Willy Tarreau43b78992009-01-25 15:42:27 +01002373 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002374 disable_poller("poll");
2375
Willy Tarreau43b78992009-01-25 15:42:27 +01002376 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002377 disable_poller("select");
2378
2379 /* Note: we could disable any poller by name here */
2380
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002381 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002382 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002383 fprintf(stderr, "\n");
2384 list_filters(stderr);
2385 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002386
Willy Tarreau4f60f162007-04-08 16:39:58 +02002387 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002388 ha_alert("No polling mechanism available.\n"
2389 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2390 " is too low on this platform to support maxconn and the number of listeners\n"
2391 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2392 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2393 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2394 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2395 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2396 " check build settings using 'haproxy -vv'.\n\n",
2397 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002398 exit(1);
2399 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002400 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2401 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002402 }
2403
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002404 if (!global.node)
2405 global.node = strdup(hostname);
2406
Willy Tarreau02b092f2020-10-07 18:36:54 +02002407 /* stop disabled proxies */
2408 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002409 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002410 stop_proxy(px);
2411 }
2412
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002413 if (!hlua_post_init())
2414 exit(1);
Thomas Holmes6abded42015-05-12 16:23:58 +01002415
Maxime de Roucy0f503922016-05-13 23:52:55 +02002416 free(err_msg);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417}
2418
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002419void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002420{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002421 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002422 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002423 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002424 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002425 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002426 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002427 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002428 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002429 struct per_thread_init_fct *tif, *tifb;
2430 struct per_thread_deinit_fct *tdf, *tdfb;
2431 struct per_thread_alloc_fct *taf, *tafb;
2432 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002433 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002434 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002435 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002436 int cur_fd;
2437
2438 /* At this point the listeners state is weird:
2439 * - most listeners are still bound and referenced in their protocol
2440 * - some might be zombies that are not in their proto anymore, but
2441 * still appear in their proxy's listeners with a valid FD.
2442 * - some might be stopped and still appear in their proxy as FD #-1
2443 * - among all of them, some might be inherited hence shared and we're
2444 * not allowed to pause them or whatever, we must just close them.
2445 * - finally some are not listeners (pipes, logs, stdout, etc) and
2446 * must be left intact.
2447 *
2448 * The safe way to proceed is to unbind (and close) whatever is not yet
2449 * unbound so that no more receiver/listener remains alive. Then close
2450 * remaining listener FDs, which correspond to zombie listeners (those
2451 * belonging to disabled proxies that were in another process).
2452 * objt_listener() would be cleaner here but not converted yet.
2453 */
2454 protocol_unbind_all();
2455
2456 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002457 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002458 continue;
2459
Willy Tarreaua74cb382020-10-15 21:29:49 +02002460 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002461 struct listener *l = fdtab[cur_fd].owner;
2462
2463 BUG_ON(l->state != LI_INIT);
2464 unbind_listener(l);
2465 }
2466 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002467
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002468 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002469 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002470 /* build a list of unique uri_auths */
2471 if (!ua)
2472 ua = p->uri_auth;
2473 else {
2474 /* check if p->uri_auth is unique */
2475 for (uap = ua; uap; uap=uap->next)
2476 if (uap == p->uri_auth)
2477 break;
2478
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002479 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002480 /* add it, if it is */
2481 p->uri_auth->next = ua;
2482 ua = p->uri_auth;
2483 }
William Lallemand0f99e342011-10-12 17:50:54 +02002484 }
2485
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002486 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002487 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002488 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002489 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002490
Christopher Faulet27c8d202021-10-13 09:50:53 +02002491 /* destroy all referenced defaults proxies */
2492 proxy_destroy_all_unref_defaults();
2493
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002494 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002495 struct stat_scope *scope, *scopep;
2496
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002497 uap = ua;
2498 ua = ua->next;
2499
Willy Tarreaua534fea2008-08-03 12:19:50 +02002500 free(uap->uri_prefix);
2501 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002502 free(uap->node);
2503 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002504
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002505 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002506 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002507
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002508 scope = uap->scope;
2509 while (scope) {
2510 scopep = scope;
2511 scope = scope->next;
2512
2513 free(scopep->px_id);
2514 free(scopep);
2515 }
2516
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002517 free(uap);
2518 }
2519
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002520 userlist_free(userlist);
2521
David Carlier834cb2e2015-09-25 12:02:25 +01002522 cfg_unregister_sections();
2523
Christopher Faulet0132d062017-07-26 15:33:35 +02002524 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002525
Willy Tarreau05554e62016-12-21 20:46:26 +01002526 list_for_each_entry(pdf, &post_deinit_list, list)
2527 pdf->fct();
2528
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002529 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002530 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002531 ha_free(&global.chroot);
2532 ha_free(&global.pidfile);
2533 ha_free(&global.node);
2534 ha_free(&global.desc);
2535 ha_free(&oldpids);
2536 ha_free(&old_argv);
2537 ha_free(&localpeer);
2538 ha_free(&global.server_state_base);
2539 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002540 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002541 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002542
William Lallemand0f99e342011-10-12 17:50:54 +02002543 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002544 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002545 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002546 free(log);
2547 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002548 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002549 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002550 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002551 free(wl);
2552 }
2553
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002554 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2555 if (bol->must_free)
2556 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002557 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002558 free(bol);
2559 }
2560
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002561 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002562 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002563 free(pxdf);
2564 }
2565
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002566 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002567 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002568 free(pdf);
2569 }
2570
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002571 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002572 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002573 free(srvdf);
2574 }
2575
Tim Duesterhusfc854942020-09-10 19:46:42 +02002576 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002577 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002578 free(pcf);
2579 }
2580
Tim Duesterhus34bef072020-07-04 11:49:50 +02002581 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002582 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002583 free(pscf);
2584 }
2585
Tim Duesterhus53508d62020-09-10 19:46:40 +02002586 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002587 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002588 free(ppcf);
2589 }
2590
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002591 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002592 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002593 free(tif);
2594 }
2595
2596 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002597 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002598 free(tdf);
2599 }
2600
2601 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002602 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002603 free(taf);
2604 }
2605
2606 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002607 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002608 free(tff);
2609 }
2610
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002611 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002612 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002613 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614} /* end deinit() */
2615
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002616__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002617{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002618 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002619 deinit();
2620 exit(status);
2621}
William Lallemand72160322018-11-06 17:37:16 +01002622
Willy Tarreau918ff602011-07-25 16:33:49 +02002623/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002624void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002625{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002626 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002627
Willy Tarreau55542642021-10-08 09:33:24 +02002628 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002629 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002630 wake_expired_tasks();
2631
William Lallemand1aab50b2018-06-07 09:46:01 +02002632 /* check if we caught some signals and process them in the
2633 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002634 if (signal_queue_len && tid == 0) {
2635 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002636 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002637 }
2638
2639 /* Process a few tasks */
2640 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002641
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002642 /* also stop if we failed to cleanly stop all tasks */
2643 if (killed > 1)
2644 break;
2645
Willy Tarreau10146c92015-04-13 20:44:19 +02002646 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002647 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002648 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002649 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002650 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002651 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2652 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002653 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002654 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002655 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002656 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002657 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002658 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002659
Willy Tarreau4f46a352020-03-23 09:27:28 +01002660 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002661 int i;
2662
2663 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002664 /* stop muxes before acknowledging stopping */
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002665 if (!(stopping_thread_mask & tid_bit)) {
2666 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2667 wake = 1;
2668 }
2669
Willy Tarreau1db42732021-04-06 11:44:07 +02002670 if (_HA_ATOMIC_OR_FETCH(&stopping_thread_mask, tid_bit) == tid_bit) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002671 /* notify all threads that stopping was just set */
2672 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002673 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002674 wake_thread(i);
2675 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002676 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002677
2678 /* stop when there's nothing left to do */
2679 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002680 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2681 /* wake all threads waiting on jobs==0 */
2682 for (i = 0; i < global.nbthread; i++)
2683 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2684 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002685 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002686 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002687 }
2688
Willy Tarreauc49ba522019-12-11 08:12:23 +01002689 /* If we have to sleep, measure how long */
2690 next = wake ? TICK_ETERNITY : next_timer_expiry();
2691
Willy Tarreau58b458d2008-06-29 22:40:23 +02002692 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002693 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002694
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002695 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002696 }
2697}
2698
Christopher Faulet1d17c102017-08-29 15:38:48 +02002699static void *run_thread_poll_loop(void *data)
2700{
Willy Tarreau082b6282019-05-22 14:42:12 +02002701 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002702 struct per_thread_init_fct *ptif;
2703 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002704 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002705 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002706 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2707 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002708
Willy Tarreau43ab05b2021-09-28 09:43:11 +02002709 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02002710 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02002711 clock_set_local_source();
Willy Tarreau91e6df02019-05-03 17:21:18 +02002712
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002713 /* Now, initialize one thread init at a time. This is better since
2714 * some init code is a bit tricky and may release global resources
2715 * after reallocating them locally. This will also ensure there is
2716 * no race on file descriptors allocation.
2717 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002718#ifdef USE_THREAD
2719 pthread_mutex_lock(&init_mutex);
2720#endif
2721 /* The first thread must set the number of threads left */
2722 if (!init_left)
2723 init_left = global.nbthread;
2724 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002725
Willy Tarreau55542642021-10-08 09:33:24 +02002726 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002727
Willy Tarreau082b6282019-05-22 14:42:12 +02002728 /* per-thread alloc calls performed here are not allowed to snoop on
2729 * other threads, so they are free to initialize at their own rhythm
2730 * as long as they act as if they were alone. None of them may rely
2731 * on resources initialized by the other ones.
2732 */
2733 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2734 if (!ptaf->fct()) {
2735 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002736#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002737 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002738#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02002739 exit(1);
2740 }
2741 }
2742
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002743 /* per-thread init calls performed here are not allowed to snoop on
2744 * other threads, so they are free to initialize at their own rhythm
2745 * as long as they act as if they were alone.
2746 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002747 list_for_each_entry(ptif, &per_thread_init_list, list) {
2748 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002749 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002750#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002751 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002752#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002753 exit(1);
2754 }
2755 }
2756
Willy Tarreau71092822019-06-10 09:51:04 +02002757 /* enabling protocols will result in fd_insert() calls to be performed,
2758 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002759 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002760 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002761 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002762 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002763
Willy Tarreau34a150c2019-06-11 09:16:41 +02002764#ifdef USE_THREAD
2765 pthread_cond_broadcast(&init_cond);
2766 pthread_mutex_unlock(&init_mutex);
2767
2768 /* now wait for other threads to finish starting */
2769 pthread_mutex_lock(&init_mutex);
2770 while (init_left)
2771 pthread_cond_wait(&init_cond, &init_mutex);
2772 pthread_mutex_unlock(&init_mutex);
2773#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002774
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002775#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2776 /* Let's refrain from using setuid executables. This way the impact of
2777 * an eventual vulnerability in a library remains limited. It may
2778 * impact external checks but who cares about them anyway ? In the
2779 * worst case it's possible to disable the option. Obviously we do this
2780 * in workers only. We can't hard-fail on this one as it really is
2781 * implementation dependent though we're interested in feedback, hence
2782 * the warning.
2783 */
2784 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2785 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002786 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 +01002787 ha_warning("Failed to disable setuid, please report to developers with detailed "
2788 "information about your operating system. You can silence this warning "
2789 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2790 }
2791 }
2792#endif
2793
Willy Tarreaud96f1122019-12-03 07:07:36 +01002794#if defined(RLIMIT_NPROC)
2795 /* all threads have started, it's now time to prevent any new thread
2796 * or process from starting. Obviously we do this in workers only. We
2797 * can't hard-fail on this one as it really is implementation dependent
2798 * though we're interested in feedback, hence the warning.
2799 */
2800 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2801 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2802 static int warn_fail;
2803
Willy Tarreau18515722021-04-06 11:57:41 +02002804 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002805 ha_warning("Failed to disable forks, please report to developers with detailed "
2806 "information about your operating system. You can silence this warning "
2807 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2808 }
2809 }
2810#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002811 run_poll_loop();
2812
2813 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2814 ptdf->fct();
2815
Willy Tarreau082b6282019-05-22 14:42:12 +02002816 list_for_each_entry(ptff, &per_thread_free_list, list)
2817 ptff->fct();
2818
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002819#ifdef USE_THREAD
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002820 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002821 if (tid > 0)
2822 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002823#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002824 return NULL;
2825}
Christopher Faulet1d17c102017-08-29 15:38:48 +02002826
William Dauchyf9af9d72019-11-17 15:47:16 +01002827/* set uid/gid depending on global settings */
2828static void set_identity(const char *program_name)
2829{
2830 if (global.gid) {
2831 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
2832 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
2833 " without 'uid'/'user' is generally useless.\n", program_name);
2834
2835 if (setgid(global.gid) == -1) {
2836 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
2837 protocol_unbind_all();
2838 exit(1);
2839 }
2840 }
2841
2842 if (global.uid && setuid(global.uid) == -1) {
2843 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
2844 protocol_unbind_all();
2845 exit(1);
2846 }
2847}
2848
Willy Tarreaubaaee002006-06-26 02:48:02 +02002849int main(int argc, char **argv)
2850{
2851 int err, retry;
2852 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02002853 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02002854 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
2855
2856 /* Catch forced CFLAGS that miss 2-complement integer overflow */
2857 if (intovf + 0x7FFFFFFF >= intovf) {
2858 fprintf(stderr,
2859 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
2860 "The source code was miscompiled by the compiler, which usually indicates that\n"
2861 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
2862 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
2863 "and INSTALL files to decide on the best way to pass your local build options.\n"
2864 "\nBuild options :"
2865#ifdef BUILD_TARGET
2866 "\n TARGET = " BUILD_TARGET
2867#endif
2868#ifdef BUILD_CPU
2869 "\n CPU = " BUILD_CPU
2870#endif
2871#ifdef BUILD_CC
2872 "\n CC = " BUILD_CC
2873#endif
2874#ifdef BUILD_CFLAGS
2875 "\n CFLAGS = " BUILD_CFLAGS
2876#endif
2877#ifdef BUILD_OPTIONS
2878 "\n OPTIONS = " BUILD_OPTIONS
2879#endif
2880#ifdef BUILD_DEBUG
2881 "\n DEBUG = " BUILD_DEBUG
2882#endif
2883 "\n\n");
2884 return 1;
2885 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002886
Olivier Houchard5fa300d2018-02-03 15:15:21 +01002887 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01002888
Willy Tarreaubf696402019-03-01 10:09:28 +01002889 /* take a copy of initial limits before we possibly change them */
2890 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02002891
2892 if (limit.rlim_max == RLIM_INFINITY)
2893 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01002894 rlim_fd_cur_at_boot = limit.rlim_cur;
2895 rlim_fd_max_at_boot = limit.rlim_max;
2896
Willy Tarreau5794fb02018-11-25 18:43:29 +01002897 /* process all initcalls in order of potential dependency */
2898 RUN_INITCALLS(STG_PREPARE);
2899 RUN_INITCALLS(STG_LOCK);
2900 RUN_INITCALLS(STG_ALLOC);
2901 RUN_INITCALLS(STG_POOL);
2902 RUN_INITCALLS(STG_REGISTER);
2903 RUN_INITCALLS(STG_INIT);
2904
Emeric Bruncf20bf12010-10-22 16:06:11 +02002905 init(argc, argv);
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002906 signal_register_fct(SIGQUIT, dump, SIGQUIT);
2907 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
2908 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02002909 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002910
Willy Tarreaue437c442010-03-17 18:02:46 +01002911 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
2912 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
2913 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002914 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002915 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916
Willy Tarreaudc23a922011-02-16 11:10:36 +01002917 /* ulimits */
2918 if (!global.rlimit_nofile)
2919 global.rlimit_nofile = global.maxsock;
2920
2921 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01002922 limit.rlim_cur = global.rlimit_nofile;
2923 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
2924
Willy Tarreaudc23a922011-02-16 11:10:36 +01002925 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02002926 getrlimit(RLIMIT_NOFILE, &limit);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002927 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2928 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
2929 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002930 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002931 }
2932 else {
2933 /* try to set it to the max possible at least */
2934 limit.rlim_cur = limit.rlim_max;
2935 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
2936 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02002937
William Dauchya5194602020-03-28 19:29:58 +01002938 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002939 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
2940 global.rlimit_nofile = limit.rlim_cur;
2941 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01002942 }
2943 }
2944
2945 if (global.rlimit_memmax) {
2946 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01002947 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01002948#ifdef RLIMIT_AS
2949 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002950 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2951 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2952 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002953 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002954 }
2955 else
William Dauchya5194602020-03-28 19:29:58 +01002956 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002957 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002958 }
2959#else
2960 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002961 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2962 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2963 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002964 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002965 }
2966 else
William Dauchya5194602020-03-28 19:29:58 +01002967 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002968 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002969 }
2970#endif
2971 }
2972
Olivier Houchardf73629d2017-04-05 22:33:04 +02002973 if (old_unixsocket) {
William Lallemand85b0bd92017-06-01 17:38:53 +02002974 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02002975 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002976 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02002977 if (!(global.mode & MODE_MWORKER))
2978 exit(1);
2979 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02002980 }
2981 }
William Lallemand85b0bd92017-06-01 17:38:53 +02002982
Willy Tarreaubaaee002006-06-26 02:48:02 +02002983 /* We will loop at most 100 times with 10 ms delay each time.
2984 * That's at most 1 second. We only send a signal to old pids
2985 * if we cannot grab at least one port.
2986 */
2987 retry = MAX_START_RETRIES;
2988 err = ERR_NONE;
2989 while (retry >= 0) {
2990 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02002991 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01002992 /* exit the loop on no error or fatal error */
2993 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02002995 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002996 break;
2997
2998 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
2999 * listening sockets. So on those platforms, it would be wiser to
3000 * simply send SIGUSR1, which will not be undoable.
3001 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003002 if (tell_old_pids(SIGTTOU) == 0) {
3003 /* no need to wait if we can't contact old pids */
3004 retry = 0;
3005 continue;
3006 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003007 /* give some time to old processes to stop listening */
3008 w.tv_sec = 0;
3009 w.tv_usec = 10*1000;
3010 select(0, NULL, NULL, NULL, &w);
3011 retry--;
3012 }
3013
Willy Tarreaue91bff22020-09-02 11:11:43 +02003014 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003015 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003016 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003017 if (retry != MAX_START_RETRIES && nb_oldpids) {
3018 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003019 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003020 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003021 exit(1);
3022 }
3023
William Lallemand944e6192018-11-21 15:48:31 +01003024 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003025 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003026 /* Note: we don't have to send anything to the old pids because we
3027 * never stopped them. */
3028 exit(1);
3029 }
3030
Willy Tarreaue91bff22020-09-02 11:11:43 +02003031 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003032 * the previous process gave us, we don't need them anymore
3033 */
3034 while (xfer_sock_list != NULL) {
3035 struct xfer_sock_list *tmpxfer = xfer_sock_list->next;
3036 close(xfer_sock_list->fd);
3037 free(xfer_sock_list->iface);
3038 free(xfer_sock_list->namespace);
3039 free(xfer_sock_list);
3040 xfer_sock_list = tmpxfer;
3041 }
Willy Tarreaudd815982007-10-16 12:25:14 +02003042
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003044 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3045 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046
Willy Tarreaubaaee002006-06-26 02:48:02 +02003047 /* MODE_QUIET can inhibit alerts and warnings below this line */
3048
PiBa-NL149a81a2017-12-25 21:03:31 +01003049 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3050 /* either stdin/out/err are already closed or should stay as they are. */
3051 if ((global.mode & MODE_DAEMON)) {
3052 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3053 global.mode &= ~MODE_VERBOSE;
3054 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3055 }
3056 } else {
3057 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3058 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003059 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003060 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 }
3062
3063 /* open log & pid files before the chroot */
William Lallemand80293002017-11-06 11:00:03 +01003064 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003065 unlink(global.pidfile);
3066 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3067 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003068 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003069 if (nb_oldpids)
3070 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003071 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003072 exit(1);
3073 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 }
3075
Willy Tarreaub38651a2007-03-24 17:24:39 +01003076 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003077 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3078 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003079 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003080 exit(1);
3081 }
3082
Jackie Tapia749f74c2020-07-22 18:59:40 -05003083 /* If the user is not root, we'll still let them try the configuration
3084 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003085 */
3086 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003087 ha_warning("[%s.main()] Some options which require full privileges"
3088 " might not work well.\n"
3089 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003090
William Lallemand095ba4c2017-06-01 17:38:50 +02003091 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3092
3093 /* chroot if needed */
3094 if (global.chroot != NULL) {
3095 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003096 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003097 if (nb_oldpids)
3098 tell_old_pids(SIGTTIN);
3099 protocol_unbind_all();
3100 exit(1);
3101 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003102 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003103 }
3104
William Lallemand944e6192018-11-21 15:48:31 +01003105 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003106 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107
William Lallemand27edc4b2019-05-07 17:49:33 +02003108 /* send a SIGTERM to workers who have a too high reloads number */
3109 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3110 mworker_kill_max_reloads(SIGTERM);
3111
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 /* Note that any error at this stage will be fatal because we will not
3113 * be able to restart the old pids.
3114 */
3115
William Dauchyf9af9d72019-11-17 15:47:16 +01003116 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3117 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003118
Willy Tarreaubaaee002006-06-26 02:48:02 +02003119 /* check ulimits */
3120 limit.rlim_cur = limit.rlim_max = 0;
3121 getrlimit(RLIMIT_NOFILE, &limit);
3122 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003123 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3124 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3125 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3126 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3127 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003128 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003129 }
3130 else
3131 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003132 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003133 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3134 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 }
3136
William Lallemand944e6192018-11-21 15:48:31 +01003137 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003139 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003140 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003141
William Lallemand095ba4c2017-06-01 17:38:50 +02003142 /*
3143 * if daemon + mworker: must fork here to let a master
3144 * process live in background before forking children
3145 */
William Lallemand73b85e72017-06-01 17:38:51 +02003146
3147 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3148 && (global.mode & MODE_MWORKER)
3149 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003150 ret = fork();
3151 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003152 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003153 protocol_unbind_all();
3154 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003155 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003156 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003157 } else /* change the process group ID in the child (master process) */
3158 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003159 }
William Lallemande20b6a62017-06-01 17:38:55 +02003160
William Lallemande20b6a62017-06-01 17:38:55 +02003161
William Lallemanddeed7802017-11-06 11:00:04 +01003162 /* if in master-worker mode, write the PID of the father */
3163 if (global.mode & MODE_MWORKER) {
3164 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003165 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003166 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003167 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003168 }
3169
Willy Tarreaubaaee002006-06-26 02:48:02 +02003170 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003171 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003172 if (global.mode & MODE_MWORKER)
3173 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003174
3175 ret = fork();
3176 if (ret < 0) {
3177 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3178 protocol_unbind_all();
3179 exit(1); /* there has been an error */
3180 }
3181 else if (ret == 0) { /* child breaks here */
Willy Tarreau3c032f22021-07-21 10:17:02 +02003182 /* This one must not be exported, it's internal! */
3183 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003184 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003185 }
3186 else { /* parent here */
3187 in_parent = 1;
3188
William Lallemand944e6192018-11-21 15:48:31 +01003189 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3190 char pidstr[100];
3191 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003192 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003193 }
3194 if (global.mode & MODE_MWORKER) {
3195 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003196
William Lallemand5d71a6b2021-11-09 15:25:31 +01003197 ha_notice("New worker (%d) forked\n", ret);
William Lallemand944e6192018-11-21 15:48:31 +01003198 /* find the right mworker_proc */
3199 list_for_each_entry(child, &proc_list, list) {
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003200 if (child->reloads == 0 && child->options & PROC_O_TYPE_WORKER) {
William Lallemand944e6192018-11-21 15:48:31 +01003201 child->timestamp = now.tv_sec;
3202 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003203 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003204 break;
3205 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003206 }
3207 }
William Lallemand944e6192018-11-21 15:48:31 +01003208 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003209
William Lallemand944e6192018-11-21 15:48:31 +01003210 } else {
3211 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003212 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003214
3215#ifdef USE_CPU_AFFINITY
Willy Tarreau44ea6312021-06-15 08:57:56 +02003216 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 +02003217
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003218#ifdef __FreeBSD__
Willy Tarreau44ea6312021-06-15 08:57:56 +02003219 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003220 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
David Carlier2d0493a2020-12-02 21:14:51 +00003221#elif defined(__linux__) || defined(__DragonFly__)
Willy Tarreau44ea6312021-06-15 08:57:56 +02003222 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003223 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003224#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003225 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003226#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003228 if (pidfd >= 0) {
3229 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3230 close(pidfd);
3231 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003232
3233 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003234 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003235
Willy Tarreaud67ff342021-06-15 07:58:09 +02003236 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003237 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
William Lallemandfab0fdc2021-11-09 18:01:22 +01003238 master = 1;
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003239
3240 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3241 (global.mode & MODE_DAEMON)) {
3242 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003243 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3244 stdio_quiet(-1);
3245
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003246 global.mode &= ~MODE_VERBOSE;
3247 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003248 }
3249
William Lallemandfab0fdc2021-11-09 18:01:22 +01003250 if (global.mode & MODE_MWORKER_WAIT) {
3251 /* only the wait mode handles the master CLI */
3252 mworker_loop();
3253 } else {
3254
3255 /* if not in wait mode, reload in wait mode to free the memory */
William Lallemand836bda22021-11-09 18:16:47 +01003256 ha_notice("Loading success.\n");
William Lallemand68836742021-11-10 10:49:06 +01003257 proc_self->failedreloads = 0; /* reset the number of failure */
William Lallemandfab0fdc2021-11-09 18:01:22 +01003258 mworker_reexec_waitmode();
3259 }
William Lallemand1499b9b2017-06-07 15:04:47 +02003260 /* should never get there */
3261 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003262 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003263#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003264 ssl_free_dh();
3265#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003266 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003267 }
3268
William Lallemandcb11fd22017-06-01 17:38:52 +02003269 /* child must never use the atexit function */
3270 atexit_flag = 0;
3271
William Lallemandbc193052018-09-11 10:06:26 +02003272 /* close useless master sockets */
3273 if (global.mode & MODE_MWORKER) {
3274 struct mworker_proc *child, *it;
3275 master = 0;
3276
William Lallemand309dc9a2018-10-26 14:47:45 +02003277 mworker_cli_proxy_stop();
3278
William Lallemandbc193052018-09-11 10:06:26 +02003279 /* free proc struct of other processes */
3280 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003281 /* close the FD of the master side for all
3282 * workers, we don't need to close the worker
3283 * side of other workers since it's done with
3284 * the bind_proc */
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003285 if (child->ipc_fd[0] >= 0)
3286 close(child->ipc_fd[0]);
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003287 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandce83b4a2018-10-26 14:47:30 +02003288 child->reloads == 0) {
3289 /* keep this struct if this is our pid */
3290 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003291 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003292 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003293 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003294 mworker_free_child(child);
3295 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003296 }
3297 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003298
William Lallemande1340412017-12-28 16:09:36 +01003299 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3300 devnullfd = open("/dev/null", O_RDWR, 0);
3301 if (devnullfd < 0) {
3302 ha_alert("Cannot open /dev/null\n");
3303 exit(EXIT_FAILURE);
3304 }
3305 }
3306
William Lallemand095ba4c2017-06-01 17:38:50 +02003307 /* Must chroot and setgid/setuid in the children */
3308 /* chroot if needed */
3309 if (global.chroot != NULL) {
3310 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003311 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003312 if (nb_oldpids)
3313 tell_old_pids(SIGTTIN);
3314 protocol_unbind_all();
3315 exit(1);
3316 }
3317 }
3318
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003319 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003320 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003321
William Lallemand7f80eb22017-05-26 18:19:55 +02003322 /* pass through every cli socket, and check if it's bound to
3323 * the current process and if it exposes listeners sockets.
3324 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3325 * */
3326
Willy Tarreau4975d142021-03-13 11:00:33 +01003327 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003328 struct bind_conf *bind_conf;
3329
Willy Tarreau4975d142021-03-13 11:00:33 +01003330 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003331 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003332 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3333 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003334 }
3335 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003336 }
3337
William Lallemand2e8fad92018-11-13 16:18:23 +01003338 /*
3339 * This is only done in daemon mode because we might want the
3340 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3341 * we should now close the 3 first FDs to ensure that we can
3342 * detach from the TTY. We MUST NOT do it in other cases since
3343 * it would have already be done, and 0-2 would have been
3344 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003345 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003346 if ((global.mode & MODE_DAEMON) &&
3347 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003348 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003349 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003350 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003351 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3352 }
3353 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003354 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3355 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003356 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003357 }
3358
William Dauchye039f262019-11-17 15:47:15 +01003359 /* try our best to re-enable core dumps depending on system capabilities.
3360 * What is addressed here :
3361 * - remove file size limits
3362 * - remove core size limits
3363 * - mark the process dumpable again if it lost it due to user/group
3364 */
3365 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3366 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3367
3368#if defined(RLIMIT_FSIZE)
3369 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3370 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3371 ha_alert("[%s.main()] Failed to set the raise the maximum "
3372 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003373 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003374 }
3375 else
3376 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003377 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003378 }
3379#endif
3380
3381#if defined(RLIMIT_CORE)
3382 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3383 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3384 ha_alert("[%s.main()] Failed to set the raise the core "
3385 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003386 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003387 }
3388 else
3389 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003390 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003391 }
3392#endif
3393
3394#if defined(USE_PRCTL)
3395 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3396 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3397 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003398#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003399 {
3400 int traceable = PROC_TRACE_CTL_ENABLE;
3401 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3402 ha_warning("[%s.main()] Failed to set the traceable flag, "
3403 "no core will be dumped.\n", argv[0]);
3404 }
William Dauchye039f262019-11-17 15:47:15 +01003405#endif
3406 }
3407
Christopher Faulete3a5e352017-10-24 13:53:54 +02003408 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003409 reset_usermsgs_ctx();
3410
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003411 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003412 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003413
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003414 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003415 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003416
3417 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003418 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003419
3420 /* wait for all threads to terminate */
3421 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003422
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003423 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003424}
3425
Willy Tarreaubaaee002006-06-26 02:48:02 +02003426/*
3427 * Local variables:
3428 * c-indent-level: 8
3429 * c-basic-offset: 8
3430 * End:
3431 */