blob: 0da19ccdf6e2508c7883098df7cbce934e9f04cb [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 Tarreau2454d6e2022-02-01 18:06:59 +01003 * Copyright 2000-2022 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 Tarreau392524d2022-02-17 18:10:36 +0100221int arg_mode = 0; /* MODE_DEBUG etc as passed on command line ... */
222char *change_dir = NULL; /* set when -C is passed */
223char *check_condition = NULL; /* check condition passed to -cc */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500225/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 * or kill. We will send them a signal every 10 ms until we can bind to all
227 * our ports. With 200 retries, that's about 2 seconds.
228 */
229#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230static int *oldpids = NULL;
231static int oldpids_sig; /* use USR1 or TERM */
232
Olivier Houchardf73629d2017-04-05 22:33:04 +0200233/* Path to the unix socket we use to retrieve listener sockets from the old process */
234static const char *old_unixsocket;
235
William Lallemandcb11fd22017-06-01 17:38:52 +0200236int atexit_flag = 0;
237
Willy Tarreaubb545b42010-08-25 12:58:59 +0200238int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200239const int zero = 0;
240const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200241const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100243char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200244char *localpeer = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
William Lallemand00417412020-06-05 14:08:41 +0200246static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200247
William Lallemandbc193052018-09-11 10:06:26 +0200248struct list proc_list = LIST_HEAD_INIT(proc_list);
249
250int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100251unsigned int rlim_fd_cur_at_boot = 0;
252unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200253
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100254/* per-boot randomness */
255unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
256
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200257/* takes the thread config in argument or NULL for any thread */
William Lallemandb3f2be32018-09-11 10:06:18 +0200258static void *run_thread_poll_loop(void *data);
259
Willy Tarreauff055502014-04-28 22:27:06 +0200260/* bitfield of a few warnings to emit just once (WARN_*) */
261unsigned int warned = 0;
262
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200263/* set if experimental features have been used for the current process */
Willy Tarreauedd42682022-02-25 10:10:00 +0100264unsigned int tainted = 0;
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200265
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200266unsigned int experimental_directives_allowed = 0;
267
268int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
269 char **errmsg)
270{
271 if (kw->flags & KWF_EXPERIMENTAL) {
272 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200273 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 +0200274 file, linenum, kw->kw);
275 return 1;
276 }
277 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
278 }
279
280 return 0;
281}
282
William Lallemande7361152018-10-26 14:47:36 +0200283/* master CLI configuration (-S flag) */
284struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100285
286/* These are strings to be reported in the output of "haproxy -vv". They may
287 * either be constants (in which case must_free must be zero) or dynamically
288 * allocated strings to pass to free() on exit, and in this case must_free
289 * must be non-zero.
290 */
291struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
292struct build_opts_str {
293 struct list list;
294 const char *str;
295 int must_free;
296};
297
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298/*********************************************************************/
299/* general purpose functions ***************************************/
300/*********************************************************************/
301
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100302/* used to register some build option strings at boot. Set must_free to
303 * non-zero if the string must be freed upon exit.
304 */
305void hap_register_build_opts(const char *str, int must_free)
306{
307 struct build_opts_str *b;
308
309 b = calloc(1, sizeof(*b));
310 if (!b) {
311 fprintf(stderr, "out of memory\n");
312 exit(1);
313 }
314 b->str = str;
315 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200316 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100317}
318
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200319#define VERSION_MAX_ELTS 7
320
321/* This function splits an haproxy version string into an array of integers.
322 * The syntax of the supported version string is the following:
323 *
324 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
325 *
326 * This validates for example:
327 * 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
328 * 2.4-dev18-f6818d-20
329 *
330 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
331 * one fixed place in the array. The tags take a numeric value called <e> which
332 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
333 * considered as zero (henxe 1.5 and 1.5.0 are the same).
334 *
335 * The resulting values are:
336 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
337 * 1.2.1 1, 2, 1, 0, 3, 0, 0
338 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
339 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
340 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
341 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
342 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
343 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
344 *
345 * The function returns non-zero if the conversion succeeded, or zero if it
346 * failed.
347 */
348int split_version(const char *version, unsigned int *value)
349{
350 const char *p, *s;
351 char *error;
352 int nelts;
353
354 /* Initialize array with zeroes */
355 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
356 value[nelts] = 0;
357 value[4] = 3;
358
359 p = version;
360
361 /* If the version number is empty, return false */
362 if (*p == '\0')
363 return 0;
364
365 /* Convert first number <a> */
366 value[0] = strtol(p, &error, 10);
367 p = error + 1;
368 if (*error == '\0')
369 return 1;
370 if (*error == '-')
371 goto split_version_tag;
372 if (*error != '.')
373 return 0;
374
375 /* Convert first number <b> */
376 value[1] = strtol(p, &error, 10);
377 p = error + 1;
378 if (*error == '\0')
379 return 1;
380 if (*error == '-')
381 goto split_version_tag;
382 if (*error != '.')
383 return 0;
384
385 /* Convert first number <c> */
386 value[2] = strtol(p, &error, 10);
387 p = error + 1;
388 if (*error == '\0')
389 return 1;
390 if (*error == '-')
391 goto split_version_tag;
392 if (*error != '.')
393 return 0;
394
395 /* Convert first number <d> */
396 value[3] = strtol(p, &error, 10);
397 p = error + 1;
398 if (*error == '\0')
399 return 1;
400 if (*error != '-')
401 return 0;
402
403 split_version_tag:
404 /* Check for commit number */
405 if (*p >= '0' && *p <= '9')
406 goto split_version_commit;
407
408 /* Read tag */
409 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
410 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
411 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
412 else
413 goto split_version_commit;
414
415 /* Convert tag number */
416 value[5] = strtol(p, &error, 10);
417 p = error + 1;
418 if (*error == '\0')
419 return 1;
420 if (*error != '-')
421 return 0;
422
423 split_version_commit:
424 /* Search the last "-" */
425 s = strrchr(p, '-');
426 if (s) {
427 s++;
428 if (*s == '\0')
429 return 0;
430 value[6] = strtol(s, &error, 10);
431 if (*error != '\0')
432 value[6] = 0;
433 return 1;
434 }
435
436 /* convert the version */
437 value[6] = strtol(p, &error, 10);
438 if (*error != '\0')
439 value[6] = 0;
440
441 return 1;
442}
443
444/* This function compares the current haproxy version with an arbitrary version
445 * string. It returns:
446 * -1 : the version in argument is older than the current haproxy version
447 * 0 : the version in argument is the same as the current haproxy version
448 * 1 : the version in argument is newer than the current haproxy version
449 *
450 * Or some errors:
451 * -2 : the current haproxy version is not parsable
452 * -3 : the version in argument is not parsable
453 */
454int compare_current_version(const char *version)
455{
456 unsigned int loc[VERSION_MAX_ELTS];
457 unsigned int mod[VERSION_MAX_ELTS];
458 int i;
459
460 /* split versions */
461 if (!split_version(haproxy_version, loc))
462 return -2;
463 if (!split_version(version, mod))
464 return -3;
465
466 /* compare versions */
467 for (i = 0; i < VERSION_MAX_ELTS; i++) {
468 if (mod[i] < loc[i])
469 return -1;
470 else if (mod[i] > loc[i])
471 return 1;
472 }
473 return 0;
474}
475
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100476static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200477{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200478 struct utsname utsname;
479
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200480 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100481 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100482
483 if (strlen(PRODUCT_URL_BUGS) > 0) {
484 char base_version[20];
485 int dots = 0;
486 char *del;
487
488 /* only retrieve the base version without distro-specific extensions */
489 for (del = haproxy_version; *del; del++) {
490 if (*del == '.')
491 dots++;
492 else if (*del < '0' || *del > '9')
493 break;
494 }
495
496 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
497 if (dots < 2)
498 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
499 else
500 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
501 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200502
503 if (uname(&utsname) == 0) {
504 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200506}
507
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100508static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100509{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100510 struct build_opts_str *item;
511
Willy Tarreau7b066db2007-12-02 11:28:59 +0100512 printf("Build options :"
513#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100514 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100515#endif
516#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100517 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100518#endif
519#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100520 "\n CC = " BUILD_CC
521#endif
522#ifdef BUILD_CFLAGS
523 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100524#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100525#ifdef BUILD_OPTIONS
526 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100527#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100528#ifdef BUILD_DEBUG
529 "\n DEBUG = " BUILD_DEBUG
530#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100531#ifdef BUILD_FEATURES
532 "\n\nFeature list : " BUILD_FEATURES
533#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200534 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100535 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200536 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100537 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200538
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100539 list_for_each_entry(item, &build_opts_list, list) {
540 puts(item->str);
541 }
542
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100543 putchar('\n');
544
Willy Tarreaube5b6852009-10-03 18:57:08 +0200545 list_pollers(stdout);
546 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200547 list_mux_proto(stdout);
548 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100549 list_services(stdout);
550 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100551 list_filters(stdout);
552 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100553}
554
Willy Tarreaubaaee002006-06-26 02:48:02 +0200555/*
556 * This function prints the command line usage and exits
557 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100558static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200559{
560 display_version();
561 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200562 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200563 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200564 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100565 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreauf4b79c42022-02-23 15:20:53 +0100567 " -dM[<byte>,help,...] debug memory (default: poison with <byte>/0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200568 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200569 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200570 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100571#if defined(USE_SYSTEMD)
572 " -Ws master-worker mode with systemd notify support.\n"
573#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200574 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200575 " -c check mode : only check config files and exit\n"
Maximilian Maderfc0cceb2021-06-06 00:50:22 +0200576 " -cc check condition : evaluate a condition and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100577 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200578 " -m limits the usable amount of memory (in MB)\n"
579 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200580 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581 " -p writes pids of all children to this file\n"
Willy Tarreaue5733232019-05-22 19:24:06 +0200582#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200583 " -de disables epoll() usage even when available\n"
584#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200585#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200586 " -dk disables kqueue() usage even when available\n"
587#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200588#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000589 " -dv disables event ports usage even when available\n"
590#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200591#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200592 " -dp disables poll() usage even when available\n"
593#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200594#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100595 " -dS disables splice usage (broken on old kernels)\n"
596#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200597#if defined(USE_GETADDRINFO)
598 " -dG disables getaddrinfo() usage\n"
599#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000600#if defined(SO_REUSEPORT)
601 " -dR disables SO_REUSEPORT usage\n"
602#endif
Willy Tarreau654726d2021-12-28 15:43:11 +0100603#if defined(HA_HAVE_DUMP_LIBS)
604 " -dL dumps loaded object files after config checks\n"
605#endif
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100606 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100607 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200608 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200609 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200610 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200611 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200612 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100614 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615 exit(1);
616}
617
618
619
620/*********************************************************************/
621/* more specific functions ***************************************/
622/*********************************************************************/
623
William Lallemand73b85e72017-06-01 17:38:51 +0200624/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
625 * pids the signal was correctly delivered to.
626 */
William Lallemande25473c2019-04-01 11:29:56 +0200627int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200628{
629 int p;
630 int ret = 0;
631 for (p = 0; p < nb_oldpids; p++)
632 if (kill(oldpids[p], sig) == 0)
633 ret++;
634 return ret;
635}
636
William Lallemand75ea0a02017-11-15 19:02:58 +0100637/*
William Lallemand73b85e72017-06-01 17:38:51 +0200638 * remove a pid forom the olpid array and decrease nb_oldpids
639 * return 1 pid was found otherwise return 0
640 */
641
642int delete_oldpid(int pid)
643{
644 int i;
645
646 for (i = 0; i < nb_oldpids; i++) {
647 if (oldpids[i] == pid) {
648 oldpids[i] = oldpids[nb_oldpids - 1];
649 oldpids[nb_oldpids - 1] = 0;
650 nb_oldpids--;
651 return 1;
652 }
653 }
654 return 0;
655}
656
William Lallemand85b0bd92017-06-01 17:38:53 +0200657
William Lallemand73b85e72017-06-01 17:38:51 +0200658/*
659 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800660 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200661 */
William Lallemandfab0fdc2021-11-09 18:01:22 +0100662static void mworker_reexec()
William Lallemand73b85e72017-06-01 17:38:51 +0200663{
William Lallemand00417412020-06-05 14:08:41 +0200664 char **next_argv = NULL;
665 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200666 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200667 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200668 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100669 struct rlimit limit;
William Lallemand2be557f2021-11-24 18:45:37 +0100670 struct mworker_proc *current_child = NULL;
William Lallemand73b85e72017-06-01 17:38:51 +0200671
672 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100673#if defined(USE_SYSTEMD)
674 if (global.tune.options & GTUNE_USE_SYSTEMD)
675 sd_notify(0, "RELOADING=1");
676#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200677 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
678
William Lallemand55a921c2022-01-28 21:17:30 +0100679 mworker_cleanup_proc();
William Lallemandbc193052018-09-11 10:06:26 +0200680 mworker_proc_list_to_env(); /* put the children description in the env */
681
William Lallemandc4810b82021-11-18 10:51:30 +0100682 /* ensure that we close correctly every listeners before reexecuting */
683 mworker_cleanlisteners();
684
William Lallemand7c756a82018-11-26 11:53:40 +0100685 /* during the reload we must ensure that every FDs that can't be
686 * reuse (ie those that are not referenced in the proc_list)
687 * are closed or they will leak. */
688
689 /* close the listeners FD */
690 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200691
William Lallemand67e371e2021-11-25 10:03:44 +0100692 if (fdtab)
693 deinit_pollers();
William Lallemandefd95472021-11-26 14:43:57 +0100694
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500695#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200696 /* close random device FDs */
697 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100698#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100699
Willy Tarreau8dca1952019-03-01 10:21:55 +0100700 /* restore the initial FD limits */
701 limit.rlim_cur = rlim_fd_cur_at_boot;
702 limit.rlim_max = rlim_fd_max_at_boot;
703 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
704 getrlimit(RLIMIT_NOFILE, &limit);
705 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
706 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
707 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
708 }
709
William Lallemand73b85e72017-06-01 17:38:51 +0200710 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200711 while (old_argv[old_argc])
712 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200713
William Lallemand85b0bd92017-06-01 17:38:53 +0200714 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200715 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200716 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200717 if (next_argv == NULL)
718 goto alloc_error;
719
William Lallemand00417412020-06-05 14:08:41 +0200720 /* copy the program name */
721 next_argv[next_argc++] = old_argv[0];
722
723 /* insert the new options just after argv[0] in case we have a -- */
724
William Lallemandbefab9e2021-11-25 00:49:19 +0100725 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
726 /* add -sf <PID>* to argv */
727 if (mworker_child_nb() > 0) {
728 struct mworker_proc *child;
William Lallemand3f128872019-04-01 11:29:59 +0200729
William Lallemandbefab9e2021-11-25 00:49:19 +0100730 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200731
William Lallemandbefab9e2021-11-25 00:49:19 +0100732 list_for_each_entry(child, &proc_list, list) {
733 if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
734 current_child = child;
William Lallemand2be557f2021-11-24 18:45:37 +0100735
William Lallemandbefab9e2021-11-25 00:49:19 +0100736 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
737 continue;
738 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
739 goto alloc_error;
740 msg = NULL;
741 }
William Lallemand73b85e72017-06-01 17:38:51 +0200742 }
William Lallemand2be557f2021-11-24 18:45:37 +0100743
744 if (current_child) {
745 /* add the -x option with the socketpair of the current worker */
746 next_argv[next_argc++] = "-x";
747 if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
748 goto alloc_error;
749 msg = NULL;
750 }
William Lallemand85b0bd92017-06-01 17:38:53 +0200751 }
752
William Lallemand00417412020-06-05 14:08:41 +0200753 /* copy the previous options */
754 for (i = 1; i < old_argc; i++)
755 next_argv[next_argc++] = old_argv[i];
756
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200757 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100758 execvp(next_argv[0], next_argv);
Christopher Faulet767a84b2017-11-24 16:50:31 +0100759 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100760 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100761 return;
762
William Lallemand73b85e72017-06-01 17:38:51 +0200763alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100764 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800765 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200766 return;
767}
768
William Lallemandfab0fdc2021-11-09 18:01:22 +0100769/* reexec haproxy in waitmode */
770static void mworker_reexec_waitmode()
771{
772 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
773 mworker_reexec();
774}
775
776/* reload haproxy and emit a warning */
777void mworker_reload()
778{
William Lallemandad221f42021-11-09 18:43:59 +0100779 struct mworker_proc *child;
William Lallemandefd95472021-11-26 14:43:57 +0100780 struct per_thread_deinit_fct *ptdf;
William Lallemandad221f42021-11-09 18:43:59 +0100781
William Lallemand836bda22021-11-09 18:16:47 +0100782 ha_notice("Reloading HAProxy\n");
William Lallemandad221f42021-11-09 18:43:59 +0100783
William Lallemandefd95472021-11-26 14:43:57 +0100784 /* close the poller FD and the thread waker pipe FD */
785 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
786 ptdf->fct();
787
William Lallemandad221f42021-11-09 18:43:59 +0100788 /* increment the number of reloads */
789 list_for_each_entry(child, &proc_list, list) {
790 child->reloads++;
791 }
792
William Lallemandfab0fdc2021-11-09 18:01:22 +0100793 mworker_reexec();
794}
795
William Lallemandb3f2be32018-09-11 10:06:18 +0200796static void mworker_loop()
797{
798
799#if defined(USE_SYSTEMD)
800 if (global.tune.options & GTUNE_USE_SYSTEMD)
801 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
802#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200803 /* Busy polling makes no sense in the master :-) */
804 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200805
William Lallemandbc193052018-09-11 10:06:26 +0200806
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100807 signal_unregister(SIGTTIN);
808 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100809 signal_unregister(SIGUSR1);
810 signal_unregister(SIGHUP);
811 signal_unregister(SIGQUIT);
812
William Lallemandb3f2be32018-09-11 10:06:18 +0200813 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
814 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100815 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
816 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200817 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
818 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
819 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
820 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
821
822 mworker_unblock_signals();
William Lallemand27f3fa52018-12-06 14:05:20 +0100823 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200824
William Lallemandbc193052018-09-11 10:06:26 +0200825 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
826 some SIGCHLD were lost */
827
William Lallemandb3f2be32018-09-11 10:06:18 +0200828 global.nbthread = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200829
William Lallemand2672eb92018-12-14 15:52:39 +0100830#ifdef USE_THREAD
831 tid_bit = 1;
832 all_threads_mask = 1;
833#endif
834
William Lallemandb3f2be32018-09-11 10:06:18 +0200835 jobs++; /* this is the "master" job, we want to take care of the
836 signals even if there is no listener so the poll loop don't
837 leave */
838
839 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200840 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200841}
William Lallemandcb11fd22017-06-01 17:38:52 +0200842
843/*
844 * Reexec the process in failure mode, instead of exiting
845 */
846void reexec_on_failure()
847{
William Lallemand68836742021-11-10 10:49:06 +0100848 struct mworker_proc *child;
849
William Lallemandcb11fd22017-06-01 17:38:52 +0200850 if (!atexit_flag)
851 return;
William Lallemand68836742021-11-10 10:49:06 +0100852
853 /* get the info of the children in the env */
854 if (mworker_env_to_proc_list() < 0) {
855 exit(EXIT_FAILURE);
856 }
857
858 /* increment the number of failed reloads */
859 list_for_each_entry(child, &proc_list, list) {
860 child->failedreloads++;
861 }
862
Willy Tarreaue08acae2022-01-28 18:40:06 +0100863 /* do not keep unused FDs retrieved from the previous process */
864 sock_drop_unused_old_sockets();
865
William Lallemandfab0fdc2021-11-09 18:01:22 +0100866 usermsgs_clr(NULL);
William Lallemand836bda22021-11-09 18:16:47 +0100867 ha_warning("Loading failure!\n");
William Lallemandfab0fdc2021-11-09 18:01:22 +0100868 mworker_reexec_waitmode();
William Lallemandcb11fd22017-06-01 17:38:52 +0200869}
William Lallemand73b85e72017-06-01 17:38:51 +0200870
871
872/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200873 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
874 * a signal zero to all subscribers. This means that it's as easy as
875 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200876 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100877static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200878{
879 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200880 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100881 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882}
883
884/*
885 * upon SIGTTOU, we pause everything
886 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100887static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888{
Willy Tarreau775e0012020-09-24 16:36:26 +0200889 if (protocol_pause_all() & ERR_FATAL) {
890 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200891 ha_warning("%s", msg);
892 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200893 soft_stop();
894 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100895 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200896}
897
898/*
899 * upon SIGTTIN, let's have a soft stop.
900 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100901static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902{
Willy Tarreau775e0012020-09-24 16:36:26 +0200903 if (protocol_resume_all() & ERR_FATAL) {
904 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 +0200905 ha_warning("%s", msg);
906 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200907 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908}
909
910/*
911 * this function dumps every server's state when the process receives SIGHUP.
912 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100913static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100915 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916
Christopher Faulet767a84b2017-11-24 16:50:31 +0100917 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 while (p) {
919 struct server *s = p->srv;
920
921 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
922 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100923 chunk_printf(&trash,
924 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
925 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200926 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200927 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200928 ha_warning("%s\n", trash.area);
929 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 s = s->next;
931 }
932
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200933 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
934 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100935 chunk_printf(&trash,
936 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
937 p->id,
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 Tarreau5fcc8f12007-09-17 11:27:09 +0200939 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100940 chunk_printf(&trash,
941 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
942 p->id,
943 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200944 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 +0200945 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100946 chunk_printf(&trash,
947 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
948 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
949 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200950 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 +0200951 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200952 ha_warning("%s\n", trash.area);
953 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954
955 p = p->next;
956 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957}
958
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100959static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200961 /* dump memory usage then free everything possible */
962 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100963 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964}
965
William Lallemande1340412017-12-28 16:09:36 +0100966/*
967 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
968 * If <fd> < 0, it opens /dev/null and use it to dup
969 *
970 * In the case of chrooting, you have to open /dev/null before the chroot, and
971 * pass the <fd> to this function
972 */
973static void stdio_quiet(int fd)
974{
975 if (fd < 0)
976 fd = open("/dev/null", O_RDWR, 0);
977
978 if (fd > -1) {
979 fclose(stdin);
980 fclose(stdout);
981 fclose(stderr);
982
983 dup2(fd, 0);
984 dup2(fd, 1);
985 dup2(fd, 2);
986 if (fd > 2)
987 close(fd);
988 return;
989 }
990
991 ha_alert("Cannot open /dev/null\n");
992 exit(EXIT_FAILURE);
993}
994
995
Joseph Herlant03420902018-11-15 10:41:50 -0800996/* This function checks if cfg_cfgfiles contains directories.
997 * If it finds one, it adds all the files (and only files) it contains
998 * in cfg_cfgfiles in place of the directory (and removes the directory).
999 * It adds the files in lexical order.
1000 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001001 * It doesn't add files with name starting with '.'
1002 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001003static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001004{
1005 struct wordlist *wl, *wlb;
1006 char *err = NULL;
1007
1008 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1009 struct stat file_stat;
1010 struct dirent **dir_entries = NULL;
1011 int dir_entries_nb;
1012 int dir_entries_it;
1013
1014 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001015 ha_alert("Cannot open configuration file/directory %s : %s\n",
1016 wl->s,
1017 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001018 exit(1);
1019 }
1020
1021 if (!S_ISDIR(file_stat.st_mode))
1022 continue;
1023
1024 /* from this point wl->s is a directory */
1025
1026 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1027 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001028 ha_alert("Cannot open configuration directory %s : %s\n",
1029 wl->s,
1030 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001031 exit(1);
1032 }
1033
1034 /* for each element in the directory wl->s */
1035 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1036 struct dirent *dir_entry = dir_entries[dir_entries_it];
1037 char *filename = NULL;
1038 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1039
1040 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001041 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001042 */
1043 if (dir_entry->d_name[0] == '.' ||
1044 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1045 goto next_dir_entry;
1046
1047 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001048 ha_alert("Cannot load configuration files %s : out of memory.\n",
1049 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001050 exit(1);
1051 }
1052
1053 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001054 ha_alert("Cannot open configuration file %s : %s\n",
1055 wl->s,
1056 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001057 exit(1);
1058 }
1059
1060 /* don't add anything else than regular file in cfg_cfgfiles
1061 * this way we avoid loops
1062 */
1063 if (!S_ISREG(file_stat.st_mode))
1064 goto next_dir_entry;
1065
1066 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001067 ha_alert("Cannot load configuration files %s : %s\n",
1068 filename,
1069 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001070 exit(1);
1071 }
1072
1073next_dir_entry:
1074 free(filename);
1075 free(dir_entry);
1076 }
1077
1078 free(dir_entries);
1079
1080 /* remove the current directory (wl) from cfg_cfgfiles */
1081 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001082 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001083 free(wl);
1084 }
1085
1086 free(err);
1087}
1088
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089/*
William Lallemand73b85e72017-06-01 17:38:51 +02001090 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001091 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001092 * Return an allocated copy of argv
1093 */
1094
1095static char **copy_argv(int argc, char **argv)
1096{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001097 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001098
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001099 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001100 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001101 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001102 return NULL;
1103 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001104 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001105
William Lallemanddf6c5a82020-06-04 17:40:23 +02001106 /* first copy argv[0] */
1107 *newargv++ = *argv++;
1108 argc--;
1109
1110 while (argc > 0) {
1111 if (**argv != '-') {
1112 /* non options are copied but will fail in the argument parser */
1113 *newargv++ = *argv++;
1114 argc--;
1115
1116 } else {
1117 char *flag;
1118
1119 flag = *argv + 1;
1120
1121 if (flag[0] == '-' && flag[1] == 0) {
1122 /* "--\0" copy every arguments till the end of argv */
1123 *newargv++ = *argv++;
1124 argc--;
1125
1126 while (argc > 0) {
1127 *newargv++ = *argv++;
1128 argc--;
1129 }
1130 } else {
1131 switch (*flag) {
1132 case 's':
1133 /* -sf / -st and their parameters are ignored */
1134 if (flag[1] == 'f' || flag[1] == 't') {
1135 argc--;
1136 argv++;
1137 /* The list can't contain a negative value since the only
1138 way to know the end of this list is by looking for the
1139 next option or the end of the options */
1140 while (argc > 0 && argv[0][0] != '-') {
1141 argc--;
1142 argv++;
1143 }
William Lallemand398da622020-09-02 16:12:23 +02001144 } else {
1145 argc--;
1146 argv++;
1147
William Lallemanddf6c5a82020-06-04 17:40:23 +02001148 }
1149 break;
1150
1151 case 'x':
1152 /* this option and its parameter are ignored */
1153 argc--;
1154 argv++;
1155 if (argc > 0) {
1156 argc--;
1157 argv++;
1158 }
1159 break;
1160
1161 case 'C':
1162 case 'n':
1163 case 'm':
1164 case 'N':
1165 case 'L':
1166 case 'f':
1167 case 'p':
1168 case 'S':
1169 /* these options have only 1 parameter which must be copied and can start with a '-' */
1170 *newargv++ = *argv++;
1171 argc--;
1172 if (argc == 0)
1173 goto error;
1174 *newargv++ = *argv++;
1175 argc--;
1176 break;
1177 default:
1178 /* for other options just copy them without parameters, this is also done
1179 * for options like "--foo", but this will fail in the argument parser.
1180 * */
1181 *newargv++ = *argv++;
1182 argc--;
1183 break;
1184 }
William Lallemand73b85e72017-06-01 17:38:51 +02001185 }
1186 }
William Lallemand73b85e72017-06-01 17:38:51 +02001187 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001188
William Lallemanddf6c5a82020-06-04 17:40:23 +02001189 return retargv;
1190
1191error:
1192 free(retargv);
1193 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001194}
1195
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001196
1197/* Performs basic random seed initialization. The main issue with this is that
1198 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1199 * which means that there will only be 4 billion possible random sequences once
1200 * srandom() is called, regardless of the internal state. Not calling it is
1201 * even worse as we'll always produce the same randoms sequences. What we do
1202 * here is to create an initial sequence from various entropy sources, hash it
1203 * using SHA1 and keep the resulting 160 bits available globally.
1204 *
1205 * We initialize the current process with the first 32 bits before starting the
1206 * polling loop, where all this will be changed to have process specific and
1207 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001208 *
1209 * Before starting threads, it's still possible to call random() as srandom()
1210 * is initialized from this, but after threads and/or processes are started,
1211 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001212 */
1213static void ha_random_boot(char *const *argv)
1214{
1215 unsigned char message[256];
1216 unsigned char *m = message;
1217 struct timeval tv;
1218 blk_SHA_CTX ctx;
1219 unsigned long l;
1220 int fd;
1221 int i;
1222
1223 /* start with current time as pseudo-random seed */
1224 gettimeofday(&tv, NULL);
1225 write_u32(m, tv.tv_sec); m += 4;
1226 write_u32(m, tv.tv_usec); m += 4;
1227
1228 /* PID and PPID add some OS-based randomness */
1229 write_u16(m, getpid()); m += 2;
1230 write_u16(m, getppid()); m += 2;
1231
1232 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1233 fd = open("/dev/urandom", O_RDONLY);
1234 if (fd >= 0) {
1235 i = read(fd, m, 20);
1236 if (i > 0)
1237 m += i;
1238 close(fd);
1239 }
1240
1241 /* take up to 160 bits bytes from openssl (non-blocking) */
1242#ifdef USE_OPENSSL
1243 if (RAND_bytes(m, 20) == 1)
1244 m += 20;
1245#endif
1246
1247 /* take 160 bits from existing random in case it was already initialized */
1248 for (i = 0; i < 5; i++) {
1249 write_u32(m, random());
1250 m += 4;
1251 }
1252
1253 /* stack address (benefit form operating system's ASLR) */
1254 l = (unsigned long)&m;
1255 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1256
1257 /* argv address (benefit form operating system's ASLR) */
1258 l = (unsigned long)&argv;
1259 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1260
1261 /* use tv_usec again after all the operations above */
1262 gettimeofday(&tv, NULL);
1263 write_u32(m, tv.tv_usec); m += 4;
1264
1265 /*
1266 * At this point, ~84-92 bytes have been used
1267 */
1268
1269 /* finish with the hostname */
1270 strncpy((char *)m, hostname, message + sizeof(message) - m);
1271 m += strlen(hostname);
1272
1273 /* total message length */
1274 l = m - message;
1275
1276 memset(&ctx, 0, sizeof(ctx));
1277 blk_SHA1_Init(&ctx);
1278 blk_SHA1_Update(&ctx, message, l);
1279 blk_SHA1_Final(boot_seed, &ctx);
1280
1281 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001282 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001283}
1284
Willy Tarreau5a023f02019-03-01 14:19:31 +01001285/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1286 * setting, and returns it. It may return -1 meaning "unlimited" if some
1287 * unlimited proxies have been found and the global.maxconn value is not yet
1288 * set. It may also return a value greater than maxconn if it's not yet set.
1289 * Note that a value of zero means there is no need for pipes. -1 is never
1290 * returned if global.maxconn is valid.
1291 */
1292static int compute_ideal_maxpipes()
1293{
1294 struct proxy *cur;
1295 int nbfe = 0, nbbe = 0;
1296 int unlimited = 0;
1297 int pipes;
1298 int max;
1299
1300 for (cur = proxies_list; cur; cur = cur->next) {
1301 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1302 if (cur->cap & PR_CAP_FE) {
1303 max = cur->maxconn;
1304 nbfe += max;
1305 if (!max) {
1306 unlimited = 1;
1307 break;
1308 }
1309 }
1310 if (cur->cap & PR_CAP_BE) {
1311 max = cur->fullconn ? cur->fullconn : global.maxconn;
1312 nbbe += max;
1313 if (!max) {
1314 unlimited = 1;
1315 break;
1316 }
1317 }
1318 }
1319 }
1320
1321 pipes = MAX(nbfe, nbbe);
1322 if (global.maxconn) {
1323 if (pipes > global.maxconn || unlimited)
1324 pipes = global.maxconn;
1325 } else if (unlimited) {
1326 pipes = -1;
1327 }
1328
1329 return pipes >= 4 ? pipes / 4 : pipes;
1330}
1331
Willy Tarreauac350932019-03-01 15:43:14 +01001332/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1333 * rlimits and computes an ideal maxconn. It's meant to be called only when
1334 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001335 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1336 * default 100) is returned as it is expected that it will even run on tight
1337 * environments, and will maintain compatibility with previous packages that
1338 * used to rely on this value as the default one. The system will emit a
1339 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001340 */
1341static int compute_ideal_maxconn()
1342{
1343 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1344 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1345 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001346 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001347 int maxconn;
1348
1349 /* we have to take into account these elements :
1350 * - number of engine_fds, which inflates the number of FD needed per
1351 * connection by this number.
1352 * - number of pipes per connection on average : for the unlimited
1353 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1354 * fixed value of 2*pipes.
1355 * - two FDs per connection
1356 */
1357
1358 /* subtract listeners and checks */
1359 remain -= global.maxsock;
1360
Willy Tarreau3f200852019-03-14 19:13:17 +01001361 /* one epoll_fd/kqueue_fd per thread */
1362 remain -= global.nbthread;
1363
1364 /* one wake-up pipe (2 fd) per thread */
1365 remain -= 2 * global.nbthread;
1366
Willy Tarreauac350932019-03-01 15:43:14 +01001367 /* Fixed pipes values : we only subtract them if they're not larger
1368 * than the remaining FDs because pipes are optional.
1369 */
1370 if (pipes >= 0 && pipes * 2 < remain)
1371 remain -= pipes * 2;
1372
1373 if (pipes < 0) {
1374 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1375 * = maxconn * (2 + 0.5 + engine_fds)
1376 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1377 */
1378 maxconn = 2 * remain / (5 + 2 * engine_fds);
1379 } else {
1380 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1381 * = maxconn * (2 + engine_fds)
1382 */
1383 maxconn = remain / (2 + engine_fds);
1384 }
1385
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001386 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001387}
1388
Willy Tarreaua409f302020-03-10 17:08:53 +01001389/* computes the estimated maxsock value for the given maxconn based on the
1390 * possibly set global.maxpipes and existing partial global.maxsock. It may
1391 * temporarily change global.maxconn for the time needed to propagate the
1392 * computations, and will reset it.
1393 */
1394static int compute_ideal_maxsock(int maxconn)
1395{
1396 int maxpipes = global.maxpipes;
1397 int maxsock = global.maxsock;
1398
1399
1400 if (!maxpipes) {
1401 int old_maxconn = global.maxconn;
1402
1403 global.maxconn = maxconn;
1404 maxpipes = compute_ideal_maxpipes();
1405 global.maxconn = old_maxconn;
1406 }
1407
1408 maxsock += maxconn * 2; /* each connection needs two sockets */
1409 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1410 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1411 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1412
1413 /* compute fd used by async engines */
1414 if (global.ssl_used_async_engines) {
1415 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1416
1417 maxsock += maxconn * sides * global.ssl_used_async_engines;
1418 }
1419 return maxsock;
1420}
1421
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001422/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001423 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1424 * value is accepted, non-zero otherwise. This is used to determine if an
1425 * automatic limit may be applied or not. When it is not, the caller knows that
1426 * the highest we can do is the rlim_max at boot. In case of error, we return
1427 * that the setting is possible, so that we defer the error processing to the
1428 * final stage in charge of enforcing this.
1429 */
1430static int check_if_maxsock_permitted(int maxsock)
1431{
1432 struct rlimit orig_limit, test_limit;
1433 int ret;
1434
1435 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1436 return 1;
1437
1438 /* don't go further if we can't even set to what we have */
1439 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1440 return 1;
1441
1442 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1443 test_limit.rlim_cur = test_limit.rlim_max;
1444 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1445
1446 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1447 return 1;
1448
1449 return ret == 0;
1450}
1451
Willy Tarreau34527d52022-02-17 17:45:58 +01001452/* This performs th every basic early initialization at the end of the PREPARE
1453 * init stage. It may only assume that list heads are initialized, but not that
1454 * anything else is correct. It will initialize a number of variables that
1455 * depend on command line and will pre-parse the command line. If it fails, it
1456 * directly exits.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001457 */
Willy Tarreau34527d52022-02-17 17:45:58 +01001458static void init_early(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459{
Kevinm48936af2010-12-22 16:08:21 +00001460 char *progname;
Willy Tarreau34527d52022-02-17 17:45:58 +01001461 char *tmp;
1462 int len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001463
Willy Tarreau34527d52022-02-17 17:45:58 +01001464 /* First, let's initialize most global variables */
1465 totalconn = actconn = listeners = stopping = 0;
1466 killed = pid = 0;
1467
1468 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
1469 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Christopher Faulete3a5e352017-10-24 13:53:54 +02001470 global.mode = MODE_STARTING;
William Lallemand73b85e72017-06-01 17:38:51 +02001471
Willy Tarreau34527d52022-02-17 17:45:58 +01001472 /* if we were in mworker mode, we should restart in mworker mode */
1473 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1474 global.mode |= MODE_MWORKER;
David du Colombier7af46052012-05-16 14:16:48 +02001475
Willy Tarreau34527d52022-02-17 17:45:58 +01001476 /* initialize date, time, and pid */
1477 tzset();
1478 clock_init_process_date();
1479 start_date = now;
1480 pid = getpid();
1481
1482 /* Set local host name and adjust some environment variables.
1483 * NB: POSIX does not make it mandatory for gethostname() to
1484 * NULL-terminate the string in case of truncation, and at least
1485 * FreeBSD appears not to do it.
Emeric Brun2b920a12010-09-23 18:30:22 +02001486 */
1487 memset(hostname, 0, sizeof(hostname));
1488 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001489
Willy Tarreau34527d52022-02-17 17:45:58 +01001490 /* preset some environment variables */
1491 localpeer = strdup(hostname);
1492 if (!localpeer || setenv("HAPROXY_LOCALPEER", localpeer, 1) < 0) {
Dragan Dosen4f014152020-06-18 16:56:47 +02001493 ha_alert("Cannot allocate memory for local peer.\n");
1494 exit(EXIT_FAILURE);
1495 }
Emeric Brun2b920a12010-09-23 18:30:22 +02001496
Willy Tarreau34527d52022-02-17 17:45:58 +01001497 /* Initialize the random generators */
1498#ifdef USE_OPENSSL
1499 /* Initialize SSL random generator. Must be called before chroot for
1500 * access to /dev/urandom, and before ha_random_boot() which may use
1501 * RAND_bytes().
Willy Tarreaubaaee002006-06-26 02:48:02 +02001502 */
Willy Tarreau34527d52022-02-17 17:45:58 +01001503 if (!ssl_initialize_random()) {
1504 ha_alert("OpenSSL random data generator initialization failed.\n");
1505 exit(EXIT_FAILURE);
1506 }
1507#endif
1508 ha_random_boot(argv); // the argv pointer brings some kernel-fed entropy
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001509
Willy Tarreau34527d52022-02-17 17:45:58 +01001510 /* Some CPU affinity stuff may have to be initialized */
1511#ifdef USE_CPU_AFFINITY
1512 {
1513 int i;
1514 ha_cpuset_zero(&cpu_map.proc);
1515 ha_cpuset_zero(&cpu_map.proc_t1);
1516 for (i = 0; i < MAX_THREADS; ++i) {
1517 ha_cpuset_zero(&cpu_map.thread[i]);
1518 }
1519 }
1520#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001521
Willy Tarreau34527d52022-02-17 17:45:58 +01001522 /* extract the program name from argv[0], it will be used for the logs
1523 * and error messages.
1524 */
1525 progname = *argv;
1526 while ((tmp = strchr(progname, '/')) != NULL)
1527 progname = tmp + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001528
Willy Tarreau34527d52022-02-17 17:45:58 +01001529 len = strlen(progname);
1530 progname = strdup(progname);
1531 if (!progname) {
1532 ha_alert("Cannot allocate memory for log_tag.\n");
1533 exit(EXIT_FAILURE);
1534 }
Willy Tarreau84310e22014-02-14 11:59:04 +01001535
Willy Tarreau34527d52022-02-17 17:45:58 +01001536 chunk_initlen(&global.log_tag, progname, len, len);
1537}
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001538
Willy Tarreau392524d2022-02-17 18:10:36 +01001539/* handles program arguments. Very minimal parsing is performed, variables are
1540 * fed with some values, and lists are completed with other ones. In case of
1541 * error, it will exit.
Willy Tarreau34527d52022-02-17 17:45:58 +01001542 */
Willy Tarreau392524d2022-02-17 18:10:36 +01001543static void init_args(int argc, char **argv)
Willy Tarreau34527d52022-02-17 17:45:58 +01001544{
Willy Tarreau34527d52022-02-17 17:45:58 +01001545 char *progname = global.log_tag.area;
Willy Tarreau392524d2022-02-17 18:10:36 +01001546 char *err_msg = NULL;
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001547
Willy Tarreau34527d52022-02-17 17:45:58 +01001548 /* pre-fill in the global tuning options before we let the cmdline
1549 * change them.
1550 */
Willy Tarreau43b78992009-01-25 15:42:27 +01001551 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001552#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001553 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001554#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001555#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001556 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001557#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001558#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001559 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001560#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001561#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001562 global.tune.options |= GTUNE_USE_EVPORTS;
1563#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001564#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001565 global.tune.options |= GTUNE_USE_SPLICE;
1566#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001567#if defined(USE_GETADDRINFO)
1568 global.tune.options |= GTUNE_USE_GAI;
1569#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001570#if defined(SO_REUSEPORT)
1571 global.tune.options |= GTUNE_USE_REUSEPORT;
1572#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001573#ifdef USE_THREAD
1574 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1575#endif
William Dauchya5194602020-03-28 19:29:58 +01001576 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577
Willy Tarreau392524d2022-02-17 18:10:36 +01001578 /* keep a copy of original arguments for the master process */
1579 old_argv = copy_argv(argc, argv);
1580 if (!old_argv) {
1581 ha_alert("failed to copy argv.\n");
1582 exit(EXIT_FAILURE);
1583 }
1584
1585 /* skip program name and start */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 argc--; argv++;
1587 while (argc > 0) {
1588 char *flag;
1589
1590 if (**argv == '-') {
1591 flag = *argv+1;
1592
1593 /* 1 arg */
1594 if (*flag == 'v') {
1595 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001596 if (flag[1] == 'v') /* -vv */
1597 display_build_opts();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 exit(0);
1599 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001600#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001602 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001604#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001606 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001608#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001609 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001610 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001611#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001612#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001613 else if (*flag == 'd' && flag[1] == 'v')
1614 global.tune.options &= ~GTUNE_USE_EVPORTS;
1615#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001616#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001617 else if (*flag == 'd' && flag[1] == 'S')
1618 global.tune.options &= ~GTUNE_USE_SPLICE;
1619#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001620#if defined(USE_GETADDRINFO)
1621 else if (*flag == 'd' && flag[1] == 'G')
1622 global.tune.options &= ~GTUNE_USE_GAI;
1623#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001624#if defined(SO_REUSEPORT)
1625 else if (*flag == 'd' && flag[1] == 'R')
1626 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1627#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001628 else if (*flag == 'd' && flag[1] == 'V')
1629 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001630 else if (*flag == 'V')
1631 arg_mode |= MODE_VERBOSE;
1632 else if (*flag == 'd' && flag[1] == 'b')
1633 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001634 else if (*flag == 'd' && flag[1] == 'D')
1635 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001636 else if (*flag == 'd' && flag[1] == 'W')
1637 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreauef301b72022-02-23 14:15:18 +01001638 else if (*flag == 'd' && flag[1] == 'M') {
Willy Tarreau1408b1f2022-02-18 18:54:40 +01001639 int ret = pool_parse_debugging(flag + 2, &err_msg);
1640
1641 if (ret <= -1) {
1642 if (ret < -1)
1643 ha_alert("-dM: %s\n", err_msg);
1644 else
1645 printf("%s\n", err_msg);
1646 ha_free(&err_msg);
1647 exit(ret < -1 ? EXIT_FAILURE : 0);
1648 } else if (ret == 0) {
1649 ha_warning("-dM: %s\n", err_msg);
1650 ha_free(&err_msg);
1651 }
Willy Tarreauef301b72022-02-23 14:15:18 +01001652 }
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001653 else if (*flag == 'd' && flag[1] == 'r')
1654 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreau654726d2021-12-28 15:43:11 +01001655#if defined(HA_HAVE_DUMP_LIBS)
1656 else if (*flag == 'd' && flag[1] == 'L')
1657 arg_mode |= MODE_DUMP_LIBS;
1658#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001659 else if (*flag == 'd')
1660 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001661 else if (*flag == 'c' && flag[1] == 'c') {
1662 arg_mode |= MODE_CHECK_CONDITION;
1663 argv++;
1664 argc--;
1665 check_condition = *argv;
1666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667 else if (*flag == 'c')
1668 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001669 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001670 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001671 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001672 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001673#if defined(USE_SYSTEMD)
1674 global.tune.options |= GTUNE_USE_SYSTEMD;
1675#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001676 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 +01001677 usage(progname);
1678#endif
1679 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001680 else if (*flag == 'W')
1681 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001682 else if (*flag == 'q')
1683 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001684 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001685 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001686 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001687 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001688 }
William Lallemand4fc09692017-06-19 16:37:19 +02001689 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001690 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001691 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001692
Olivier Houchardf73629d2017-04-05 22:33:04 +02001693 argv++;
1694 argc--;
1695 }
William Lallemande7361152018-10-26 14:47:36 +02001696 else if (*flag == 'S') {
1697 struct wordlist *c;
1698
William Lallemanda6b32492020-06-04 23:49:20 +02001699 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001700 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1701 usage(progname);
1702 }
1703 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1704 ha_alert("Cannot allocate memory\n");
1705 exit(EXIT_FAILURE);
1706 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001707 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001708
1709 argv++;
1710 argc--;
1711 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001712 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1713 /* list of pids to finish ('f') or terminate ('t') */
1714
1715 if (flag[1] == 'f')
1716 oldpids_sig = SIGUSR1; /* finish then exit */
1717 else
1718 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001719 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001720 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001721 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1722 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001723 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001724 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001725 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001726 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001727 errno = 0;
1728 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1729 if (errno) {
1730 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1731 flag,
1732 *argv, strerror(errno));
1733 exit(1);
1734 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001735 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001736 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001737 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1738 flag, endptr);
1739 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001740 }
Chris Lane236062f2018-02-05 23:15:44 +00001741 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001742 if (oldpids[nb_oldpids] <= 0)
1743 usage(progname);
1744 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001745 }
1746 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001747 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1748 /* now that's a cfgfile list */
1749 argv++; argc--;
1750 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001751 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001752 ha_alert("Cannot load configuration file/directory %s : %s\n",
1753 *argv,
1754 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001755 exit(1);
1756 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001757 argv++; argc--;
1758 }
1759 break;
1760 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001761 else { /* >=2 args */
1762 argv++; argc--;
1763 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001764 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001765
1766 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001767 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001768 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001769 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001770 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001771 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001772 free(localpeer);
1773 if ((localpeer = strdup(*argv)) == NULL) {
1774 ha_alert("Cannot allocate memory for local peer.\n");
1775 exit(EXIT_FAILURE);
1776 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001777 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001778 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001779 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001780 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001781 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001782 ha_alert("Cannot load configuration file/directory %s : %s\n",
1783 *argv,
1784 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001785 exit(1);
1786 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001787 break;
Willy Tarreau392524d2022-02-17 18:10:36 +01001788 case 'p' :
1789 free(global.pidfile);
1790 if ((global.pidfile = strdup(*argv)) == NULL) {
1791 ha_alert("Cannot allocate memory for pidfile.\n");
1792 exit(EXIT_FAILURE);
1793 }
1794 break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001795 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001796 }
1797 }
1798 }
1799 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001800 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001801 argv++; argc--;
1802 }
Willy Tarreau392524d2022-02-17 18:10:36 +01001803 free(err_msg);
1804}
1805
1806/*
1807 * This function initializes all the necessary variables. It only returns
1808 * if everything is OK. If something fails, it exits.
1809 */
1810static void init(int argc, char **argv)
1811{
1812 char *progname = global.log_tag.area;
1813 int err_code = 0;
1814 struct wordlist *wl;
1815 struct proxy *px;
1816 struct post_check_fct *pcf;
1817 int ideal_maxconn;
1818
1819 if (!init_trash_buffers(1)) {
1820 ha_alert("failed to initialize trash buffers.\n");
1821 exit(1);
1822 }
1823
1824 if (init_acl() != 0)
1825 exit(1);
1826
1827 /* Initialise lua. */
1828 hlua_init();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001829
Christopher Faulete3a5e352017-10-24 13:53:54 +02001830 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001831 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Willy Tarreau654726d2021-12-28 15:43:11 +01001832 | MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001833
William Lallemand944e6192018-11-21 15:48:31 +01001834 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001835 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001836 global.mode |= MODE_MWORKER_WAIT;
1837 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001838 }
1839
Willy Tarreau26146192021-07-21 10:01:36 +02001840 if ((global.mode & (MODE_MWORKER | MODE_CHECK | MODE_CHECK_CONDITION)) == MODE_MWORKER &&
1841 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001842 atexit_flag = 1;
1843 atexit(reexec_on_failure);
1844 }
1845
Willy Tarreau576132e2011-09-10 19:26:56 +02001846 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001847 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001848 exit(1);
1849 }
1850
Amaury Denoyelle11124302021-06-04 18:22:08 +02001851 usermsgs_clr("config");
1852
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001853 if (global.mode & MODE_CHECK_CONDITION) {
1854 int result;
1855
1856 uint32_t err;
1857 const char *errptr;
1858 char *errmsg = NULL;
1859
1860 char *args[MAX_LINE_ARGS+1];
1861 int arg = sizeof(args) / sizeof(*args);
1862 size_t outlen = strlen(check_condition) + 1;
Willy Tarreauc8194c32021-07-16 16:38:58 +02001863 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001864
1865 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02001866 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001867 &errptr);
1868
1869 if (err & PARSE_ERR_QUOTE) {
1870 ha_alert("Syntax Error in condition: Unmatched quote.\n");
1871 exit(2);
1872 }
1873
1874 if (err & PARSE_ERR_HEX) {
1875 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
1876 exit(2);
1877 }
1878
1879 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
1880 ha_alert("Error in condition: Line too long.\n");
1881 exit(2);
1882 }
1883
Willy Tarreauc8194c32021-07-16 16:38:58 +02001884 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001885 ha_alert("Error in condition: Too many words.\n");
1886 exit(2);
1887 }
1888
1889 if (err) {
1890 ha_alert("Unhandled error in condition, please report this to the developers.\n");
1891 exit(2);
1892 }
1893
Willy Tarreauc8194c32021-07-16 16:38:58 +02001894 /* remerge all words into a single expression */
1895 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
1896 ;
1897
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001898 result = cfg_eval_condition(args, &errmsg, &errptr);
1899
1900 if (result < 0) {
1901 if (errmsg)
1902 ha_alert("Failed to evaluate condition: %s\n", errmsg);
1903
1904 exit(2);
1905 }
1906
1907 exit(result ? 0 : 1);
1908 }
1909
William Lallemand944e6192018-11-21 15:48:31 +01001910 /* in wait mode, we don't try to read the configuration files */
1911 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001912 char *env_cfgfiles = NULL;
1913 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001914
William Lallemand944e6192018-11-21 15:48:31 +01001915 /* handle cfgfiles that are actually directories */
1916 cfgfiles_expand_directories();
1917
1918 if (LIST_ISEMPTY(&cfg_cfgfiles))
1919 usage(progname);
1920
1921
1922 list_for_each_entry(wl, &cfg_cfgfiles, list) {
1923 int ret;
1924
Christopher Faulet4e366822021-01-12 18:57:38 +01001925 if (env_err == 0) {
1926 if (!memprintf(&env_cfgfiles, "%s%s%s",
1927 (env_cfgfiles ? env_cfgfiles : ""),
1928 (env_cfgfiles ? ";" : ""), wl->s))
1929 env_err = 1;
1930 }
William Lallemand7b302d82019-05-20 11:15:37 +02001931
William Lallemand944e6192018-11-21 15:48:31 +01001932 ret = readcfgfile(wl->s);
1933 if (ret == -1) {
1934 ha_alert("Could not open configuration file %s : %s\n",
1935 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01001936 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001937 exit(1);
1938 }
1939 if (ret & (ERR_ABORT|ERR_FATAL))
1940 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
1941 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01001942 if (err_code & ERR_ABORT) {
1943 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001944 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01001945 }
Willy Tarreauc4382422009-12-06 13:10:44 +01001946 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001947
William Lallemand944e6192018-11-21 15:48:31 +01001948 /* do not try to resolve arguments nor to spot inconsistencies when
1949 * the configuration contains fatal errors caused by files not found
1950 * or failed memory allocations.
1951 */
1952 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1953 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01001954 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001955 exit(1);
1956 }
Christopher Faulet4e366822021-01-12 18:57:38 +01001957 if (env_err) {
1958 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
1959 exit(1);
1960 }
1961 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
1962 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02001963
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02001964 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001965 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01001966 struct mworker_proc *tmproc;
1967
William Lallemand482f9a92019-04-12 16:15:00 +02001968 setenv("HAPROXY_MWORKER", "1", 1);
1969
William Lallemand16dd1b32018-11-19 18:46:18 +01001970 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
1971
William Lallemand56be0e02022-01-28 21:11:41 +01001972 tmproc = mworker_proc_new();
William Lallemand16dd1b32018-11-19 18:46:18 +01001973 if (!tmproc) {
1974 ha_alert("Cannot allocate process structures.\n");
1975 exit(EXIT_FAILURE);
1976 }
William Lallemand8f7069a2019-04-12 16:09:23 +02001977 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01001978 tmproc->pid = pid;
1979 tmproc->timestamp = start_date.tv_sec;
William Lallemand16dd1b32018-11-19 18:46:18 +01001980 proc_self = tmproc;
1981
Willy Tarreau2b718102021-04-21 07:32:39 +02001982 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01001983 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001984
William Lallemand56be0e02022-01-28 21:11:41 +01001985 tmproc = mworker_proc_new();
Willy Tarreau6185a032021-06-15 08:02:06 +02001986 if (!tmproc) {
1987 ha_alert("Cannot allocate process structures.\n");
1988 exit(EXIT_FAILURE);
1989 }
Willy Tarreau6185a032021-06-15 08:02:06 +02001990 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
William Lallemandce83b4a2018-10-26 14:47:30 +02001991
Willy Tarreau6185a032021-06-15 08:02:06 +02001992 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
1993 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02001994 }
Willy Tarreau6185a032021-06-15 08:02:06 +02001995
1996 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01001997 }
1998 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
1999 struct wordlist *it, *c;
2000
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02002001 /* get the info of the children in the env */
2002 if (mworker_env_to_proc_list() < 0) {
2003 exit(EXIT_FAILURE);
2004 }
William Lallemande7361152018-10-26 14:47:36 +02002005
William Lallemand550db6d2018-11-06 17:37:12 +01002006 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02002007
William Lallemand550db6d2018-11-06 17:37:12 +01002008 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02002009 ha_alert("Can't create the master's CLI.\n");
2010 exit(EXIT_FAILURE);
2011 }
William Lallemande7361152018-10-26 14:47:36 +02002012
William Lallemand550db6d2018-11-06 17:37:12 +01002013 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
2014
2015 if (mworker_cli_proxy_new_listener(c->s) < 0) {
2016 ha_alert("Can't create the master's CLI.\n");
2017 exit(EXIT_FAILURE);
2018 }
Willy Tarreau2b718102021-04-21 07:32:39 +02002019 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01002020 free(c->s);
2021 free(c);
2022 }
2023 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002024 }
2025
Eric Salama5ba83352021-03-16 15:11:17 +01002026 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
2027 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
2028 }
2029
Christopher Faulet27c8d202021-10-13 09:50:53 +02002030 /* destroy unreferenced defaults proxies */
2031 proxy_destroy_all_unref_defaults();
2032
Willy Tarreaue90904d2021-02-12 14:08:31 +01002033
Willy Tarreaubb925012009-07-23 13:36:36 +02002034 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02002035 for (px = proxies_list; px; px = px->next) {
2036 struct server *srv;
2037 struct post_proxy_check_fct *ppcf;
2038 struct post_server_check_fct *pscf;
2039
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002040 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002041 continue;
2042
Christopher Fauletc1692962019-08-12 09:51:07 +02002043 list_for_each_entry(pscf, &post_server_check_list, list) {
2044 for (srv = px->srv; srv; srv = srv->next)
2045 err_code |= pscf->fct(srv);
2046 }
2047 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2048 err_code |= ppcf->fct(px);
2049 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002050 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002051 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002052 exit(1);
2053 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002054
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002055 err_code |= pattern_finalize_config();
2056 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2057 ha_alert("Failed to finalize pattern config.\n");
2058 exit(1);
2059 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002060
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002061 if (global.rlimit_memmax_all)
2062 global.rlimit_memmax = global.rlimit_memmax_all;
2063
Willy Tarreaue5733232019-05-22 19:24:06 +02002064#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002065 err_code |= netns_init();
2066 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002067 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002068 exit(1);
2069 }
2070#endif
2071
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002072 /* Apply server states */
2073 apply_server_state();
2074
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002075 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002076 srv_compute_all_admin_states(px);
2077
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002078 /* Apply servers' configured address */
2079 err_code |= srv_init_addr();
2080 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002081 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002082 exit(1);
2083 }
2084
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002085 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2086 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2087 exit(1);
2088 }
2089
Willy Tarreau654726d2021-12-28 15:43:11 +01002090#if defined(HA_HAVE_DUMP_LIBS)
2091 if (global.mode & MODE_DUMP_LIBS) {
2092 qfprintf(stdout, "List of loaded object files:\n");
2093 chunk_reset(&trash);
2094 if (dump_libs(&trash, 0))
2095 printf("%s", trash.area);
2096 }
2097#endif
2098
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002100 struct peers *pr;
2101 struct proxy *px;
2102
Willy Tarreaubebd2122020-04-15 16:06:11 +02002103 if (warned & WARN_ANY)
2104 qfprintf(stdout, "Warnings were found.\n");
2105
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002106 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002107 if (pr->peers_fe)
2108 break;
2109
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002110 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002111 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002112 break;
2113
Emeric Brunbc5c8212021-08-13 09:32:50 +02002114 if (!px) {
2115 /* We may only have log-forward section */
2116 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002117 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002118 break;
2119 }
2120
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002121 if (pr || px) {
2122 /* At least one peer or one listener has been found */
2123 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002124 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002125 }
2126 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2127 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002128 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002129
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002130 if (global.mode & MODE_DIAG) {
2131 cfg_run_diagnostics();
2132 }
2133
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002134 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002135 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002136
Willy Tarreaue6945732016-12-21 19:57:00 +01002137 list_for_each_entry(pcf, &post_check_list, list) {
2138 err_code |= pcf->fct();
2139 if (err_code & (ERR_ABORT|ERR_FATAL))
2140 exit(1);
2141 }
2142
Willy Tarreaubaaee002006-06-26 02:48:02 +02002143 if (cfg_maxconn > 0)
2144 global.maxconn = cfg_maxconn;
2145
Willy Tarreau4975d142021-03-13 11:00:33 +01002146 if (global.cli_fe)
2147 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002148
2149 if (cfg_peers) {
2150 /* peers also need to bypass global maxconn */
2151 struct peers *p = cfg_peers;
2152
2153 for (p = cfg_peers; p; p = p->next)
2154 if (p->peers_fe)
2155 global.maxsock += p->peers_fe->maxconn;
2156 }
2157
Willy Tarreaud0256482015-01-15 21:45:22 +01002158 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002159 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2160 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2161 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2162 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002163 *
2164 * If memmax is set, then it depends on which values are set. If
2165 * maxsslconn is set, we use memmax to determine how many cleartext
2166 * connections may be added, and set maxconn to the sum of the two.
2167 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2168 * the remaining amount of memory between memmax and the cleartext
2169 * connections. If neither are set, then it is considered that all
2170 * connections are SSL-capable, and maxconn is computed based on this,
2171 * then maxsslconn accordingly. We need to know if SSL is used on the
2172 * frontends, backends, or both, because when it's used on both sides,
2173 * we need twice the value for maxsslconn, but we only count the
2174 * handshake once since it is not performed on the two sides at the
2175 * same time (frontend-side is terminated before backend-side begins).
2176 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002177 * ssl_handshake_cost during its initialization. In any case, if
2178 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2179 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002180 */
Willy Tarreauac350932019-03-01 15:43:14 +01002181 ideal_maxconn = compute_ideal_maxconn();
2182
Willy Tarreaud0256482015-01-15 21:45:22 +01002183 if (!global.rlimit_memmax) {
2184 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002185 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002186 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2187 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2188 }
2189 }
2190#ifdef USE_OPENSSL
2191 else if (!global.maxconn && !global.maxsslconn &&
2192 (global.ssl_used_frontend || global.ssl_used_backend)) {
2193 /* memmax is set, compute everything automatically. Here we want
2194 * to ensure that all SSL connections will be served. We take
2195 * care of the number of sides where SSL is used, and consider
2196 * the worst case : SSL used on both sides and doing a handshake
2197 * simultaneously. Note that we can't have more than maxconn
2198 * handshakes at a time by definition, so for the worst case of
2199 * two SSL conns per connection, we count a single handshake.
2200 */
2201 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2202 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002203 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002204
2205 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2206 mem -= global.maxzlibmem;
2207 mem = mem * MEM_USABLE_RATIO;
2208
Willy Tarreau304e17e2020-03-10 17:54:54 +01002209 /* Principle: we test once to set maxconn according to the free
2210 * memory. If it results in values the system rejects, we try a
2211 * second time by respecting rlim_fd_max. If it fails again, we
2212 * go back to the initial value and will let the final code
2213 * dealing with rlimit report the error. That's up to 3 attempts.
2214 */
2215 do {
2216 global.maxconn = mem /
2217 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2218 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2219 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002220
Willy Tarreau304e17e2020-03-10 17:54:54 +01002221 if (retried == 1)
2222 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2223 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002224#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002225 if (global.maxconn > SYSTEM_MAXCONN)
2226 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002227#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002228 global.maxsslconn = sides * global.maxconn;
2229
2230 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2231 break;
2232 } while (retried++ < 2);
2233
Willy Tarreaud0256482015-01-15 21:45:22 +01002234 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2235 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2236 global.maxconn, global.maxsslconn);
2237 }
2238 else if (!global.maxsslconn &&
2239 (global.ssl_used_frontend || global.ssl_used_backend)) {
2240 /* memmax and maxconn are known, compute maxsslconn automatically.
2241 * maxsslconn being forced, we don't know how many of it will be
2242 * on each side if both sides are being used. The worst case is
2243 * when all connections use only one SSL instance because
2244 * handshakes may be on two sides at the same time.
2245 */
2246 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2247 int64_t mem = global.rlimit_memmax * 1048576ULL;
2248 int64_t sslmem;
2249
2250 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2251 mem -= global.maxzlibmem;
2252 mem = mem * MEM_USABLE_RATIO;
2253
Willy Tarreau87b09662015-04-03 00:22:06 +02002254 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002255 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2256 global.maxsslconn = round_2dig(global.maxsslconn);
2257
2258 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002259 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2260 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2261 "without SSL is %d, but %d was found and SSL is in use.\n",
2262 global.rlimit_memmax,
2263 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2264 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002265 exit(1);
2266 }
2267
2268 if (global.maxsslconn > sides * global.maxconn)
2269 global.maxsslconn = sides * global.maxconn;
2270
2271 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2272 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2273 }
2274#endif
2275 else if (!global.maxconn) {
2276 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2277 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2278 int64_t mem = global.rlimit_memmax * 1048576ULL;
2279 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002280 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002281
2282 if (global.ssl_used_frontend || global.ssl_used_backend)
2283 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2284
2285 mem -= global.maxzlibmem;
2286 mem = mem * MEM_USABLE_RATIO;
2287
2288 clearmem = mem;
2289 if (sides)
2290 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2291
Willy Tarreau304e17e2020-03-10 17:54:54 +01002292 /* Principle: we test once to set maxconn according to the free
2293 * memory. If it results in values the system rejects, we try a
2294 * second time by respecting rlim_fd_max. If it fails again, we
2295 * go back to the initial value and will let the final code
2296 * dealing with rlimit report the error. That's up to 3 attempts.
2297 */
2298 do {
2299 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2300 if (retried == 1)
2301 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2302 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002303#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002304 if (global.maxconn > SYSTEM_MAXCONN)
2305 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002306#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002307
Willy Tarreau304e17e2020-03-10 17:54:54 +01002308 if (clearmem <= 0 || !global.maxconn) {
2309 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2310 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2311 "is %d, but %d was found.\n",
2312 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002313 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002314 global.maxsslconn);
2315 exit(1);
2316 }
2317
2318 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2319 break;
2320 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002321
2322 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2323 if (sides && global.maxsslconn > sides * global.maxconn) {
2324 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2325 "to be limited to %d. Better reduce global.maxsslconn to get more "
2326 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2327 }
2328 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2329 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002330 }
2331
Willy Tarreaua409f302020-03-10 17:08:53 +01002332 global.maxsock = compute_ideal_maxsock(global.maxconn);
2333 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002334 if (!global.maxpipes)
2335 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002336
Olivier Houchard88698d92019-04-16 19:07:22 +02002337 /* update connection pool thresholds */
2338 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2339 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2340
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002341 proxy_adjust_all_maxconn();
2342
Willy Tarreau1db37712007-06-03 17:16:49 +02002343 if (global.tune.maxpollevents <= 0)
2344 global.tune.maxpollevents = MAX_POLL_EVENTS;
2345
Willy Tarreau060a7612021-03-10 11:06:26 +01002346 if (global.tune.runqueue_depth <= 0) {
2347 /* tests on various thread counts from 1 to 64 have shown an
2348 * optimal queue depth following roughly 1/sqrt(threads).
2349 */
2350 int s = my_flsl(global.nbthread);
2351 s += (global.nbthread / s); // roughly twice the sqrt.
2352 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2353 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002354
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002355 if (global.tune.recv_enough == 0)
2356 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2357
Willy Tarreau27a674e2009-08-17 07:23:33 +02002358 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2359 global.tune.maxrewrite = global.tune.bufsize / 2;
2360
Amaury Denoyelle11124302021-06-04 18:22:08 +02002361 usermsgs_clr(NULL);
2362
Willy Tarreaubaaee002006-06-26 02:48:02 +02002363 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2364 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002365 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002366 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2367 }
2368
William Lallemand095ba4c2017-06-01 17:38:50 +02002369 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002370 /* command line daemon mode inhibits foreground and debug modes mode */
2371 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002372 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002374
2375 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002376
William Lallemand095ba4c2017-06-01 17:38:50 +02002377 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002378 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002379 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 }
2381
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002382 if (global.nbthread < 1)
2383 global.nbthread = 1;
2384
Christopher Faulet3ef26392017-08-29 16:46:57 +02002385 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002386 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002387 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002388 exit(1);
2389 }
2390
Christopher Faulet96d44832017-11-14 22:02:30 +01002391 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002392 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002393 exit(1);
2394 }
2395
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002396 /*
2397 * Note: we could register external pollers here.
2398 * Built-in pollers have been registered before main().
2399 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002400
Willy Tarreau43b78992009-01-25 15:42:27 +01002401 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002402 disable_poller("kqueue");
2403
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002404 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2405 disable_poller("evports");
2406
Willy Tarreau43b78992009-01-25 15:42:27 +01002407 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002408 disable_poller("epoll");
2409
Willy Tarreau43b78992009-01-25 15:42:27 +01002410 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002411 disable_poller("poll");
2412
Willy Tarreau43b78992009-01-25 15:42:27 +01002413 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002414 disable_poller("select");
2415
2416 /* Note: we could disable any poller by name here */
2417
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002418 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002419 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002420 fprintf(stderr, "\n");
2421 list_filters(stderr);
2422 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002423
Willy Tarreau4f60f162007-04-08 16:39:58 +02002424 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002425 ha_alert("No polling mechanism available.\n"
2426 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2427 " is too low on this platform to support maxconn and the number of listeners\n"
2428 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2429 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2430 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2431 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2432 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2433 " check build settings using 'haproxy -vv'.\n\n",
2434 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002435 exit(1);
2436 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002437 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2438 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002439 }
2440
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002441 if (!global.node)
2442 global.node = strdup(hostname);
2443
Willy Tarreau02b092f2020-10-07 18:36:54 +02002444 /* stop disabled proxies */
2445 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002446 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002447 stop_proxy(px);
2448 }
2449
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002450 if (!hlua_post_init())
2451 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452}
2453
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002454void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002455{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002456 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002457 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002458 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002459 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002460 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002461 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002462 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002463 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002464 struct per_thread_init_fct *tif, *tifb;
2465 struct per_thread_deinit_fct *tdf, *tdfb;
2466 struct per_thread_alloc_fct *taf, *tafb;
2467 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002468 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002469 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002470 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002471 int cur_fd;
2472
2473 /* At this point the listeners state is weird:
2474 * - most listeners are still bound and referenced in their protocol
2475 * - some might be zombies that are not in their proto anymore, but
2476 * still appear in their proxy's listeners with a valid FD.
2477 * - some might be stopped and still appear in their proxy as FD #-1
2478 * - among all of them, some might be inherited hence shared and we're
2479 * not allowed to pause them or whatever, we must just close them.
2480 * - finally some are not listeners (pipes, logs, stdout, etc) and
2481 * must be left intact.
2482 *
2483 * The safe way to proceed is to unbind (and close) whatever is not yet
2484 * unbound so that no more receiver/listener remains alive. Then close
2485 * remaining listener FDs, which correspond to zombie listeners (those
2486 * belonging to disabled proxies that were in another process).
2487 * objt_listener() would be cleaner here but not converted yet.
2488 */
2489 protocol_unbind_all();
2490
2491 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002492 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002493 continue;
2494
Willy Tarreaua74cb382020-10-15 21:29:49 +02002495 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002496 struct listener *l = fdtab[cur_fd].owner;
2497
2498 BUG_ON(l->state != LI_INIT);
2499 unbind_listener(l);
2500 }
2501 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002502
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002503 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002504 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002505 /* build a list of unique uri_auths */
2506 if (!ua)
2507 ua = p->uri_auth;
2508 else {
2509 /* check if p->uri_auth is unique */
2510 for (uap = ua; uap; uap=uap->next)
2511 if (uap == p->uri_auth)
2512 break;
2513
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002514 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002515 /* add it, if it is */
2516 p->uri_auth->next = ua;
2517 ua = p->uri_auth;
2518 }
William Lallemand0f99e342011-10-12 17:50:54 +02002519 }
2520
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002521 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002522 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002523 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002525
Christopher Faulet27c8d202021-10-13 09:50:53 +02002526 /* destroy all referenced defaults proxies */
2527 proxy_destroy_all_unref_defaults();
2528
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002529 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002530 struct stat_scope *scope, *scopep;
2531
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002532 uap = ua;
2533 ua = ua->next;
2534
Willy Tarreaua534fea2008-08-03 12:19:50 +02002535 free(uap->uri_prefix);
2536 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002537 free(uap->node);
2538 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002539
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002540 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002541 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002542
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002543 scope = uap->scope;
2544 while (scope) {
2545 scopep = scope;
2546 scope = scope->next;
2547
2548 free(scopep->px_id);
2549 free(scopep);
2550 }
2551
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002552 free(uap);
2553 }
2554
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002555 userlist_free(userlist);
2556
David Carlier834cb2e2015-09-25 12:02:25 +01002557 cfg_unregister_sections();
2558
Christopher Faulet0132d062017-07-26 15:33:35 +02002559 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002560
Willy Tarreau05554e62016-12-21 20:46:26 +01002561 list_for_each_entry(pdf, &post_deinit_list, list)
2562 pdf->fct();
2563
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002564 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002565 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002566 ha_free(&global.chroot);
2567 ha_free(&global.pidfile);
2568 ha_free(&global.node);
2569 ha_free(&global.desc);
2570 ha_free(&oldpids);
2571 ha_free(&old_argv);
2572 ha_free(&localpeer);
2573 ha_free(&global.server_state_base);
2574 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002575 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002576 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002577
William Lallemand0f99e342011-10-12 17:50:54 +02002578 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002579 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002580 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002581 free(log);
2582 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002583 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002584 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002585 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002586 free(wl);
2587 }
2588
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002589 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2590 if (bol->must_free)
2591 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002592 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002593 free(bol);
2594 }
2595
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002596 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002597 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002598 free(pxdf);
2599 }
2600
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002601 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002602 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002603 free(pdf);
2604 }
2605
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002606 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002607 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002608 free(srvdf);
2609 }
2610
Tim Duesterhusfc854942020-09-10 19:46:42 +02002611 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002612 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002613 free(pcf);
2614 }
2615
Tim Duesterhus34bef072020-07-04 11:49:50 +02002616 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002617 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002618 free(pscf);
2619 }
2620
Tim Duesterhus53508d62020-09-10 19:46:40 +02002621 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002622 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002623 free(ppcf);
2624 }
2625
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002626 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002627 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002628 free(tif);
2629 }
2630
2631 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002632 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002633 free(tdf);
2634 }
2635
2636 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002637 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002638 free(taf);
2639 }
2640
2641 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002642 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002643 free(tff);
2644 }
2645
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002646 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002647 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002648 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649} /* end deinit() */
2650
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002651__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002652{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002653 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002654 deinit();
2655 exit(status);
2656}
William Lallemand72160322018-11-06 17:37:16 +01002657
Willy Tarreau918ff602011-07-25 16:33:49 +02002658/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002659void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002660{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002661 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002662
Willy Tarreau55542642021-10-08 09:33:24 +02002663 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002664 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002665 wake_expired_tasks();
2666
William Lallemand1aab50b2018-06-07 09:46:01 +02002667 /* check if we caught some signals and process them in the
2668 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002669 if (signal_queue_len && tid == 0) {
2670 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002671 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002672 }
2673
2674 /* Process a few tasks */
2675 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002676
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002677 /* also stop if we failed to cleanly stop all tasks */
2678 if (killed > 1)
2679 break;
2680
Willy Tarreau10146c92015-04-13 20:44:19 +02002681 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002682 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002683 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002684 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002685 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002686 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2687 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002688 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002689 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002690 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002691 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002692 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002693 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002694
Willy Tarreau4f46a352020-03-23 09:27:28 +01002695 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002696 int i;
2697
2698 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002699 /* stop muxes before acknowledging stopping */
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002700 if (!(stopping_thread_mask & tid_bit)) {
2701 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2702 wake = 1;
2703 }
2704
Willy Tarreau1db42732021-04-06 11:44:07 +02002705 if (_HA_ATOMIC_OR_FETCH(&stopping_thread_mask, tid_bit) == tid_bit) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002706 /* notify all threads that stopping was just set */
2707 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002708 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002709 wake_thread(i);
2710 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002711 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002712
2713 /* stop when there's nothing left to do */
2714 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002715 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2716 /* wake all threads waiting on jobs==0 */
2717 for (i = 0; i < global.nbthread; i++)
2718 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2719 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002720 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002721 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002722 }
2723
Willy Tarreauc49ba522019-12-11 08:12:23 +01002724 /* If we have to sleep, measure how long */
2725 next = wake ? TICK_ETERNITY : next_timer_expiry();
2726
Willy Tarreau58b458d2008-06-29 22:40:23 +02002727 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002728 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002729
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002730 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002731 }
2732}
2733
Christopher Faulet1d17c102017-08-29 15:38:48 +02002734static void *run_thread_poll_loop(void *data)
2735{
Willy Tarreau082b6282019-05-22 14:42:12 +02002736 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002737 struct per_thread_init_fct *ptif;
2738 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002739 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002740 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002741 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2742 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002743
Willy Tarreau43ab05b2021-09-28 09:43:11 +02002744 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02002745 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02002746 clock_set_local_source();
Willy Tarreau91e6df02019-05-03 17:21:18 +02002747
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002748 /* Now, initialize one thread init at a time. This is better since
2749 * some init code is a bit tricky and may release global resources
2750 * after reallocating them locally. This will also ensure there is
2751 * no race on file descriptors allocation.
2752 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002753#ifdef USE_THREAD
2754 pthread_mutex_lock(&init_mutex);
2755#endif
2756 /* The first thread must set the number of threads left */
2757 if (!init_left)
2758 init_left = global.nbthread;
2759 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002760
Willy Tarreau55542642021-10-08 09:33:24 +02002761 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002762
Willy Tarreau082b6282019-05-22 14:42:12 +02002763 /* per-thread alloc calls performed here are not allowed to snoop on
2764 * other threads, so they are free to initialize at their own rhythm
2765 * as long as they act as if they were alone. None of them may rely
2766 * on resources initialized by the other ones.
2767 */
2768 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2769 if (!ptaf->fct()) {
2770 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002771#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002772 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002773#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02002774 exit(1);
2775 }
2776 }
2777
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002778 /* per-thread init calls performed here are not allowed to snoop on
2779 * other threads, so they are free to initialize at their own rhythm
2780 * as long as they act as if they were alone.
2781 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002782 list_for_each_entry(ptif, &per_thread_init_list, list) {
2783 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002784 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002785#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002786 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002787#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002788 exit(1);
2789 }
2790 }
2791
Willy Tarreau71092822019-06-10 09:51:04 +02002792 /* enabling protocols will result in fd_insert() calls to be performed,
2793 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002794 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002795 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002796 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002797 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002798
Willy Tarreau34a150c2019-06-11 09:16:41 +02002799#ifdef USE_THREAD
2800 pthread_cond_broadcast(&init_cond);
2801 pthread_mutex_unlock(&init_mutex);
2802
2803 /* now wait for other threads to finish starting */
2804 pthread_mutex_lock(&init_mutex);
2805 while (init_left)
2806 pthread_cond_wait(&init_cond, &init_mutex);
2807 pthread_mutex_unlock(&init_mutex);
2808#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002809
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002810#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2811 /* Let's refrain from using setuid executables. This way the impact of
2812 * an eventual vulnerability in a library remains limited. It may
2813 * impact external checks but who cares about them anyway ? In the
2814 * worst case it's possible to disable the option. Obviously we do this
2815 * in workers only. We can't hard-fail on this one as it really is
2816 * implementation dependent though we're interested in feedback, hence
2817 * the warning.
2818 */
2819 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2820 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002821 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 +01002822 ha_warning("Failed to disable setuid, please report to developers with detailed "
2823 "information about your operating system. You can silence this warning "
2824 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2825 }
2826 }
2827#endif
2828
Willy Tarreaud96f1122019-12-03 07:07:36 +01002829#if defined(RLIMIT_NPROC)
2830 /* all threads have started, it's now time to prevent any new thread
2831 * or process from starting. Obviously we do this in workers only. We
2832 * can't hard-fail on this one as it really is implementation dependent
2833 * though we're interested in feedback, hence the warning.
2834 */
2835 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2836 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2837 static int warn_fail;
2838
Willy Tarreau18515722021-04-06 11:57:41 +02002839 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002840 ha_warning("Failed to disable forks, please report to developers with detailed "
2841 "information about your operating system. You can silence this warning "
2842 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2843 }
2844 }
2845#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002846 run_poll_loop();
2847
2848 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2849 ptdf->fct();
2850
Willy Tarreau082b6282019-05-22 14:42:12 +02002851 list_for_each_entry(ptff, &per_thread_free_list, list)
2852 ptff->fct();
2853
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002854#ifdef USE_THREAD
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002855 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002856 if (tid > 0)
2857 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002858#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002859 return NULL;
2860}
Christopher Faulet1d17c102017-08-29 15:38:48 +02002861
William Dauchyf9af9d72019-11-17 15:47:16 +01002862/* set uid/gid depending on global settings */
2863static void set_identity(const char *program_name)
2864{
2865 if (global.gid) {
2866 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
2867 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
2868 " without 'uid'/'user' is generally useless.\n", program_name);
2869
2870 if (setgid(global.gid) == -1) {
2871 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
2872 protocol_unbind_all();
2873 exit(1);
2874 }
2875 }
2876
2877 if (global.uid && setuid(global.uid) == -1) {
2878 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
2879 protocol_unbind_all();
2880 exit(1);
2881 }
2882}
2883
Willy Tarreaubaaee002006-06-26 02:48:02 +02002884int main(int argc, char **argv)
2885{
2886 int err, retry;
2887 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02002888 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02002889 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
2890
2891 /* Catch forced CFLAGS that miss 2-complement integer overflow */
2892 if (intovf + 0x7FFFFFFF >= intovf) {
2893 fprintf(stderr,
2894 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
2895 "The source code was miscompiled by the compiler, which usually indicates that\n"
2896 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
2897 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
2898 "and INSTALL files to decide on the best way to pass your local build options.\n"
2899 "\nBuild options :"
2900#ifdef BUILD_TARGET
2901 "\n TARGET = " BUILD_TARGET
2902#endif
2903#ifdef BUILD_CPU
2904 "\n CPU = " BUILD_CPU
2905#endif
2906#ifdef BUILD_CC
2907 "\n CC = " BUILD_CC
2908#endif
2909#ifdef BUILD_CFLAGS
2910 "\n CFLAGS = " BUILD_CFLAGS
2911#endif
2912#ifdef BUILD_OPTIONS
2913 "\n OPTIONS = " BUILD_OPTIONS
2914#endif
2915#ifdef BUILD_DEBUG
2916 "\n DEBUG = " BUILD_DEBUG
2917#endif
2918 "\n\n");
2919 return 1;
2920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002921
Olivier Houchard5fa300d2018-02-03 15:15:21 +01002922 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01002923
Willy Tarreaubf696402019-03-01 10:09:28 +01002924 /* take a copy of initial limits before we possibly change them */
2925 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02002926
2927 if (limit.rlim_max == RLIM_INFINITY)
2928 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01002929 rlim_fd_cur_at_boot = limit.rlim_cur;
2930 rlim_fd_max_at_boot = limit.rlim_max;
2931
Willy Tarreau5794fb02018-11-25 18:43:29 +01002932 /* process all initcalls in order of potential dependency */
2933 RUN_INITCALLS(STG_PREPARE);
2934 RUN_INITCALLS(STG_LOCK);
Willy Tarreau3ebe4d92022-02-18 14:51:49 +01002935 RUN_INITCALLS(STG_REGISTER);
Willy Tarreau34527d52022-02-17 17:45:58 +01002936
2937 /* now's time to initialize early boot variables */
2938 init_early(argc, argv);
2939
Willy Tarreau18f96d02022-02-23 17:25:00 +01002940 /* handles argument parsing */
2941 init_args(argc, argv);
2942
Willy Tarreau5794fb02018-11-25 18:43:29 +01002943 RUN_INITCALLS(STG_ALLOC);
2944 RUN_INITCALLS(STG_POOL);
Willy Tarreau5794fb02018-11-25 18:43:29 +01002945 RUN_INITCALLS(STG_INIT);
2946
Willy Tarreau34527d52022-02-17 17:45:58 +01002947 /* this is the late init where the config is parsed */
Emeric Bruncf20bf12010-10-22 16:06:11 +02002948 init(argc, argv);
Willy Tarreau34527d52022-02-17 17:45:58 +01002949
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002950 signal_register_fct(SIGQUIT, dump, SIGQUIT);
2951 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
2952 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02002953 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002954
Willy Tarreaue437c442010-03-17 18:02:46 +01002955 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
2956 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
2957 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002958 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002959 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002960
Willy Tarreaudc23a922011-02-16 11:10:36 +01002961 /* ulimits */
2962 if (!global.rlimit_nofile)
2963 global.rlimit_nofile = global.maxsock;
2964
2965 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01002966 limit.rlim_cur = global.rlimit_nofile;
2967 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
2968
Willy Tarreaudc23a922011-02-16 11:10:36 +01002969 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02002970 getrlimit(RLIMIT_NOFILE, &limit);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002971 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2972 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
2973 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002974 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002975 }
2976 else {
2977 /* try to set it to the max possible at least */
2978 limit.rlim_cur = limit.rlim_max;
2979 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
2980 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02002981
William Dauchya5194602020-03-28 19:29:58 +01002982 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002983 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
2984 global.rlimit_nofile = limit.rlim_cur;
2985 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01002986 }
2987 }
2988
2989 if (global.rlimit_memmax) {
2990 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01002991 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01002992#ifdef RLIMIT_AS
2993 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002994 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2995 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2996 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002997 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002998 }
2999 else
William Dauchya5194602020-03-28 19:29:58 +01003000 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003001 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003002 }
3003#else
3004 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003005 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3006 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3007 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003008 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003009 }
3010 else
William Dauchya5194602020-03-28 19:29:58 +01003011 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003012 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003013 }
3014#endif
3015 }
3016
William Lallemandf82afbb2022-01-07 18:19:42 +01003017 /* Try to get the listeners FD from the previous process using
3018 * _getsocks on the stat socket, it must never been done in wait mode
3019 * and check mode
3020 */
3021 if (old_unixsocket &&
3022 !(global.mode & (MODE_MWORKER_WAIT|MODE_CHECK|MODE_CHECK_CONDITION))) {
William Lallemand85b0bd92017-06-01 17:38:53 +02003023 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02003024 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003025 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02003026 if (!(global.mode & MODE_MWORKER))
3027 exit(1);
3028 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02003029 }
3030 }
William Lallemand85b0bd92017-06-01 17:38:53 +02003031
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 /* We will loop at most 100 times with 10 ms delay each time.
3033 * That's at most 1 second. We only send a signal to old pids
3034 * if we cannot grab at least one port.
3035 */
3036 retry = MAX_START_RETRIES;
3037 err = ERR_NONE;
3038 while (retry >= 0) {
3039 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003040 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003041 /* exit the loop on no error or fatal error */
3042 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003043 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003044 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003045 break;
3046
3047 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3048 * listening sockets. So on those platforms, it would be wiser to
3049 * simply send SIGUSR1, which will not be undoable.
3050 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003051 if (tell_old_pids(SIGTTOU) == 0) {
3052 /* no need to wait if we can't contact old pids */
3053 retry = 0;
3054 continue;
3055 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056 /* give some time to old processes to stop listening */
3057 w.tv_sec = 0;
3058 w.tv_usec = 10*1000;
3059 select(0, NULL, NULL, NULL, &w);
3060 retry--;
3061 }
3062
Willy Tarreaue91bff22020-09-02 11:11:43 +02003063 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003064 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003065 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003066 if (retry != MAX_START_RETRIES && nb_oldpids) {
3067 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003068 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003069 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003070 exit(1);
3071 }
3072
William Lallemand944e6192018-11-21 15:48:31 +01003073 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003074 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075 /* Note: we don't have to send anything to the old pids because we
3076 * never stopped them. */
3077 exit(1);
3078 }
3079
Willy Tarreaue91bff22020-09-02 11:11:43 +02003080 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003081 * the previous process gave us, we don't need them anymore
3082 */
Willy Tarreaub5101162022-01-28 18:28:18 +01003083 sock_drop_unused_old_sockets();
Willy Tarreaudd815982007-10-16 12:25:14 +02003084
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003086 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3087 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003088
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089 /* MODE_QUIET can inhibit alerts and warnings below this line */
3090
PiBa-NL149a81a2017-12-25 21:03:31 +01003091 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3092 /* either stdin/out/err are already closed or should stay as they are. */
3093 if ((global.mode & MODE_DAEMON)) {
3094 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3095 global.mode &= ~MODE_VERBOSE;
3096 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3097 }
3098 } else {
3099 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3100 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003101 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003102 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 }
3104
3105 /* open log & pid files before the chroot */
William Lallemand7b820a62022-02-14 09:02:14 +01003106 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) &&
3107 !(global.mode & MODE_MWORKER_WAIT) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 unlink(global.pidfile);
3109 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3110 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003111 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 if (nb_oldpids)
3113 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003114 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003115 exit(1);
3116 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003117 }
3118
Willy Tarreaub38651a2007-03-24 17:24:39 +01003119 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003120 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3121 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003122 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003123 exit(1);
3124 }
3125
Jackie Tapia749f74c2020-07-22 18:59:40 -05003126 /* If the user is not root, we'll still let them try the configuration
3127 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003128 */
3129 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003130 ha_warning("[%s.main()] Some options which require full privileges"
3131 " might not work well.\n"
3132 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003133
William Lallemand095ba4c2017-06-01 17:38:50 +02003134 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3135
3136 /* chroot if needed */
3137 if (global.chroot != NULL) {
3138 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003139 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003140 if (nb_oldpids)
3141 tell_old_pids(SIGTTIN);
3142 protocol_unbind_all();
3143 exit(1);
3144 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003145 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003146 }
3147
William Lallemand944e6192018-11-21 15:48:31 +01003148 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003149 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150
William Lallemand27edc4b2019-05-07 17:49:33 +02003151 /* send a SIGTERM to workers who have a too high reloads number */
3152 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3153 mworker_kill_max_reloads(SIGTERM);
3154
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 /* Note that any error at this stage will be fatal because we will not
3156 * be able to restart the old pids.
3157 */
3158
William Dauchyf9af9d72019-11-17 15:47:16 +01003159 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3160 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003161
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 /* check ulimits */
3163 limit.rlim_cur = limit.rlim_max = 0;
3164 getrlimit(RLIMIT_NOFILE, &limit);
3165 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003166 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3167 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3168 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3169 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3170 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003171 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003172 }
3173 else
3174 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003175 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003176 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3177 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003178 }
3179
William Lallemand944e6192018-11-21 15:48:31 +01003180 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003181 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003182 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003183 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184
William Lallemand095ba4c2017-06-01 17:38:50 +02003185 /*
3186 * if daemon + mworker: must fork here to let a master
3187 * process live in background before forking children
3188 */
William Lallemand73b85e72017-06-01 17:38:51 +02003189
3190 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3191 && (global.mode & MODE_MWORKER)
3192 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003193 ret = fork();
3194 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003195 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003196 protocol_unbind_all();
3197 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003198 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003199 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003200 } else /* change the process group ID in the child (master process) */
3201 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003202 }
William Lallemande20b6a62017-06-01 17:38:55 +02003203
William Lallemande20b6a62017-06-01 17:38:55 +02003204
William Lallemanddeed7802017-11-06 11:00:04 +01003205 /* if in master-worker mode, write the PID of the father */
3206 if (global.mode & MODE_MWORKER) {
3207 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003208 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003209 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003210 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003211 }
3212
Willy Tarreaubaaee002006-06-26 02:48:02 +02003213 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003214 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003215 if (global.mode & MODE_MWORKER)
3216 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003217
3218 ret = fork();
3219 if (ret < 0) {
3220 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3221 protocol_unbind_all();
3222 exit(1); /* there has been an error */
3223 }
3224 else if (ret == 0) { /* child breaks here */
Willy Tarreau3c032f22021-07-21 10:17:02 +02003225 /* This one must not be exported, it's internal! */
3226 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003227 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003228 }
3229 else { /* parent here */
3230 in_parent = 1;
3231
William Lallemand944e6192018-11-21 15:48:31 +01003232 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3233 char pidstr[100];
3234 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003235 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003236 }
3237 if (global.mode & MODE_MWORKER) {
3238 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003239
William Lallemand5d71a6b2021-11-09 15:25:31 +01003240 ha_notice("New worker (%d) forked\n", ret);
William Lallemand944e6192018-11-21 15:48:31 +01003241 /* find the right mworker_proc */
3242 list_for_each_entry(child, &proc_list, list) {
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003243 if (child->reloads == 0 && child->options & PROC_O_TYPE_WORKER) {
William Lallemand944e6192018-11-21 15:48:31 +01003244 child->timestamp = now.tv_sec;
3245 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003246 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003247 break;
3248 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003249 }
3250 }
William Lallemand944e6192018-11-21 15:48:31 +01003251 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003252
William Lallemand944e6192018-11-21 15:48:31 +01003253 } else {
3254 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003255 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003257
3258#ifdef USE_CPU_AFFINITY
Willy Tarreau44ea6312021-06-15 08:57:56 +02003259 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 +02003260
David CARLIERdf91cbd2022-01-06 18:53:50 +00003261#if defined(CPUSET_USE_CPUSET) || defined(__DragonFly__)
David CARLIERbb10dad2022-01-08 09:59:38 +00003262 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003263 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
David CARLIERdf91cbd2022-01-06 18:53:50 +00003264#elif defined(__FreeBSD__)
David CARLIERbb10dad2022-01-08 09:59:38 +00003265 struct hap_cpuset *set = &cpu_map.proc;
David CARLIERdf91cbd2022-01-06 18:53:50 +00003266 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003267#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003268 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003269#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003270 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003271 if (pidfd >= 0) {
3272 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3273 close(pidfd);
3274 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003275
3276 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003277 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003278
Willy Tarreaud67ff342021-06-15 07:58:09 +02003279 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003280 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
William Lallemandfab0fdc2021-11-09 18:01:22 +01003281 master = 1;
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003282
3283 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3284 (global.mode & MODE_DAEMON)) {
3285 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003286 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3287 stdio_quiet(-1);
3288
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003289 global.mode &= ~MODE_VERBOSE;
3290 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003291 }
3292
William Lallemandfab0fdc2021-11-09 18:01:22 +01003293 if (global.mode & MODE_MWORKER_WAIT) {
3294 /* only the wait mode handles the master CLI */
3295 mworker_loop();
3296 } else {
3297
3298 /* if not in wait mode, reload in wait mode to free the memory */
William Lallemand836bda22021-11-09 18:16:47 +01003299 ha_notice("Loading success.\n");
William Lallemand68836742021-11-10 10:49:06 +01003300 proc_self->failedreloads = 0; /* reset the number of failure */
William Lallemandfab0fdc2021-11-09 18:01:22 +01003301 mworker_reexec_waitmode();
3302 }
William Lallemand1499b9b2017-06-07 15:04:47 +02003303 /* should never get there */
3304 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003305 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003306#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003307 ssl_free_dh();
3308#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003309 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003310 }
3311
William Lallemandcb11fd22017-06-01 17:38:52 +02003312 /* child must never use the atexit function */
3313 atexit_flag = 0;
3314
William Lallemandbc193052018-09-11 10:06:26 +02003315 /* close useless master sockets */
3316 if (global.mode & MODE_MWORKER) {
3317 struct mworker_proc *child, *it;
3318 master = 0;
3319
William Lallemand309dc9a2018-10-26 14:47:45 +02003320 mworker_cli_proxy_stop();
3321
William Lallemandbc193052018-09-11 10:06:26 +02003322 /* free proc struct of other processes */
3323 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003324 /* close the FD of the master side for all
3325 * workers, we don't need to close the worker
3326 * side of other workers since it's done with
3327 * the bind_proc */
William Lallemand7e018782022-01-28 21:56:24 +01003328 if (child->ipc_fd[0] >= 0) {
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003329 close(child->ipc_fd[0]);
William Lallemand7e018782022-01-28 21:56:24 +01003330 child->ipc_fd[0] = -1;
3331 }
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003332 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandce83b4a2018-10-26 14:47:30 +02003333 child->reloads == 0) {
3334 /* keep this struct if this is our pid */
3335 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003336 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003337 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003338 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003339 mworker_free_child(child);
3340 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003341 }
3342 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003343
William Lallemande1340412017-12-28 16:09:36 +01003344 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3345 devnullfd = open("/dev/null", O_RDWR, 0);
3346 if (devnullfd < 0) {
3347 ha_alert("Cannot open /dev/null\n");
3348 exit(EXIT_FAILURE);
3349 }
3350 }
3351
William Lallemand095ba4c2017-06-01 17:38:50 +02003352 /* Must chroot and setgid/setuid in the children */
3353 /* chroot if needed */
3354 if (global.chroot != NULL) {
3355 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003356 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003357 if (nb_oldpids)
3358 tell_old_pids(SIGTTIN);
3359 protocol_unbind_all();
3360 exit(1);
3361 }
3362 }
3363
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003364 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003365 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003366
William Lallemand7f80eb22017-05-26 18:19:55 +02003367 /* pass through every cli socket, and check if it's bound to
3368 * the current process and if it exposes listeners sockets.
3369 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3370 * */
3371
Willy Tarreau4975d142021-03-13 11:00:33 +01003372 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003373 struct bind_conf *bind_conf;
3374
Willy Tarreau4975d142021-03-13 11:00:33 +01003375 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003376 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003377 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3378 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003379 }
3380 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003381 }
3382
William Lallemand2e8fad92018-11-13 16:18:23 +01003383 /*
3384 * This is only done in daemon mode because we might want the
3385 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3386 * we should now close the 3 first FDs to ensure that we can
3387 * detach from the TTY. We MUST NOT do it in other cases since
3388 * it would have already be done, and 0-2 would have been
3389 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003391 if ((global.mode & MODE_DAEMON) &&
3392 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003393 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003394 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003395 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3397 }
3398 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003399 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3400 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003401 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 }
3403
William Dauchye039f262019-11-17 15:47:15 +01003404 /* try our best to re-enable core dumps depending on system capabilities.
3405 * What is addressed here :
3406 * - remove file size limits
3407 * - remove core size limits
3408 * - mark the process dumpable again if it lost it due to user/group
3409 */
3410 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3411 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3412
3413#if defined(RLIMIT_FSIZE)
3414 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3415 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3416 ha_alert("[%s.main()] Failed to set the raise the maximum "
3417 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003418 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003419 }
3420 else
3421 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003422 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003423 }
3424#endif
3425
3426#if defined(RLIMIT_CORE)
3427 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3428 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3429 ha_alert("[%s.main()] Failed to set the raise the core "
3430 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003431 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003432 }
3433 else
3434 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003435 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003436 }
3437#endif
3438
3439#if defined(USE_PRCTL)
3440 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3441 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3442 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003443#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003444 {
3445 int traceable = PROC_TRACE_CTL_ENABLE;
3446 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3447 ha_warning("[%s.main()] Failed to set the traceable flag, "
3448 "no core will be dumped.\n", argv[0]);
3449 }
William Dauchye039f262019-11-17 15:47:15 +01003450#endif
3451 }
3452
Christopher Faulete3a5e352017-10-24 13:53:54 +02003453 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003454 reset_usermsgs_ctx();
3455
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003456 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003457 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003458
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003459 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003460 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003461
3462 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003463 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003464
3465 /* wait for all threads to terminate */
3466 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003467
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003468 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003469}
3470
Willy Tarreaubaaee002006-06-26 02:48:02 +02003471/*
3472 * Local variables:
3473 * c-indent-level: 8
3474 * c-basic-offset: 8
3475 * End:
3476 */