blob: 3c04c58e6eece035ef42c5320b196cb9351e2dc1 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
Willy Tarreaua5357cd2021-05-09 06:14:25 +02002 * HAProxy : High Availability-enabled HTTP/TCP proxy
Willy Tarreau421ed392021-01-06 17:41:32 +01003 * Copyright 2000-2021 Willy Tarreau <willy@haproxy.org>.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
Ilya Shipitsin46a030c2020-07-05 16:36:08 +050010 * Please refer to RFC7230 - RFC7235 information about HTTP protocol, and
11 * RFC6265 for information about cookies usage. More generally, the IETF HTTP
Willy Tarreaubaaee002006-06-26 02:48:02 +020012 * Working Group's web site should be consulted for protocol related changes :
13 *
14 * http://ftp.ics.uci.edu/pub/ietf/http/
15 *
16 * Pending bugs (may be not fixed because never reproduced) :
17 * - solaris only : sometimes, an HTTP proxy with only a dispatch address causes
18 * the proxy to terminate (no core) if the client breaks the connection during
19 * the response. Seen on 1.1.8pre4, but never reproduced. May not be related to
20 * the snprintf() bug since requests were simple (GET / HTTP/1.0), but may be
21 * related to missing setsid() (fixed in 1.1.15)
22 * - a proxy with an invalid config will prevent the startup even if disabled.
23 *
24 * ChangeLog has moved to the CHANGELOG file.
25 *
Willy Tarreaubaaee002006-06-26 02:48:02 +020026 */
27
David Carlier7ece0962015-12-08 21:43:09 +000028#define _GNU_SOURCE
Willy Tarreaubaaee002006-06-26 02:48:02 +020029#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <string.h>
33#include <ctype.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020034#include <dirent.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020035#include <sys/stat.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <sys/time.h>
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <netinet/tcp.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42#include <netdb.h>
43#include <fcntl.h>
44#include <errno.h>
45#include <signal.h>
46#include <stdarg.h>
47#include <sys/resource.h>
Tim Duesterhusdfad6a42020-04-18 16:02:47 +020048#include <sys/utsname.h>
Marc-Antoine Perennou992709b2013-02-12 10:53:52 +010049#include <sys/wait.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <time.h>
51#include <syslog.h>
Michael Schererab012dd2013-01-12 18:35:19 +010052#include <grp.h>
Willy Tarreaud10385a2021-10-06 22:22:40 +020053
Willy Tarreau5e03dfa2021-10-06 22:53:51 +020054#ifdef USE_THREAD
55#include <pthread.h>
56#endif
57
Willy Tarreaufc6c0322012-11-16 16:12:27 +010058#ifdef USE_CPU_AFFINITY
Willy Tarreaufc6c0322012-11-16 16:12:27 +010059#include <sched.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000060#if defined(__FreeBSD__) || defined(__DragonFly__)
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020061#include <sys/param.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000062#ifdef __FreeBSD__
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020063#include <sys/cpuset.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000064#endif
David Carlier5e4c8e22019-09-13 05:12:58 +010065#endif
Willy Tarreaufc6c0322012-11-16 16:12:27 +010066#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020067
Willy Tarreau636848a2019-04-15 19:38:50 +020068#if defined(USE_PRCTL)
69#include <sys/prctl.h>
70#endif
71
devnexen@gmail.com21185972021-08-21 09:13:10 +010072#if defined(USE_PROCCTL)
73#include <sys/procctl.h>
74#endif
75
Willy Tarreaubaaee002006-06-26 02:48:02 +020076#ifdef DEBUG_FULL
77#include <assert.h>
78#endif
Tim Duesterhusd6942c82017-11-20 15:58:35 +010079#if defined(USE_SYSTEMD)
80#include <systemd/sd-daemon.h>
81#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020082
Willy Tarreau6c3a6812020-03-06 18:57:15 +010083#include <import/sha1.h>
84
Willy Tarreaub2551052020-06-09 09:07:15 +020085#include <haproxy/acl.h>
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +010086#include <haproxy/action.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020087#include <haproxy/activity.h>
88#include <haproxy/api.h>
89#include <haproxy/arg.h>
90#include <haproxy/auth.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020091#include <haproxy/base64.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020092#include <haproxy/capture-t.h>
Willy Tarreau66243b42021-07-16 15:39:28 +020093#include <haproxy/cfgcond.h>
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +020094#include <haproxy/cfgdiag.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020095#include <haproxy/cfgparse.h>
Willy Tarreauc13ed532020-06-02 10:22:45 +020096#include <haproxy/chunk.h>
Willy Tarreau83487a82020-06-04 20:19:54 +020097#include <haproxy/cli.h>
Willy Tarreau55542642021-10-08 09:33:24 +020098#include <haproxy/clock.h>
Willy Tarreau7ea393d2020-06-04 18:02:10 +020099#include <haproxy/connection.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200100#ifdef USE_CPU_AFFINITY
Amaury Denoyelle982fb532021-04-21 18:39:58 +0200101#include <haproxy/cpuset.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200102#endif
Willy Tarreaueb92deb2020-06-04 10:53:16 +0200103#include <haproxy/dns.h>
Willy Tarreau2741c8c2020-06-02 11:28:02 +0200104#include <haproxy/dynbuf.h>
Willy Tarreau8d366972020-05-27 16:10:29 +0200105#include <haproxy/errors.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200106#include <haproxy/fd.h>
Willy Tarreauc7babd82020-06-04 21:29:29 +0200107#include <haproxy/filters.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200108#include <haproxy/global.h>
Willy Tarreau86416052020-06-04 09:20:54 +0200109#include <haproxy/hlua.h>
Willy Tarreauc761f842020-06-04 11:40:28 +0200110#include <haproxy/http_rules.h>
Willy Tarreau853b2972020-05-27 18:01:47 +0200111#include <haproxy/list.h>
Willy Tarreau213e9902020-06-04 14:58:24 +0200112#include <haproxy/listener.h>
Willy Tarreauaeed4a82020-06-04 22:01:04 +0200113#include <haproxy/log.h>
Willy Tarreaub5abe5b2020-06-04 14:07:37 +0200114#include <haproxy/mworker.h>
Willy Tarreau7a00efb2020-06-02 17:02:59 +0200115#include <haproxy/namespace.h>
Willy Tarreau6131d6a2020-06-02 16:48:09 +0200116#include <haproxy/net_helper.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +0200117#include <haproxy/openssl-compat.h>
Willy Tarreau225a90a2020-06-04 15:06:28 +0200118#include <haproxy/pattern.h>
Willy Tarreau3c2a7c22020-06-04 18:38:21 +0200119#include <haproxy/peers.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200120#include <haproxy/pool.h>
121#include <haproxy/protocol.h>
Willy Tarreaubf3b06b2020-08-26 10:23:40 +0200122#include <haproxy/proto_tcp.h>
Willy Tarreaua264d962020-06-04 22:29:18 +0200123#include <haproxy/proxy.h>
Willy Tarreau7cd8b6e2020-06-02 17:32:26 +0200124#include <haproxy/regex.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200125#include <haproxy/sample.h>
Willy Tarreau1e56f922020-06-04 23:20:13 +0200126#include <haproxy/server.h>
Willy Tarreau48d25b32020-06-04 18:58:52 +0200127#include <haproxy/session.h>
Willy Tarreau3727a8a2020-06-04 17:37:26 +0200128#include <haproxy/signal.h>
Willy Tarreau063d47d2020-08-28 16:29:53 +0200129#include <haproxy/sock.h>
Willy Tarreau25140cc2020-08-28 15:40:33 +0200130#include <haproxy/sock_inet.h>
Willy Tarreau209108d2020-06-04 20:30:20 +0200131#include <haproxy/ssl_sock.h>
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +0200132#include <haproxy/stats-t.h>
Willy Tarreaudfd3de82020-06-04 23:46:14 +0200133#include <haproxy/stream.h>
Willy Tarreaucea0e1b2020-06-04 17:25:40 +0200134#include <haproxy/task.h>
Willy Tarreau3f567e42020-05-28 15:29:19 +0200135#include <haproxy/thread.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200136#include <haproxy/time.h>
137#include <haproxy/tools.h>
138#include <haproxy/uri_auth-t.h>
Willy Tarreaua1718922020-06-04 16:25:31 +0200139#include <haproxy/vars.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200140#include <haproxy/version.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200141
Willy Tarreaubaaee002006-06-26 02:48:02 +0200142
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100143/* array of init calls for older platforms */
144DECLARE_INIT_STAGES;
145
Willy Tarreauf4596402021-04-10 16:53:05 +0200146/* create a read_mostly section to hold variables which are accessed a lot
147 * but which almost never change. The purpose is to isolate them in their
148 * own cache lines where they don't risk to be perturbated by write accesses
149 * to neighbor variables. We need to create an empty aligned variable for
150 * this. The fact that the variable is of size zero means that it will be
151 * eliminated at link time if no other variable uses it, but alignment will
152 * be respected.
153 */
154empty_t __read_mostly_align HA_SECTION("read_mostly") ALIGNED(64);
155
Willy Tarreauf0d3b732021-05-06 16:30:32 +0200156#ifdef BUILD_FEATURES
157const char *build_features = BUILD_FEATURES;
158#else
159const char *build_features = "";
160#endif
161
Willy Tarreau477ecd82010-01-03 21:12:30 +0100162/* list of config files */
163static struct list cfg_cfgfiles = LIST_HEAD_INIT(cfg_cfgfiles);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200164int pid; /* current process id */
165
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100166volatile unsigned long sleeping_thread_mask = 0; /* Threads that are about to sleep in poll() */
Willy Tarreau4b3f27b2020-03-12 17:28:01 +0100167volatile unsigned long stopping_thread_mask = 0; /* Threads acknowledged stopping */
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100168
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169/* global options */
170struct global global = {
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100171 .hard_stop_after = TICK_ETERNITY,
Amaury Denoyelle0f50cb92021-03-26 18:50:33 +0100172 .numa_cpu_mapping = 1,
Willy Tarreau149ab772019-01-26 14:27:06 +0100173 .nbthread = 0,
William Lallemand5f232402012-04-05 18:02:55 +0200174 .req_count = 0,
William Lallemand0f99e342011-10-12 17:50:54 +0200175 .logsrvs = LIST_HEAD_INIT(global.logsrvs),
William Lallemand9d5f5482012-11-07 16:12:57 +0100176 .maxzlibmem = 0,
William Lallemandd85f9172012-11-09 17:05:39 +0100177 .comp_rate_lim = 0,
Emeric Brun850efd52014-01-29 12:24:34 +0100178 .ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED,
Emeric Bruned760922010-10-22 17:59:25 +0200179 .unix_bind = {
180 .ux = {
181 .uid = -1,
182 .gid = -1,
183 .mode = 0,
184 }
185 },
Willy Tarreau27a674e2009-08-17 07:23:33 +0200186 .tune = {
Willy Tarreau7ac908b2019-02-27 12:02:18 +0100187 .options = GTUNE_LISTENER_MQ,
Willy Tarreauc77d3642018-12-12 06:19:42 +0100188 .bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
Christopher Faulet546c4692020-01-22 14:31:21 +0100189 .maxrewrite = MAXREWRITE,
Willy Tarreaua24adf02014-11-27 01:11:56 +0100190 .reserved_bufs = RESERVED_BUFS,
Willy Tarreauf3045d22015-04-29 16:24:50 +0200191 .pattern_cache = DEFAULT_PAT_LRU_SIZE,
Olivier Houchard88698d92019-04-16 19:07:22 +0200192 .pool_low_ratio = 20,
193 .pool_high_ratio = 25,
Christopher Faulet41ba36f2019-07-19 09:36:45 +0200194 .max_http_hdr = MAX_HTTP_HDR,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200195#ifdef USE_OPENSSL
Emeric Brun46635772012-11-14 11:32:56 +0100196 .sslcachesize = SSLCACHESIZE,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200197#endif
William Lallemandf3747832012-11-09 12:33:10 +0100198 .comp_maxlevel = 1,
Willy Tarreau7e312732014-02-12 16:35:14 +0100199#ifdef DEFAULT_IDLE_TIMER
200 .idle_timer = DEFAULT_IDLE_TIMER,
201#else
202 .idle_timer = 1000, /* 1 second */
203#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200204 },
Emeric Brun76d88952012-10-05 15:47:31 +0200205#ifdef USE_OPENSSL
206#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200207 .maxsslconn = DEFAULT_MAXSSLCONN,
208#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200209#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210 /* others NULL OK */
211};
212
213/*********************************************************************/
214
215int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100216int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200217int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100218int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100219int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100220int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500222/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 * or kill. We will send them a signal every 10 ms until we can bind to all
224 * our ports. With 200 retries, that's about 2 seconds.
225 */
226#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227static int *oldpids = NULL;
228static int oldpids_sig; /* use USR1 or TERM */
229
Olivier Houchardf73629d2017-04-05 22:33:04 +0200230/* Path to the unix socket we use to retrieve listener sockets from the old process */
231static const char *old_unixsocket;
232
William Lallemand85b0bd92017-06-01 17:38:53 +0200233static char *cur_unixsocket = NULL;
234
William Lallemandcb11fd22017-06-01 17:38:52 +0200235int atexit_flag = 0;
236
Willy Tarreaubb545b42010-08-25 12:58:59 +0200237int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238const int zero = 0;
239const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200240const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100242char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200243char *localpeer = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
William Lallemand00417412020-06-05 14:08:41 +0200245static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200246
William Lallemandbc193052018-09-11 10:06:26 +0200247struct list proc_list = LIST_HEAD_INIT(proc_list);
248
249int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100250unsigned int rlim_fd_cur_at_boot = 0;
251unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200252
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100253/* per-boot randomness */
254unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
255
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200256/* takes the thread config in argument or NULL for any thread */
William Lallemandb3f2be32018-09-11 10:06:18 +0200257static void *run_thread_poll_loop(void *data);
258
Willy Tarreauff055502014-04-28 22:27:06 +0200259/* bitfield of a few warnings to emit just once (WARN_*) */
260unsigned int warned = 0;
261
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200262/* set if experimental features have been used for the current process */
263static unsigned int tainted = 0;
264
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200265unsigned int experimental_directives_allowed = 0;
266
267int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
268 char **errmsg)
269{
270 if (kw->flags & KWF_EXPERIMENTAL) {
271 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200272 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 +0200273 file, linenum, kw->kw);
274 return 1;
275 }
276 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
277 }
278
279 return 0;
280}
281
William Lallemande7361152018-10-26 14:47:36 +0200282/* master CLI configuration (-S flag) */
283struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100284
285/* These are strings to be reported in the output of "haproxy -vv". They may
286 * either be constants (in which case must_free must be zero) or dynamically
287 * allocated strings to pass to free() on exit, and in this case must_free
288 * must be non-zero.
289 */
290struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
291struct build_opts_str {
292 struct list list;
293 const char *str;
294 int must_free;
295};
296
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297/*********************************************************************/
298/* general purpose functions ***************************************/
299/*********************************************************************/
300
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100301/* used to register some build option strings at boot. Set must_free to
302 * non-zero if the string must be freed upon exit.
303 */
304void hap_register_build_opts(const char *str, int must_free)
305{
306 struct build_opts_str *b;
307
308 b = calloc(1, sizeof(*b));
309 if (!b) {
310 fprintf(stderr, "out of memory\n");
311 exit(1);
312 }
313 b->str = str;
314 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200315 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100316}
317
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200318#define VERSION_MAX_ELTS 7
319
320/* This function splits an haproxy version string into an array of integers.
321 * The syntax of the supported version string is the following:
322 *
323 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
324 *
325 * This validates for example:
326 * 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
327 * 2.4-dev18-f6818d-20
328 *
329 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
330 * one fixed place in the array. The tags take a numeric value called <e> which
331 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
332 * considered as zero (henxe 1.5 and 1.5.0 are the same).
333 *
334 * The resulting values are:
335 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
336 * 1.2.1 1, 2, 1, 0, 3, 0, 0
337 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
338 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
339 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
340 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
341 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
342 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
343 *
344 * The function returns non-zero if the conversion succeeded, or zero if it
345 * failed.
346 */
347int split_version(const char *version, unsigned int *value)
348{
349 const char *p, *s;
350 char *error;
351 int nelts;
352
353 /* Initialize array with zeroes */
354 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
355 value[nelts] = 0;
356 value[4] = 3;
357
358 p = version;
359
360 /* If the version number is empty, return false */
361 if (*p == '\0')
362 return 0;
363
364 /* Convert first number <a> */
365 value[0] = strtol(p, &error, 10);
366 p = error + 1;
367 if (*error == '\0')
368 return 1;
369 if (*error == '-')
370 goto split_version_tag;
371 if (*error != '.')
372 return 0;
373
374 /* Convert first number <b> */
375 value[1] = strtol(p, &error, 10);
376 p = error + 1;
377 if (*error == '\0')
378 return 1;
379 if (*error == '-')
380 goto split_version_tag;
381 if (*error != '.')
382 return 0;
383
384 /* Convert first number <c> */
385 value[2] = strtol(p, &error, 10);
386 p = error + 1;
387 if (*error == '\0')
388 return 1;
389 if (*error == '-')
390 goto split_version_tag;
391 if (*error != '.')
392 return 0;
393
394 /* Convert first number <d> */
395 value[3] = strtol(p, &error, 10);
396 p = error + 1;
397 if (*error == '\0')
398 return 1;
399 if (*error != '-')
400 return 0;
401
402 split_version_tag:
403 /* Check for commit number */
404 if (*p >= '0' && *p <= '9')
405 goto split_version_commit;
406
407 /* Read tag */
408 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
409 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
410 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
411 else
412 goto split_version_commit;
413
414 /* Convert tag number */
415 value[5] = strtol(p, &error, 10);
416 p = error + 1;
417 if (*error == '\0')
418 return 1;
419 if (*error != '-')
420 return 0;
421
422 split_version_commit:
423 /* Search the last "-" */
424 s = strrchr(p, '-');
425 if (s) {
426 s++;
427 if (*s == '\0')
428 return 0;
429 value[6] = strtol(s, &error, 10);
430 if (*error != '\0')
431 value[6] = 0;
432 return 1;
433 }
434
435 /* convert the version */
436 value[6] = strtol(p, &error, 10);
437 if (*error != '\0')
438 value[6] = 0;
439
440 return 1;
441}
442
443/* This function compares the current haproxy version with an arbitrary version
444 * string. It returns:
445 * -1 : the version in argument is older than the current haproxy version
446 * 0 : the version in argument is the same as the current haproxy version
447 * 1 : the version in argument is newer than the current haproxy version
448 *
449 * Or some errors:
450 * -2 : the current haproxy version is not parsable
451 * -3 : the version in argument is not parsable
452 */
453int compare_current_version(const char *version)
454{
455 unsigned int loc[VERSION_MAX_ELTS];
456 unsigned int mod[VERSION_MAX_ELTS];
457 int i;
458
459 /* split versions */
460 if (!split_version(haproxy_version, loc))
461 return -2;
462 if (!split_version(version, mod))
463 return -3;
464
465 /* compare versions */
466 for (i = 0; i < VERSION_MAX_ELTS; i++) {
467 if (mod[i] < loc[i])
468 return -1;
469 else if (mod[i] > loc[i])
470 return 1;
471 }
472 return 0;
473}
474
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100475static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200476{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200477 struct utsname utsname;
478
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200479 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100480 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100481
482 if (strlen(PRODUCT_URL_BUGS) > 0) {
483 char base_version[20];
484 int dots = 0;
485 char *del;
486
487 /* only retrieve the base version without distro-specific extensions */
488 for (del = haproxy_version; *del; del++) {
489 if (*del == '.')
490 dots++;
491 else if (*del < '0' || *del > '9')
492 break;
493 }
494
495 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
496 if (dots < 2)
497 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
498 else
499 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
500 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200501
502 if (uname(&utsname) == 0) {
503 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
504 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200505}
506
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100507static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100508{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100509 struct build_opts_str *item;
510
Willy Tarreau7b066db2007-12-02 11:28:59 +0100511 printf("Build options :"
512#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100513 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100514#endif
515#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100516 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100517#endif
518#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100519 "\n CC = " BUILD_CC
520#endif
521#ifdef BUILD_CFLAGS
522 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100523#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100524#ifdef BUILD_OPTIONS
525 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100526#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100527#ifdef BUILD_DEBUG
528 "\n DEBUG = " BUILD_DEBUG
529#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100530#ifdef BUILD_FEATURES
531 "\n\nFeature list : " BUILD_FEATURES
532#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200533 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100534 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200535 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100536 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200537
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100538 list_for_each_entry(item, &build_opts_list, list) {
539 puts(item->str);
540 }
541
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100542 putchar('\n');
543
Willy Tarreaube5b6852009-10-03 18:57:08 +0200544 list_pollers(stdout);
545 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200546 list_mux_proto(stdout);
547 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100548 list_services(stdout);
549 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100550 list_filters(stdout);
551 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100552}
553
Willy Tarreaubaaee002006-06-26 02:48:02 +0200554/*
555 * This function prints the command line usage and exits
556 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100557static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200558{
559 display_version();
560 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200561 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200562 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200563 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100564 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200565 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreau6e064432012-05-08 15:40:42 +0200566 " -dM[<byte>] poisons memory with <byte> (defaults to 0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200568 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200569 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100570#if defined(USE_SYSTEMD)
571 " -Ws master-worker mode with systemd notify support.\n"
572#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200573 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200574 " -c check mode : only check config files and exit\n"
Maximilian Maderfc0cceb2021-06-06 00:50:22 +0200575 " -cc check condition : evaluate a condition and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100576 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 " -m limits the usable amount of memory (in MB)\n"
578 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200579 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580 " -p writes pids of all children to this file\n"
Willy Tarreaue5733232019-05-22 19:24:06 +0200581#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200582 " -de disables epoll() usage even when available\n"
583#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200584#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200585 " -dk disables kqueue() usage even when available\n"
586#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200587#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000588 " -dv disables event ports usage even when available\n"
589#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200590#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200591 " -dp disables poll() usage even when available\n"
592#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200593#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100594 " -dS disables splice usage (broken on old kernels)\n"
595#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200596#if defined(USE_GETADDRINFO)
597 " -dG disables getaddrinfo() usage\n"
598#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000599#if defined(SO_REUSEPORT)
600 " -dR disables SO_REUSEPORT usage\n"
601#endif
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100602 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100603 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200604 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200605 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200606 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200607 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200608 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200609 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100610 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200611 exit(1);
612}
613
614
615
616/*********************************************************************/
617/* more specific functions ***************************************/
618/*********************************************************************/
619
William Lallemand73b85e72017-06-01 17:38:51 +0200620/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
621 * pids the signal was correctly delivered to.
622 */
William Lallemande25473c2019-04-01 11:29:56 +0200623int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200624{
625 int p;
626 int ret = 0;
627 for (p = 0; p < nb_oldpids; p++)
628 if (kill(oldpids[p], sig) == 0)
629 ret++;
630 return ret;
631}
632
William Lallemand75ea0a02017-11-15 19:02:58 +0100633/*
William Lallemand73b85e72017-06-01 17:38:51 +0200634 * remove a pid forom the olpid array and decrease nb_oldpids
635 * return 1 pid was found otherwise return 0
636 */
637
638int delete_oldpid(int pid)
639{
640 int i;
641
642 for (i = 0; i < nb_oldpids; i++) {
643 if (oldpids[i] == pid) {
644 oldpids[i] = oldpids[nb_oldpids - 1];
645 oldpids[nb_oldpids - 1] = 0;
646 nb_oldpids--;
647 return 1;
648 }
649 }
650 return 0;
651}
652
William Lallemand85b0bd92017-06-01 17:38:53 +0200653
654static void get_cur_unixsocket()
655{
656 /* if -x was used, try to update the stat socket if not available anymore */
Willy Tarreau4975d142021-03-13 11:00:33 +0100657 if (global.cli_fe) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200658 struct bind_conf *bind_conf;
659
660 /* pass through all stats socket */
Willy Tarreau4975d142021-03-13 11:00:33 +0100661 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200662 struct listener *l;
663
664 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
665
Willy Tarreau37159062020-08-27 07:48:42 +0200666 if (l->rx.addr.ss_family == AF_UNIX &&
William Lallemand85b0bd92017-06-01 17:38:53 +0200667 (bind_conf->level & ACCESS_FD_LISTENERS)) {
668 const struct sockaddr_un *un;
669
Willy Tarreau37159062020-08-27 07:48:42 +0200670 un = (struct sockaddr_un *)&l->rx.addr;
William Lallemand85b0bd92017-06-01 17:38:53 +0200671 /* priority to old_unixsocket */
672 if (!cur_unixsocket) {
673 cur_unixsocket = strdup(un->sun_path);
674 } else {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100675 if (old_unixsocket && strcmp(un->sun_path, old_unixsocket) == 0) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200676 free(cur_unixsocket);
677 cur_unixsocket = strdup(old_unixsocket);
678 return;
679 }
680 }
681 }
682 }
683 }
684 }
685 if (!cur_unixsocket && old_unixsocket)
686 cur_unixsocket = strdup(old_unixsocket);
687}
688
William Lallemand73b85e72017-06-01 17:38:51 +0200689/*
690 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800691 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200692 */
William Lallemandfab0fdc2021-11-09 18:01:22 +0100693static void mworker_reexec()
William Lallemand73b85e72017-06-01 17:38:51 +0200694{
William Lallemand00417412020-06-05 14:08:41 +0200695 char **next_argv = NULL;
696 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200697 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200698 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200699 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100700 struct rlimit limit;
William Lallemand7c756a82018-11-26 11:53:40 +0100701 struct per_thread_deinit_fct *ptdf;
William Lallemand73b85e72017-06-01 17:38:51 +0200702
703 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100704#if defined(USE_SYSTEMD)
705 if (global.tune.options & GTUNE_USE_SYSTEMD)
706 sd_notify(0, "RELOADING=1");
707#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200708 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
709
William Lallemandbc193052018-09-11 10:06:26 +0200710 mworker_proc_list_to_env(); /* put the children description in the env */
711
William Lallemandc4810b82021-11-18 10:51:30 +0100712 /* ensure that we close correctly every listeners before reexecuting */
713 mworker_cleanlisteners();
714
William Lallemand7c756a82018-11-26 11:53:40 +0100715 /* during the reload we must ensure that every FDs that can't be
716 * reuse (ie those that are not referenced in the proc_list)
717 * are closed or they will leak. */
718
719 /* close the listeners FD */
720 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200721
722 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
723 /* close the poller FD and the thread waker pipe FD */
724 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
725 ptdf->fct();
726 if (fdtab)
727 deinit_pollers();
728 }
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500729#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200730 /* close random device FDs */
731 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100732#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100733
Willy Tarreau8dca1952019-03-01 10:21:55 +0100734 /* restore the initial FD limits */
735 limit.rlim_cur = rlim_fd_cur_at_boot;
736 limit.rlim_max = rlim_fd_max_at_boot;
737 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
738 getrlimit(RLIMIT_NOFILE, &limit);
739 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
740 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
741 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
742 }
743
William Lallemand73b85e72017-06-01 17:38:51 +0200744 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200745 while (old_argv[old_argc])
746 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200747
William Lallemand85b0bd92017-06-01 17:38:53 +0200748 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200749 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200750 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200751 if (next_argv == NULL)
752 goto alloc_error;
753
William Lallemand00417412020-06-05 14:08:41 +0200754 /* copy the program name */
755 next_argv[next_argc++] = old_argv[0];
756
757 /* insert the new options just after argv[0] in case we have a -- */
758
William Lallemand73b85e72017-06-01 17:38:51 +0200759 /* add -sf <PID>* to argv */
William Lallemand3f128872019-04-01 11:29:59 +0200760 if (mworker_child_nb() > 0) {
761 struct mworker_proc *child;
762
William Lallemand73b85e72017-06-01 17:38:51 +0200763 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200764
765 list_for_each_entry(child, &proc_list, list) {
William Lallemand677e2f22019-11-19 17:04:18 +0100766 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1 )
William Lallemand3f128872019-04-01 11:29:59 +0200767 continue;
William Lallemand00417412020-06-05 14:08:41 +0200768 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
William Lallemand73b85e72017-06-01 17:38:51 +0200769 goto alloc_error;
770 msg = NULL;
771 }
772 }
William Lallemand2bf6d622017-06-20 11:20:23 +0200773 /* add the -x option with the stat socket */
William Lallemand85b0bd92017-06-01 17:38:53 +0200774 if (cur_unixsocket) {
William Lallemand2bf6d622017-06-20 11:20:23 +0200775 next_argv[next_argc++] = "-x";
776 next_argv[next_argc++] = (char *)cur_unixsocket;
William Lallemand85b0bd92017-06-01 17:38:53 +0200777 }
778
William Lallemand00417412020-06-05 14:08:41 +0200779 /* copy the previous options */
780 for (i = 1; i < old_argc; i++)
781 next_argv[next_argc++] = old_argv[i];
782
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200783 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100784 execvp(next_argv[0], next_argv);
Christopher Faulet767a84b2017-11-24 16:50:31 +0100785 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100786 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100787 return;
788
William Lallemand73b85e72017-06-01 17:38:51 +0200789alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100790 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800791 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200792 return;
793}
794
William Lallemandfab0fdc2021-11-09 18:01:22 +0100795/* reexec haproxy in waitmode */
796static void mworker_reexec_waitmode()
797{
798 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
799 mworker_reexec();
800}
801
802/* reload haproxy and emit a warning */
803void mworker_reload()
804{
William Lallemandad221f42021-11-09 18:43:59 +0100805 struct mworker_proc *child;
806
William Lallemand836bda22021-11-09 18:16:47 +0100807 ha_notice("Reloading HAProxy\n");
William Lallemandad221f42021-11-09 18:43:59 +0100808
809 /* increment the number of reloads */
810 list_for_each_entry(child, &proc_list, list) {
811 child->reloads++;
812 }
813
William Lallemandfab0fdc2021-11-09 18:01:22 +0100814 mworker_reexec();
815}
816
William Lallemandb3f2be32018-09-11 10:06:18 +0200817static void mworker_loop()
818{
819
820#if defined(USE_SYSTEMD)
821 if (global.tune.options & GTUNE_USE_SYSTEMD)
822 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
823#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200824 /* Busy polling makes no sense in the master :-) */
825 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200826
William Lallemandbc193052018-09-11 10:06:26 +0200827
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100828 signal_unregister(SIGTTIN);
829 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100830 signal_unregister(SIGUSR1);
831 signal_unregister(SIGHUP);
832 signal_unregister(SIGQUIT);
833
William Lallemandb3f2be32018-09-11 10:06:18 +0200834 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
835 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100836 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
837 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200838 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
839 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
840 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
841 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
842
843 mworker_unblock_signals();
William Lallemand27f3fa52018-12-06 14:05:20 +0100844 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200845
William Lallemandbc193052018-09-11 10:06:26 +0200846 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
847 some SIGCHLD were lost */
848
William Lallemandb3f2be32018-09-11 10:06:18 +0200849 global.nbthread = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200850
William Lallemand2672eb92018-12-14 15:52:39 +0100851#ifdef USE_THREAD
852 tid_bit = 1;
853 all_threads_mask = 1;
854#endif
855
William Lallemandb3f2be32018-09-11 10:06:18 +0200856 jobs++; /* this is the "master" job, we want to take care of the
857 signals even if there is no listener so the poll loop don't
858 leave */
859
860 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200861 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200862}
William Lallemandcb11fd22017-06-01 17:38:52 +0200863
864/*
865 * Reexec the process in failure mode, instead of exiting
866 */
867void reexec_on_failure()
868{
William Lallemand68836742021-11-10 10:49:06 +0100869 struct mworker_proc *child;
870
William Lallemandcb11fd22017-06-01 17:38:52 +0200871 if (!atexit_flag)
872 return;
William Lallemand68836742021-11-10 10:49:06 +0100873
874 /* get the info of the children in the env */
875 if (mworker_env_to_proc_list() < 0) {
876 exit(EXIT_FAILURE);
877 }
878
879 /* increment the number of failed reloads */
880 list_for_each_entry(child, &proc_list, list) {
881 child->failedreloads++;
882 }
883
William Lallemandfab0fdc2021-11-09 18:01:22 +0100884 usermsgs_clr(NULL);
William Lallemand836bda22021-11-09 18:16:47 +0100885 ha_warning("Loading failure!\n");
William Lallemandfab0fdc2021-11-09 18:01:22 +0100886 mworker_reexec_waitmode();
William Lallemandcb11fd22017-06-01 17:38:52 +0200887}
William Lallemand73b85e72017-06-01 17:38:51 +0200888
889
890/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200891 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
892 * a signal zero to all subscribers. This means that it's as easy as
893 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200894 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100895static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200896{
897 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200898 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100899 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900}
901
902/*
903 * upon SIGTTOU, we pause everything
904 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100905static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906{
Willy Tarreau775e0012020-09-24 16:36:26 +0200907 if (protocol_pause_all() & ERR_FATAL) {
908 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200909 ha_warning("%s", msg);
910 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200911 soft_stop();
912 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100913 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914}
915
916/*
917 * upon SIGTTIN, let's have a soft stop.
918 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100919static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920{
Willy Tarreau775e0012020-09-24 16:36:26 +0200921 if (protocol_resume_all() & ERR_FATAL) {
922 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 +0200923 ha_warning("%s", msg);
924 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200925 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926}
927
928/*
929 * this function dumps every server's state when the process receives SIGHUP.
930 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100931static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100933 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200934
Christopher Faulet767a84b2017-11-24 16:50:31 +0100935 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936 while (p) {
937 struct server *s = p->srv;
938
939 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
940 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100941 chunk_printf(&trash,
942 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
943 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200944 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200945 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200946 ha_warning("%s\n", trash.area);
947 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200948 s = s->next;
949 }
950
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200951 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
952 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100953 chunk_printf(&trash,
954 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
955 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200956 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 +0200957 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100958 chunk_printf(&trash,
959 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
960 p->id,
961 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200962 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 +0200963 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100964 chunk_printf(&trash,
965 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
966 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
967 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200968 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 +0200969 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200970 ha_warning("%s\n", trash.area);
971 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200972
973 p = p->next;
974 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200975}
976
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100977static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200978{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200979 /* dump memory usage then free everything possible */
980 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100981 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982}
983
William Lallemande1340412017-12-28 16:09:36 +0100984/*
985 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
986 * If <fd> < 0, it opens /dev/null and use it to dup
987 *
988 * In the case of chrooting, you have to open /dev/null before the chroot, and
989 * pass the <fd> to this function
990 */
991static void stdio_quiet(int fd)
992{
993 if (fd < 0)
994 fd = open("/dev/null", O_RDWR, 0);
995
996 if (fd > -1) {
997 fclose(stdin);
998 fclose(stdout);
999 fclose(stderr);
1000
1001 dup2(fd, 0);
1002 dup2(fd, 1);
1003 dup2(fd, 2);
1004 if (fd > 2)
1005 close(fd);
1006 return;
1007 }
1008
1009 ha_alert("Cannot open /dev/null\n");
1010 exit(EXIT_FAILURE);
1011}
1012
1013
Joseph Herlant03420902018-11-15 10:41:50 -08001014/* This function checks if cfg_cfgfiles contains directories.
1015 * If it finds one, it adds all the files (and only files) it contains
1016 * in cfg_cfgfiles in place of the directory (and removes the directory).
1017 * It adds the files in lexical order.
1018 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001019 * It doesn't add files with name starting with '.'
1020 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001021static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001022{
1023 struct wordlist *wl, *wlb;
1024 char *err = NULL;
1025
1026 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1027 struct stat file_stat;
1028 struct dirent **dir_entries = NULL;
1029 int dir_entries_nb;
1030 int dir_entries_it;
1031
1032 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001033 ha_alert("Cannot open configuration file/directory %s : %s\n",
1034 wl->s,
1035 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001036 exit(1);
1037 }
1038
1039 if (!S_ISDIR(file_stat.st_mode))
1040 continue;
1041
1042 /* from this point wl->s is a directory */
1043
1044 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1045 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001046 ha_alert("Cannot open configuration directory %s : %s\n",
1047 wl->s,
1048 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001049 exit(1);
1050 }
1051
1052 /* for each element in the directory wl->s */
1053 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1054 struct dirent *dir_entry = dir_entries[dir_entries_it];
1055 char *filename = NULL;
1056 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1057
1058 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001059 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001060 */
1061 if (dir_entry->d_name[0] == '.' ||
1062 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1063 goto next_dir_entry;
1064
1065 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001066 ha_alert("Cannot load configuration files %s : out of memory.\n",
1067 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001068 exit(1);
1069 }
1070
1071 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001072 ha_alert("Cannot open configuration file %s : %s\n",
1073 wl->s,
1074 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001075 exit(1);
1076 }
1077
1078 /* don't add anything else than regular file in cfg_cfgfiles
1079 * this way we avoid loops
1080 */
1081 if (!S_ISREG(file_stat.st_mode))
1082 goto next_dir_entry;
1083
1084 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001085 ha_alert("Cannot load configuration files %s : %s\n",
1086 filename,
1087 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001088 exit(1);
1089 }
1090
1091next_dir_entry:
1092 free(filename);
1093 free(dir_entry);
1094 }
1095
1096 free(dir_entries);
1097
1098 /* remove the current directory (wl) from cfg_cfgfiles */
1099 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001100 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001101 free(wl);
1102 }
1103
1104 free(err);
1105}
1106
Willy Tarreaubaaee002006-06-26 02:48:02 +02001107/*
William Lallemand73b85e72017-06-01 17:38:51 +02001108 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001109 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001110 * Return an allocated copy of argv
1111 */
1112
1113static char **copy_argv(int argc, char **argv)
1114{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001115 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001116
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001117 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001118 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001119 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001120 return NULL;
1121 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001122 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001123
William Lallemanddf6c5a82020-06-04 17:40:23 +02001124 /* first copy argv[0] */
1125 *newargv++ = *argv++;
1126 argc--;
1127
1128 while (argc > 0) {
1129 if (**argv != '-') {
1130 /* non options are copied but will fail in the argument parser */
1131 *newargv++ = *argv++;
1132 argc--;
1133
1134 } else {
1135 char *flag;
1136
1137 flag = *argv + 1;
1138
1139 if (flag[0] == '-' && flag[1] == 0) {
1140 /* "--\0" copy every arguments till the end of argv */
1141 *newargv++ = *argv++;
1142 argc--;
1143
1144 while (argc > 0) {
1145 *newargv++ = *argv++;
1146 argc--;
1147 }
1148 } else {
1149 switch (*flag) {
1150 case 's':
1151 /* -sf / -st and their parameters are ignored */
1152 if (flag[1] == 'f' || flag[1] == 't') {
1153 argc--;
1154 argv++;
1155 /* The list can't contain a negative value since the only
1156 way to know the end of this list is by looking for the
1157 next option or the end of the options */
1158 while (argc > 0 && argv[0][0] != '-') {
1159 argc--;
1160 argv++;
1161 }
William Lallemand398da622020-09-02 16:12:23 +02001162 } else {
1163 argc--;
1164 argv++;
1165
William Lallemanddf6c5a82020-06-04 17:40:23 +02001166 }
1167 break;
1168
1169 case 'x':
1170 /* this option and its parameter are ignored */
1171 argc--;
1172 argv++;
1173 if (argc > 0) {
1174 argc--;
1175 argv++;
1176 }
1177 break;
1178
1179 case 'C':
1180 case 'n':
1181 case 'm':
1182 case 'N':
1183 case 'L':
1184 case 'f':
1185 case 'p':
1186 case 'S':
1187 /* these options have only 1 parameter which must be copied and can start with a '-' */
1188 *newargv++ = *argv++;
1189 argc--;
1190 if (argc == 0)
1191 goto error;
1192 *newargv++ = *argv++;
1193 argc--;
1194 break;
1195 default:
1196 /* for other options just copy them without parameters, this is also done
1197 * for options like "--foo", but this will fail in the argument parser.
1198 * */
1199 *newargv++ = *argv++;
1200 argc--;
1201 break;
1202 }
William Lallemand73b85e72017-06-01 17:38:51 +02001203 }
1204 }
William Lallemand73b85e72017-06-01 17:38:51 +02001205 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001206
William Lallemanddf6c5a82020-06-04 17:40:23 +02001207 return retargv;
1208
1209error:
1210 free(retargv);
1211 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001212}
1213
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001214
1215/* Performs basic random seed initialization. The main issue with this is that
1216 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1217 * which means that there will only be 4 billion possible random sequences once
1218 * srandom() is called, regardless of the internal state. Not calling it is
1219 * even worse as we'll always produce the same randoms sequences. What we do
1220 * here is to create an initial sequence from various entropy sources, hash it
1221 * using SHA1 and keep the resulting 160 bits available globally.
1222 *
1223 * We initialize the current process with the first 32 bits before starting the
1224 * polling loop, where all this will be changed to have process specific and
1225 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001226 *
1227 * Before starting threads, it's still possible to call random() as srandom()
1228 * is initialized from this, but after threads and/or processes are started,
1229 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001230 */
1231static void ha_random_boot(char *const *argv)
1232{
1233 unsigned char message[256];
1234 unsigned char *m = message;
1235 struct timeval tv;
1236 blk_SHA_CTX ctx;
1237 unsigned long l;
1238 int fd;
1239 int i;
1240
1241 /* start with current time as pseudo-random seed */
1242 gettimeofday(&tv, NULL);
1243 write_u32(m, tv.tv_sec); m += 4;
1244 write_u32(m, tv.tv_usec); m += 4;
1245
1246 /* PID and PPID add some OS-based randomness */
1247 write_u16(m, getpid()); m += 2;
1248 write_u16(m, getppid()); m += 2;
1249
1250 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1251 fd = open("/dev/urandom", O_RDONLY);
1252 if (fd >= 0) {
1253 i = read(fd, m, 20);
1254 if (i > 0)
1255 m += i;
1256 close(fd);
1257 }
1258
1259 /* take up to 160 bits bytes from openssl (non-blocking) */
1260#ifdef USE_OPENSSL
1261 if (RAND_bytes(m, 20) == 1)
1262 m += 20;
1263#endif
1264
1265 /* take 160 bits from existing random in case it was already initialized */
1266 for (i = 0; i < 5; i++) {
1267 write_u32(m, random());
1268 m += 4;
1269 }
1270
1271 /* stack address (benefit form operating system's ASLR) */
1272 l = (unsigned long)&m;
1273 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1274
1275 /* argv address (benefit form operating system's ASLR) */
1276 l = (unsigned long)&argv;
1277 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1278
1279 /* use tv_usec again after all the operations above */
1280 gettimeofday(&tv, NULL);
1281 write_u32(m, tv.tv_usec); m += 4;
1282
1283 /*
1284 * At this point, ~84-92 bytes have been used
1285 */
1286
1287 /* finish with the hostname */
1288 strncpy((char *)m, hostname, message + sizeof(message) - m);
1289 m += strlen(hostname);
1290
1291 /* total message length */
1292 l = m - message;
1293
1294 memset(&ctx, 0, sizeof(ctx));
1295 blk_SHA1_Init(&ctx);
1296 blk_SHA1_Update(&ctx, message, l);
1297 blk_SHA1_Final(boot_seed, &ctx);
1298
1299 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001300 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001301}
1302
Willy Tarreau5a023f02019-03-01 14:19:31 +01001303/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1304 * setting, and returns it. It may return -1 meaning "unlimited" if some
1305 * unlimited proxies have been found and the global.maxconn value is not yet
1306 * set. It may also return a value greater than maxconn if it's not yet set.
1307 * Note that a value of zero means there is no need for pipes. -1 is never
1308 * returned if global.maxconn is valid.
1309 */
1310static int compute_ideal_maxpipes()
1311{
1312 struct proxy *cur;
1313 int nbfe = 0, nbbe = 0;
1314 int unlimited = 0;
1315 int pipes;
1316 int max;
1317
1318 for (cur = proxies_list; cur; cur = cur->next) {
1319 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1320 if (cur->cap & PR_CAP_FE) {
1321 max = cur->maxconn;
1322 nbfe += max;
1323 if (!max) {
1324 unlimited = 1;
1325 break;
1326 }
1327 }
1328 if (cur->cap & PR_CAP_BE) {
1329 max = cur->fullconn ? cur->fullconn : global.maxconn;
1330 nbbe += max;
1331 if (!max) {
1332 unlimited = 1;
1333 break;
1334 }
1335 }
1336 }
1337 }
1338
1339 pipes = MAX(nbfe, nbbe);
1340 if (global.maxconn) {
1341 if (pipes > global.maxconn || unlimited)
1342 pipes = global.maxconn;
1343 } else if (unlimited) {
1344 pipes = -1;
1345 }
1346
1347 return pipes >= 4 ? pipes / 4 : pipes;
1348}
1349
Willy Tarreauac350932019-03-01 15:43:14 +01001350/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1351 * rlimits and computes an ideal maxconn. It's meant to be called only when
1352 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001353 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1354 * default 100) is returned as it is expected that it will even run on tight
1355 * environments, and will maintain compatibility with previous packages that
1356 * used to rely on this value as the default one. The system will emit a
1357 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001358 */
1359static int compute_ideal_maxconn()
1360{
1361 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1362 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1363 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001364 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001365 int maxconn;
1366
1367 /* we have to take into account these elements :
1368 * - number of engine_fds, which inflates the number of FD needed per
1369 * connection by this number.
1370 * - number of pipes per connection on average : for the unlimited
1371 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1372 * fixed value of 2*pipes.
1373 * - two FDs per connection
1374 */
1375
1376 /* subtract listeners and checks */
1377 remain -= global.maxsock;
1378
Willy Tarreau3f200852019-03-14 19:13:17 +01001379 /* one epoll_fd/kqueue_fd per thread */
1380 remain -= global.nbthread;
1381
1382 /* one wake-up pipe (2 fd) per thread */
1383 remain -= 2 * global.nbthread;
1384
Willy Tarreauac350932019-03-01 15:43:14 +01001385 /* Fixed pipes values : we only subtract them if they're not larger
1386 * than the remaining FDs because pipes are optional.
1387 */
1388 if (pipes >= 0 && pipes * 2 < remain)
1389 remain -= pipes * 2;
1390
1391 if (pipes < 0) {
1392 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1393 * = maxconn * (2 + 0.5 + engine_fds)
1394 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1395 */
1396 maxconn = 2 * remain / (5 + 2 * engine_fds);
1397 } else {
1398 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1399 * = maxconn * (2 + engine_fds)
1400 */
1401 maxconn = remain / (2 + engine_fds);
1402 }
1403
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001404 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001405}
1406
Willy Tarreaua409f302020-03-10 17:08:53 +01001407/* computes the estimated maxsock value for the given maxconn based on the
1408 * possibly set global.maxpipes and existing partial global.maxsock. It may
1409 * temporarily change global.maxconn for the time needed to propagate the
1410 * computations, and will reset it.
1411 */
1412static int compute_ideal_maxsock(int maxconn)
1413{
1414 int maxpipes = global.maxpipes;
1415 int maxsock = global.maxsock;
1416
1417
1418 if (!maxpipes) {
1419 int old_maxconn = global.maxconn;
1420
1421 global.maxconn = maxconn;
1422 maxpipes = compute_ideal_maxpipes();
1423 global.maxconn = old_maxconn;
1424 }
1425
1426 maxsock += maxconn * 2; /* each connection needs two sockets */
1427 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1428 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1429 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1430
1431 /* compute fd used by async engines */
1432 if (global.ssl_used_async_engines) {
1433 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1434
1435 maxsock += maxconn * sides * global.ssl_used_async_engines;
1436 }
1437 return maxsock;
1438}
1439
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001440/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001441 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1442 * value is accepted, non-zero otherwise. This is used to determine if an
1443 * automatic limit may be applied or not. When it is not, the caller knows that
1444 * the highest we can do is the rlim_max at boot. In case of error, we return
1445 * that the setting is possible, so that we defer the error processing to the
1446 * final stage in charge of enforcing this.
1447 */
1448static int check_if_maxsock_permitted(int maxsock)
1449{
1450 struct rlimit orig_limit, test_limit;
1451 int ret;
1452
1453 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1454 return 1;
1455
1456 /* don't go further if we can't even set to what we have */
1457 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1458 return 1;
1459
1460 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1461 test_limit.rlim_cur = test_limit.rlim_max;
1462 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1463
1464 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1465 return 1;
1466
1467 return ret == 0;
1468}
1469
Amaury Denoyelle484454d2021-05-05 16:18:45 +02001470void mark_tainted(const enum tainted_flags flag)
1471{
1472 HA_ATOMIC_OR(&tainted, flag);
1473}
1474
1475unsigned int get_tainted()
1476{
1477 int tainted_state;
1478 HA_ATOMIC_STORE(&tainted_state, tainted);
1479 return tainted_state;
1480}
Willy Tarreau304e17e2020-03-10 17:54:54 +01001481
William Lallemand73b85e72017-06-01 17:38:51 +02001482/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02001483 * This function initializes all the necessary variables. It only returns
1484 * if everything is OK. If something fails, it exits.
1485 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001486static void init(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001487{
Willy Tarreaubaaee002006-06-26 02:48:02 +02001488 int arg_mode = 0; /* MODE_DEBUG, ... */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001489 char *tmp;
1490 char *cfg_pidfile = NULL;
Willy Tarreau058e9072009-07-20 09:30:05 +02001491 int err_code = 0;
Maxime de Roucy0f503922016-05-13 23:52:55 +02001492 char *err_msg = NULL;
Willy Tarreau477ecd82010-01-03 21:12:30 +01001493 struct wordlist *wl;
Kevinm48936af2010-12-22 16:08:21 +00001494 char *progname;
Willy Tarreau576132e2011-09-10 19:26:56 +02001495 char *change_dir = NULL;
Christopher Fauletd7c91962015-04-30 11:48:27 +02001496 struct proxy *px;
Willy Tarreaue6945732016-12-21 19:57:00 +01001497 struct post_check_fct *pcf;
Willy Tarreauac350932019-03-01 15:43:14 +01001498 int ideal_maxconn;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001499 char *check_condition = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001500
Christopher Faulete3a5e352017-10-24 13:53:54 +02001501 global.mode = MODE_STARTING;
William Lallemand00417412020-06-05 14:08:41 +02001502 old_argv = copy_argv(argc, argv);
1503 if (!old_argv) {
William Lallemanddf6c5a82020-06-04 17:40:23 +02001504 ha_alert("failed to copy argv.\n");
1505 exit(1);
1506 }
William Lallemand73b85e72017-06-01 17:38:51 +02001507
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001508 if (!init_trash_buffers(1)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001509 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet748919a2017-07-26 14:59:46 +02001510 exit(1);
1511 }
David du Colombier7af46052012-05-16 14:16:48 +02001512
Emeric Brun2b920a12010-09-23 18:30:22 +02001513 /* NB: POSIX does not make it mandatory for gethostname() to NULL-terminate
1514 * the string in case of truncation, and at least FreeBSD appears not to do
1515 * it.
1516 */
1517 memset(hostname, 0, sizeof(hostname));
1518 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001519
1520 if ((localpeer = strdup(hostname)) == NULL) {
1521 ha_alert("Cannot allocate memory for local peer.\n");
1522 exit(EXIT_FAILURE);
1523 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001524 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Emeric Brun2b920a12010-09-23 18:30:22 +02001525
William Lallemand24c928c2020-01-14 17:58:18 +01001526 /* we were in mworker mode, we should restart in mworker mode */
1527 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1528 global.mode |= MODE_MWORKER;
1529
Willy Tarreaubaaee002006-06-26 02:48:02 +02001530 /*
1531 * Initialize the previously static variables.
1532 */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001533
Willy Tarreau173d9952018-01-26 21:48:23 +01001534 totalconn = actconn = listeners = stopping = 0;
Cyril Bonté203ec5a2017-03-23 22:44:13 +01001535 killed = 0;
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001536
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537
1538#ifdef HAPROXY_MEMMAX
Willy Tarreau70060452015-12-14 12:46:07 +01001539 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001540#endif
1541
Benoit GARNIERb413c2a2016-03-27 11:08:03 +02001542 tzset();
Willy Tarreau55542642021-10-08 09:33:24 +02001543 clock_init_process_date();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001544 start_date = now;
1545
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001546 ha_random_boot(argv);
Willy Tarreau84310e22014-02-14 11:59:04 +01001547
Willy Tarreau8ed669b2013-01-11 15:49:37 +01001548 if (init_acl() != 0)
1549 exit(1);
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001550
Amaury Denoyellec593bcd2021-05-19 15:35:29 +02001551#ifdef USE_OPENSSL
1552 /* Initialize the random generator.
1553 * Must be called before chroot for access to /dev/urandom
1554 */
1555 if (!ssl_initialize_random()) {
1556 ha_alert("OpenSSL random data generator initialization failed.\n");
1557 exit(1);
1558 }
1559#endif
1560
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001561 /* Initialise lua. */
1562 hlua_init();
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001563
Christopher Fauletff2613e2016-11-09 11:36:17 +01001564 /* Initialize process vars */
Willy Tarreaub7bfcb32021-08-31 08:13:25 +02001565 vars_init_head(&proc_vars, SCOPE_PROC);
Christopher Fauletff2613e2016-11-09 11:36:17 +01001566
Willy Tarreau43b78992009-01-25 15:42:27 +01001567 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001568#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001569 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001571#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001572 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001573#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001574#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001575 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001576#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001577#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001578 global.tune.options |= GTUNE_USE_EVPORTS;
1579#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001580#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001581 global.tune.options |= GTUNE_USE_SPLICE;
1582#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001583#if defined(USE_GETADDRINFO)
1584 global.tune.options |= GTUNE_USE_GAI;
1585#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001586#if defined(SO_REUSEPORT)
1587 global.tune.options |= GTUNE_USE_REUSEPORT;
1588#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001589#ifdef USE_THREAD
1590 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1591#endif
William Dauchya5194602020-03-28 19:29:58 +01001592 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001593
1594 pid = getpid();
1595 progname = *argv;
1596 while ((tmp = strchr(progname, '/')) != NULL)
1597 progname = tmp + 1;
1598
Kevinm48936af2010-12-22 16:08:21 +00001599 /* the process name is used for the logs only */
Eric Salama7cea6062020-10-02 11:58:19 +02001600 chunk_initlen(&global.log_tag, strdup(progname), strlen(progname), strlen(progname));
1601 if (b_orig(&global.log_tag) == NULL) {
1602 chunk_destroy(&global.log_tag);
1603 ha_alert("Cannot allocate memory for log_tag.\n");
1604 exit(EXIT_FAILURE);
1605 }
Kevinm48936af2010-12-22 16:08:21 +00001606
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607 argc--; argv++;
1608 while (argc > 0) {
1609 char *flag;
1610
1611 if (**argv == '-') {
1612 flag = *argv+1;
1613
1614 /* 1 arg */
1615 if (*flag == 'v') {
1616 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001617 if (flag[1] == 'v') /* -vv */
1618 display_build_opts();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001619 exit(0);
1620 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001621#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001623 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001624#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001625#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001626 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001627 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001628#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001629#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001630 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001631 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001632#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001633#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001634 else if (*flag == 'd' && flag[1] == 'v')
1635 global.tune.options &= ~GTUNE_USE_EVPORTS;
1636#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001637#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001638 else if (*flag == 'd' && flag[1] == 'S')
1639 global.tune.options &= ~GTUNE_USE_SPLICE;
1640#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001641#if defined(USE_GETADDRINFO)
1642 else if (*flag == 'd' && flag[1] == 'G')
1643 global.tune.options &= ~GTUNE_USE_GAI;
1644#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001645#if defined(SO_REUSEPORT)
1646 else if (*flag == 'd' && flag[1] == 'R')
1647 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1648#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001649 else if (*flag == 'd' && flag[1] == 'V')
1650 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001651 else if (*flag == 'V')
1652 arg_mode |= MODE_VERBOSE;
1653 else if (*flag == 'd' && flag[1] == 'b')
1654 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001655 else if (*flag == 'd' && flag[1] == 'D')
1656 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001657 else if (*flag == 'd' && flag[1] == 'W')
1658 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreau6e064432012-05-08 15:40:42 +02001659 else if (*flag == 'd' && flag[1] == 'M')
1660 mem_poison_byte = flag[2] ? strtol(flag + 2, NULL, 0) : 'P';
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001661 else if (*flag == 'd' && flag[1] == 'r')
1662 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001663 else if (*flag == 'd')
1664 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001665 else if (*flag == 'c' && flag[1] == 'c') {
1666 arg_mode |= MODE_CHECK_CONDITION;
1667 argv++;
1668 argc--;
1669 check_condition = *argv;
1670 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001671 else if (*flag == 'c')
1672 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001673 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001674 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001675 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001676 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001677#if defined(USE_SYSTEMD)
1678 global.tune.options |= GTUNE_USE_SYSTEMD;
1679#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001680 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 +01001681 usage(progname);
1682#endif
1683 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001684 else if (*flag == 'W')
1685 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001686 else if (*flag == 'q')
1687 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001688 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001689 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001690 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001691 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001692 }
William Lallemand4fc09692017-06-19 16:37:19 +02001693 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001694 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001695 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001696
Olivier Houchardf73629d2017-04-05 22:33:04 +02001697 argv++;
1698 argc--;
1699 }
William Lallemande7361152018-10-26 14:47:36 +02001700 else if (*flag == 'S') {
1701 struct wordlist *c;
1702
William Lallemanda6b32492020-06-04 23:49:20 +02001703 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001704 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1705 usage(progname);
1706 }
1707 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1708 ha_alert("Cannot allocate memory\n");
1709 exit(EXIT_FAILURE);
1710 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001711 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001712
1713 argv++;
1714 argc--;
1715 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001716 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1717 /* list of pids to finish ('f') or terminate ('t') */
1718
1719 if (flag[1] == 'f')
1720 oldpids_sig = SIGUSR1; /* finish then exit */
1721 else
1722 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001723 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001724 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001725 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1726 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001727 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001728 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001729 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001730 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001731 errno = 0;
1732 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1733 if (errno) {
1734 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1735 flag,
1736 *argv, strerror(errno));
1737 exit(1);
1738 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001739 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001740 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001741 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1742 flag, endptr);
1743 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001744 }
Chris Lane236062f2018-02-05 23:15:44 +00001745 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001746 if (oldpids[nb_oldpids] <= 0)
1747 usage(progname);
1748 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001749 }
1750 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001751 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1752 /* now that's a cfgfile list */
1753 argv++; argc--;
1754 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001755 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001756 ha_alert("Cannot load configuration file/directory %s : %s\n",
1757 *argv,
1758 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001759 exit(1);
1760 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001761 argv++; argc--;
1762 }
1763 break;
1764 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001765 else { /* >=2 args */
1766 argv++; argc--;
1767 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001768 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001769
1770 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001771 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001772 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001773 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001774 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001775 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001776 free(localpeer);
1777 if ((localpeer = strdup(*argv)) == NULL) {
1778 ha_alert("Cannot allocate memory for local peer.\n");
1779 exit(EXIT_FAILURE);
1780 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001781 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001782 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001783 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001784 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001785 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001786 ha_alert("Cannot load configuration file/directory %s : %s\n",
1787 *argv,
1788 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001789 exit(1);
1790 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001791 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001792 case 'p' : cfg_pidfile = *argv; break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001793 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001794 }
1795 }
1796 }
1797 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001798 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001799 argv++; argc--;
1800 }
1801
Christopher Faulete3a5e352017-10-24 13:53:54 +02001802 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001803 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001804 | MODE_DIAG | MODE_CHECK_CONDITION));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001805
William Lallemand944e6192018-11-21 15:48:31 +01001806 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001807 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001808 global.mode |= MODE_MWORKER_WAIT;
1809 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001810 }
1811
Willy Tarreau26146192021-07-21 10:01:36 +02001812 if ((global.mode & (MODE_MWORKER | MODE_CHECK | MODE_CHECK_CONDITION)) == MODE_MWORKER &&
1813 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001814 atexit_flag = 1;
1815 atexit(reexec_on_failure);
1816 }
1817
Willy Tarreau576132e2011-09-10 19:26:56 +02001818 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001819 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001820 exit(1);
1821 }
1822
Willy Tarreaubaaee002006-06-26 02:48:02 +02001823 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001824
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001825#ifdef USE_CPU_AFFINITY
1826 {
1827 int i;
Willy Tarreau44ea6312021-06-15 08:57:56 +02001828 ha_cpuset_zero(&cpu_map.proc);
1829 ha_cpuset_zero(&cpu_map.proc_t1);
Willy Tarreau26f42a02021-05-14 08:26:38 +02001830 for (i = 0; i < MAX_THREADS; ++i) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02001831 ha_cpuset_zero(&cpu_map.thread[i]);
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001832 }
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001833 }
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001834#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001835
Amaury Denoyelle11124302021-06-04 18:22:08 +02001836 usermsgs_clr("config");
1837
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001838 if (global.mode & MODE_CHECK_CONDITION) {
1839 int result;
1840
1841 uint32_t err;
1842 const char *errptr;
1843 char *errmsg = NULL;
1844
1845 char *args[MAX_LINE_ARGS+1];
1846 int arg = sizeof(args) / sizeof(*args);
1847 size_t outlen = strlen(check_condition) + 1;
Willy Tarreauc8194c32021-07-16 16:38:58 +02001848 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001849
1850 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02001851 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001852 &errptr);
1853
1854 if (err & PARSE_ERR_QUOTE) {
1855 ha_alert("Syntax Error in condition: Unmatched quote.\n");
1856 exit(2);
1857 }
1858
1859 if (err & PARSE_ERR_HEX) {
1860 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
1861 exit(2);
1862 }
1863
1864 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
1865 ha_alert("Error in condition: Line too long.\n");
1866 exit(2);
1867 }
1868
Willy Tarreauc8194c32021-07-16 16:38:58 +02001869 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001870 ha_alert("Error in condition: Too many words.\n");
1871 exit(2);
1872 }
1873
1874 if (err) {
1875 ha_alert("Unhandled error in condition, please report this to the developers.\n");
1876 exit(2);
1877 }
1878
Willy Tarreauc8194c32021-07-16 16:38:58 +02001879 /* remerge all words into a single expression */
1880 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
1881 ;
1882
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001883 result = cfg_eval_condition(args, &errmsg, &errptr);
1884
1885 if (result < 0) {
1886 if (errmsg)
1887 ha_alert("Failed to evaluate condition: %s\n", errmsg);
1888
1889 exit(2);
1890 }
1891
1892 exit(result ? 0 : 1);
1893 }
1894
William Lallemand944e6192018-11-21 15:48:31 +01001895 /* in wait mode, we don't try to read the configuration files */
1896 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001897 char *env_cfgfiles = NULL;
1898 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001899
William Lallemand944e6192018-11-21 15:48:31 +01001900 /* handle cfgfiles that are actually directories */
1901 cfgfiles_expand_directories();
1902
1903 if (LIST_ISEMPTY(&cfg_cfgfiles))
1904 usage(progname);
1905
1906
1907 list_for_each_entry(wl, &cfg_cfgfiles, list) {
1908 int ret;
1909
Christopher Faulet4e366822021-01-12 18:57:38 +01001910 if (env_err == 0) {
1911 if (!memprintf(&env_cfgfiles, "%s%s%s",
1912 (env_cfgfiles ? env_cfgfiles : ""),
1913 (env_cfgfiles ? ";" : ""), wl->s))
1914 env_err = 1;
1915 }
William Lallemand7b302d82019-05-20 11:15:37 +02001916
William Lallemand944e6192018-11-21 15:48:31 +01001917 ret = readcfgfile(wl->s);
1918 if (ret == -1) {
1919 ha_alert("Could not open configuration file %s : %s\n",
1920 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01001921 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001922 exit(1);
1923 }
1924 if (ret & (ERR_ABORT|ERR_FATAL))
1925 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
1926 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01001927 if (err_code & ERR_ABORT) {
1928 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001929 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01001930 }
Willy Tarreauc4382422009-12-06 13:10:44 +01001931 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001932
William Lallemand944e6192018-11-21 15:48:31 +01001933 /* do not try to resolve arguments nor to spot inconsistencies when
1934 * the configuration contains fatal errors caused by files not found
1935 * or failed memory allocations.
1936 */
1937 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1938 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01001939 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001940 exit(1);
1941 }
Christopher Faulet4e366822021-01-12 18:57:38 +01001942 if (env_err) {
1943 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
1944 exit(1);
1945 }
1946 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
1947 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02001948
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02001949 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001950 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01001951 struct mworker_proc *tmproc;
1952
William Lallemand482f9a92019-04-12 16:15:00 +02001953 setenv("HAPROXY_MWORKER", "1", 1);
1954
William Lallemand16dd1b32018-11-19 18:46:18 +01001955 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
1956
William Lallemandf3a86832019-04-01 11:29:58 +02001957 tmproc = calloc(1, sizeof(*tmproc));
William Lallemand16dd1b32018-11-19 18:46:18 +01001958 if (!tmproc) {
1959 ha_alert("Cannot allocate process structures.\n");
1960 exit(EXIT_FAILURE);
1961 }
William Lallemand8f7069a2019-04-12 16:09:23 +02001962 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand68836742021-11-10 10:49:06 +01001963 tmproc->failedreloads = 0;
William Lallemand16dd1b32018-11-19 18:46:18 +01001964 tmproc->reloads = 0;
William Lallemand16dd1b32018-11-19 18:46:18 +01001965 tmproc->pid = pid;
1966 tmproc->timestamp = start_date.tv_sec;
1967 tmproc->ipc_fd[0] = -1;
1968 tmproc->ipc_fd[1] = -1;
1969
1970 proc_self = tmproc;
1971
Willy Tarreau2b718102021-04-21 07:32:39 +02001972 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01001973 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001974
Willy Tarreau6185a032021-06-15 08:02:06 +02001975 tmproc = calloc(1, sizeof(*tmproc));
1976 if (!tmproc) {
1977 ha_alert("Cannot allocate process structures.\n");
1978 exit(EXIT_FAILURE);
1979 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001980
Willy Tarreau6185a032021-06-15 08:02:06 +02001981 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
1982 tmproc->pid = -1;
William Lallemand68836742021-11-10 10:49:06 +01001983 tmproc->failedreloads = 0;
Willy Tarreau6185a032021-06-15 08:02:06 +02001984 tmproc->reloads = 0;
1985 tmproc->timestamp = -1;
Willy Tarreau6185a032021-06-15 08:02:06 +02001986 tmproc->ipc_fd[0] = -1;
1987 tmproc->ipc_fd[1] = -1;
William Lallemandce83b4a2018-10-26 14:47:30 +02001988
Willy Tarreau6185a032021-06-15 08:02:06 +02001989 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
1990 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02001991 }
Willy Tarreau6185a032021-06-15 08:02:06 +02001992
1993 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01001994 }
1995 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
1996 struct wordlist *it, *c;
1997
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02001998 /* get the info of the children in the env */
1999 if (mworker_env_to_proc_list() < 0) {
2000 exit(EXIT_FAILURE);
2001 }
William Lallemande7361152018-10-26 14:47:36 +02002002
William Lallemand550db6d2018-11-06 17:37:12 +01002003 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02002004
William Lallemand550db6d2018-11-06 17:37:12 +01002005 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02002006 ha_alert("Can't create the master's CLI.\n");
2007 exit(EXIT_FAILURE);
2008 }
William Lallemande7361152018-10-26 14:47:36 +02002009
William Lallemand550db6d2018-11-06 17:37:12 +01002010 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
2011
2012 if (mworker_cli_proxy_new_listener(c->s) < 0) {
2013 ha_alert("Can't create the master's CLI.\n");
2014 exit(EXIT_FAILURE);
2015 }
Willy Tarreau2b718102021-04-21 07:32:39 +02002016 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01002017 free(c->s);
2018 free(c);
2019 }
2020 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002021 }
2022
Eric Salama5ba83352021-03-16 15:11:17 +01002023 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
2024 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
2025 }
2026
Christopher Faulet27c8d202021-10-13 09:50:53 +02002027 /* destroy unreferenced defaults proxies */
2028 proxy_destroy_all_unref_defaults();
2029
Willy Tarreaue90904d2021-02-12 14:08:31 +01002030
Willy Tarreaubb925012009-07-23 13:36:36 +02002031 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02002032 for (px = proxies_list; px; px = px->next) {
2033 struct server *srv;
2034 struct post_proxy_check_fct *ppcf;
2035 struct post_server_check_fct *pscf;
2036
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002037 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002038 continue;
2039
Christopher Fauletc1692962019-08-12 09:51:07 +02002040 list_for_each_entry(pscf, &post_server_check_list, list) {
2041 for (srv = px->srv; srv; srv = srv->next)
2042 err_code |= pscf->fct(srv);
2043 }
2044 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2045 err_code |= ppcf->fct(px);
2046 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002047 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002048 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002049 exit(1);
2050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002052 err_code |= pattern_finalize_config();
2053 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2054 ha_alert("Failed to finalize pattern config.\n");
2055 exit(1);
2056 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002057
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002058 if (global.rlimit_memmax_all)
2059 global.rlimit_memmax = global.rlimit_memmax_all;
2060
Willy Tarreaue5733232019-05-22 19:24:06 +02002061#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002062 err_code |= netns_init();
2063 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002064 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002065 exit(1);
2066 }
2067#endif
2068
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002069 /* Apply server states */
2070 apply_server_state();
2071
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002072 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002073 srv_compute_all_admin_states(px);
2074
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002075 /* Apply servers' configured address */
2076 err_code |= srv_init_addr();
2077 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002078 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002079 exit(1);
2080 }
2081
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002082 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2083 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2084 exit(1);
2085 }
2086
Willy Tarreaubaaee002006-06-26 02:48:02 +02002087 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002088 struct peers *pr;
2089 struct proxy *px;
2090
Willy Tarreaubebd2122020-04-15 16:06:11 +02002091 if (warned & WARN_ANY)
2092 qfprintf(stdout, "Warnings were found.\n");
2093
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002094 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002095 if (pr->peers_fe)
2096 break;
2097
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002098 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002099 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002100 break;
2101
Emeric Brunbc5c8212021-08-13 09:32:50 +02002102 if (!px) {
2103 /* We may only have log-forward section */
2104 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002105 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002106 break;
2107 }
2108
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002109 if (pr || px) {
2110 /* At least one peer or one listener has been found */
2111 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002112 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002113 }
2114 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2115 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002116 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002117
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002118 if (global.mode & MODE_DIAG) {
2119 cfg_run_diagnostics();
2120 }
2121
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002122 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002123 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002124
Willy Tarreaue6945732016-12-21 19:57:00 +01002125 list_for_each_entry(pcf, &post_check_list, list) {
2126 err_code |= pcf->fct();
2127 if (err_code & (ERR_ABORT|ERR_FATAL))
2128 exit(1);
2129 }
2130
Willy Tarreaubaaee002006-06-26 02:48:02 +02002131 if (cfg_maxconn > 0)
2132 global.maxconn = cfg_maxconn;
2133
Willy Tarreau4975d142021-03-13 11:00:33 +01002134 if (global.cli_fe)
2135 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002136
2137 if (cfg_peers) {
2138 /* peers also need to bypass global maxconn */
2139 struct peers *p = cfg_peers;
2140
2141 for (p = cfg_peers; p; p = p->next)
2142 if (p->peers_fe)
2143 global.maxsock += p->peers_fe->maxconn;
2144 }
2145
Willy Tarreaubaaee002006-06-26 02:48:02 +02002146 if (cfg_pidfile) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002147 free(global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002148 global.pidfile = strdup(cfg_pidfile);
2149 }
2150
Willy Tarreaud0256482015-01-15 21:45:22 +01002151 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002152 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2153 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2154 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2155 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002156 *
2157 * If memmax is set, then it depends on which values are set. If
2158 * maxsslconn is set, we use memmax to determine how many cleartext
2159 * connections may be added, and set maxconn to the sum of the two.
2160 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2161 * the remaining amount of memory between memmax and the cleartext
2162 * connections. If neither are set, then it is considered that all
2163 * connections are SSL-capable, and maxconn is computed based on this,
2164 * then maxsslconn accordingly. We need to know if SSL is used on the
2165 * frontends, backends, or both, because when it's used on both sides,
2166 * we need twice the value for maxsslconn, but we only count the
2167 * handshake once since it is not performed on the two sides at the
2168 * same time (frontend-side is terminated before backend-side begins).
2169 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002170 * ssl_handshake_cost during its initialization. In any case, if
2171 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2172 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002173 */
Willy Tarreauac350932019-03-01 15:43:14 +01002174 ideal_maxconn = compute_ideal_maxconn();
2175
Willy Tarreaud0256482015-01-15 21:45:22 +01002176 if (!global.rlimit_memmax) {
2177 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002178 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002179 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2180 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2181 }
2182 }
2183#ifdef USE_OPENSSL
2184 else if (!global.maxconn && !global.maxsslconn &&
2185 (global.ssl_used_frontend || global.ssl_used_backend)) {
2186 /* memmax is set, compute everything automatically. Here we want
2187 * to ensure that all SSL connections will be served. We take
2188 * care of the number of sides where SSL is used, and consider
2189 * the worst case : SSL used on both sides and doing a handshake
2190 * simultaneously. Note that we can't have more than maxconn
2191 * handshakes at a time by definition, so for the worst case of
2192 * two SSL conns per connection, we count a single handshake.
2193 */
2194 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2195 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002196 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002197
2198 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2199 mem -= global.maxzlibmem;
2200 mem = mem * MEM_USABLE_RATIO;
2201
Willy Tarreau304e17e2020-03-10 17:54:54 +01002202 /* Principle: we test once to set maxconn according to the free
2203 * memory. If it results in values the system rejects, we try a
2204 * second time by respecting rlim_fd_max. If it fails again, we
2205 * go back to the initial value and will let the final code
2206 * dealing with rlimit report the error. That's up to 3 attempts.
2207 */
2208 do {
2209 global.maxconn = mem /
2210 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2211 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2212 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002213
Willy Tarreau304e17e2020-03-10 17:54:54 +01002214 if (retried == 1)
2215 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2216 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002217#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002218 if (global.maxconn > SYSTEM_MAXCONN)
2219 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002220#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002221 global.maxsslconn = sides * global.maxconn;
2222
2223 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2224 break;
2225 } while (retried++ < 2);
2226
Willy Tarreaud0256482015-01-15 21:45:22 +01002227 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2228 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2229 global.maxconn, global.maxsslconn);
2230 }
2231 else if (!global.maxsslconn &&
2232 (global.ssl_used_frontend || global.ssl_used_backend)) {
2233 /* memmax and maxconn are known, compute maxsslconn automatically.
2234 * maxsslconn being forced, we don't know how many of it will be
2235 * on each side if both sides are being used. The worst case is
2236 * when all connections use only one SSL instance because
2237 * handshakes may be on two sides at the same time.
2238 */
2239 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2240 int64_t mem = global.rlimit_memmax * 1048576ULL;
2241 int64_t sslmem;
2242
2243 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2244 mem -= global.maxzlibmem;
2245 mem = mem * MEM_USABLE_RATIO;
2246
Willy Tarreau87b09662015-04-03 00:22:06 +02002247 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002248 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2249 global.maxsslconn = round_2dig(global.maxsslconn);
2250
2251 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002252 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2253 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2254 "without SSL is %d, but %d was found and SSL is in use.\n",
2255 global.rlimit_memmax,
2256 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2257 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002258 exit(1);
2259 }
2260
2261 if (global.maxsslconn > sides * global.maxconn)
2262 global.maxsslconn = sides * global.maxconn;
2263
2264 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2265 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2266 }
2267#endif
2268 else if (!global.maxconn) {
2269 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2270 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2271 int64_t mem = global.rlimit_memmax * 1048576ULL;
2272 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002273 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002274
2275 if (global.ssl_used_frontend || global.ssl_used_backend)
2276 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2277
2278 mem -= global.maxzlibmem;
2279 mem = mem * MEM_USABLE_RATIO;
2280
2281 clearmem = mem;
2282 if (sides)
2283 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2284
Willy Tarreau304e17e2020-03-10 17:54:54 +01002285 /* Principle: we test once to set maxconn according to the free
2286 * memory. If it results in values the system rejects, we try a
2287 * second time by respecting rlim_fd_max. If it fails again, we
2288 * go back to the initial value and will let the final code
2289 * dealing with rlimit report the error. That's up to 3 attempts.
2290 */
2291 do {
2292 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2293 if (retried == 1)
2294 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2295 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002296#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002297 if (global.maxconn > SYSTEM_MAXCONN)
2298 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002299#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002300
Willy Tarreau304e17e2020-03-10 17:54:54 +01002301 if (clearmem <= 0 || !global.maxconn) {
2302 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2303 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2304 "is %d, but %d was found.\n",
2305 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002306 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002307 global.maxsslconn);
2308 exit(1);
2309 }
2310
2311 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2312 break;
2313 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002314
2315 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2316 if (sides && global.maxsslconn > sides * global.maxconn) {
2317 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2318 "to be limited to %d. Better reduce global.maxsslconn to get more "
2319 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2320 }
2321 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2322 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002323 }
2324
Willy Tarreaua409f302020-03-10 17:08:53 +01002325 global.maxsock = compute_ideal_maxsock(global.maxconn);
2326 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002327 if (!global.maxpipes)
2328 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002329
Olivier Houchard88698d92019-04-16 19:07:22 +02002330 /* update connection pool thresholds */
2331 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2332 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2333
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002334 proxy_adjust_all_maxconn();
2335
Willy Tarreau1db37712007-06-03 17:16:49 +02002336 if (global.tune.maxpollevents <= 0)
2337 global.tune.maxpollevents = MAX_POLL_EVENTS;
2338
Willy Tarreau060a7612021-03-10 11:06:26 +01002339 if (global.tune.runqueue_depth <= 0) {
2340 /* tests on various thread counts from 1 to 64 have shown an
2341 * optimal queue depth following roughly 1/sqrt(threads).
2342 */
2343 int s = my_flsl(global.nbthread);
2344 s += (global.nbthread / s); // roughly twice the sqrt.
2345 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2346 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002347
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002348 if (global.tune.recv_enough == 0)
2349 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2350
Willy Tarreau27a674e2009-08-17 07:23:33 +02002351 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2352 global.tune.maxrewrite = global.tune.bufsize / 2;
2353
Amaury Denoyelle11124302021-06-04 18:22:08 +02002354 usermsgs_clr(NULL);
2355
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2357 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002358 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002359 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2360 }
2361
William Lallemand095ba4c2017-06-01 17:38:50 +02002362 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002363 /* command line daemon mode inhibits foreground and debug modes mode */
2364 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002365 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002367
2368 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369
William Lallemand095ba4c2017-06-01 17:38:50 +02002370 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002371 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002372 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 }
2374
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002375 if (global.nbthread < 1)
2376 global.nbthread = 1;
2377
Christopher Faulet3ef26392017-08-29 16:46:57 +02002378 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002379 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002380 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002381 exit(1);
2382 }
2383
Christopher Faulet96d44832017-11-14 22:02:30 +01002384 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002385 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002386 exit(1);
2387 }
2388
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002389 /*
2390 * Note: we could register external pollers here.
2391 * Built-in pollers have been registered before main().
2392 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002393
Willy Tarreau43b78992009-01-25 15:42:27 +01002394 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002395 disable_poller("kqueue");
2396
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002397 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2398 disable_poller("evports");
2399
Willy Tarreau43b78992009-01-25 15:42:27 +01002400 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002401 disable_poller("epoll");
2402
Willy Tarreau43b78992009-01-25 15:42:27 +01002403 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002404 disable_poller("poll");
2405
Willy Tarreau43b78992009-01-25 15:42:27 +01002406 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002407 disable_poller("select");
2408
2409 /* Note: we could disable any poller by name here */
2410
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002411 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002412 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002413 fprintf(stderr, "\n");
2414 list_filters(stderr);
2415 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002416
Willy Tarreau4f60f162007-04-08 16:39:58 +02002417 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002418 ha_alert("No polling mechanism available.\n"
2419 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2420 " is too low on this platform to support maxconn and the number of listeners\n"
2421 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2422 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2423 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2424 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2425 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2426 " check build settings using 'haproxy -vv'.\n\n",
2427 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002428 exit(1);
2429 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002430 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2431 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002432 }
2433
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002434 if (!global.node)
2435 global.node = strdup(hostname);
2436
Willy Tarreau02b092f2020-10-07 18:36:54 +02002437 /* stop disabled proxies */
2438 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002439 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002440 stop_proxy(px);
2441 }
2442
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002443 if (!hlua_post_init())
2444 exit(1);
Thomas Holmes6abded42015-05-12 16:23:58 +01002445
Maxime de Roucy0f503922016-05-13 23:52:55 +02002446 free(err_msg);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002447}
2448
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002449void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002451 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002452 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002453 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002454 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002455 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002456 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002457 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002458 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002459 struct per_thread_init_fct *tif, *tifb;
2460 struct per_thread_deinit_fct *tdf, *tdfb;
2461 struct per_thread_alloc_fct *taf, *tafb;
2462 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002463 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002464 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002465 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002466 int cur_fd;
2467
2468 /* At this point the listeners state is weird:
2469 * - most listeners are still bound and referenced in their protocol
2470 * - some might be zombies that are not in their proto anymore, but
2471 * still appear in their proxy's listeners with a valid FD.
2472 * - some might be stopped and still appear in their proxy as FD #-1
2473 * - among all of them, some might be inherited hence shared and we're
2474 * not allowed to pause them or whatever, we must just close them.
2475 * - finally some are not listeners (pipes, logs, stdout, etc) and
2476 * must be left intact.
2477 *
2478 * The safe way to proceed is to unbind (and close) whatever is not yet
2479 * unbound so that no more receiver/listener remains alive. Then close
2480 * remaining listener FDs, which correspond to zombie listeners (those
2481 * belonging to disabled proxies that were in another process).
2482 * objt_listener() would be cleaner here but not converted yet.
2483 */
2484 protocol_unbind_all();
2485
2486 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002487 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002488 continue;
2489
Willy Tarreaua74cb382020-10-15 21:29:49 +02002490 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002491 struct listener *l = fdtab[cur_fd].owner;
2492
2493 BUG_ON(l->state != LI_INIT);
2494 unbind_listener(l);
2495 }
2496 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002497
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002498 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002499 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002500 /* build a list of unique uri_auths */
2501 if (!ua)
2502 ua = p->uri_auth;
2503 else {
2504 /* check if p->uri_auth is unique */
2505 for (uap = ua; uap; uap=uap->next)
2506 if (uap == p->uri_auth)
2507 break;
2508
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002509 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002510 /* add it, if it is */
2511 p->uri_auth->next = ua;
2512 ua = p->uri_auth;
2513 }
William Lallemand0f99e342011-10-12 17:50:54 +02002514 }
2515
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002516 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002517 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002518 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002519 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002520
Christopher Faulet27c8d202021-10-13 09:50:53 +02002521 /* destroy all referenced defaults proxies */
2522 proxy_destroy_all_unref_defaults();
2523
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002524 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002525 struct stat_scope *scope, *scopep;
2526
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002527 uap = ua;
2528 ua = ua->next;
2529
Willy Tarreaua534fea2008-08-03 12:19:50 +02002530 free(uap->uri_prefix);
2531 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002532 free(uap->node);
2533 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002534
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002535 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002536 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002537
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002538 scope = uap->scope;
2539 while (scope) {
2540 scopep = scope;
2541 scope = scope->next;
2542
2543 free(scopep->px_id);
2544 free(scopep);
2545 }
2546
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002547 free(uap);
2548 }
2549
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002550 userlist_free(userlist);
2551
David Carlier834cb2e2015-09-25 12:02:25 +01002552 cfg_unregister_sections();
2553
Christopher Faulet0132d062017-07-26 15:33:35 +02002554 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002555
Willy Tarreau05554e62016-12-21 20:46:26 +01002556 list_for_each_entry(pdf, &post_deinit_list, list)
2557 pdf->fct();
2558
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002559 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002560 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002561 ha_free(&global.chroot);
2562 ha_free(&global.pidfile);
2563 ha_free(&global.node);
2564 ha_free(&global.desc);
2565 ha_free(&oldpids);
2566 ha_free(&old_argv);
2567 ha_free(&localpeer);
2568 ha_free(&global.server_state_base);
2569 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002570 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002571 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002572
William Lallemand0f99e342011-10-12 17:50:54 +02002573 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002574 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002575 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002576 free(log);
2577 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002578 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002579 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002580 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002581 free(wl);
2582 }
2583
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002584 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2585 if (bol->must_free)
2586 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002587 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002588 free(bol);
2589 }
2590
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002591 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002592 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002593 free(pxdf);
2594 }
2595
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002596 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002597 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002598 free(pdf);
2599 }
2600
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002601 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002602 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002603 free(srvdf);
2604 }
2605
Tim Duesterhusfc854942020-09-10 19:46:42 +02002606 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002607 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002608 free(pcf);
2609 }
2610
Tim Duesterhus34bef072020-07-04 11:49:50 +02002611 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002612 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002613 free(pscf);
2614 }
2615
Tim Duesterhus53508d62020-09-10 19:46:40 +02002616 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002617 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002618 free(ppcf);
2619 }
2620
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002621 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002622 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002623 free(tif);
2624 }
2625
2626 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002627 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002628 free(tdf);
2629 }
2630
2631 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002632 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002633 free(taf);
2634 }
2635
2636 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002637 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002638 free(tff);
2639 }
2640
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002641 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002642 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002643 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002644} /* end deinit() */
2645
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002646__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002647{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002648 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002649 deinit();
2650 exit(status);
2651}
William Lallemand72160322018-11-06 17:37:16 +01002652
Willy Tarreau918ff602011-07-25 16:33:49 +02002653/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002654void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002655{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002656 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002657
Willy Tarreau55542642021-10-08 09:33:24 +02002658 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002659 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002660 wake_expired_tasks();
2661
William Lallemand1aab50b2018-06-07 09:46:01 +02002662 /* check if we caught some signals and process them in the
2663 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002664 if (signal_queue_len && tid == 0) {
2665 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002666 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002667 }
2668
2669 /* Process a few tasks */
2670 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002671
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002672 /* also stop if we failed to cleanly stop all tasks */
2673 if (killed > 1)
2674 break;
2675
Willy Tarreau10146c92015-04-13 20:44:19 +02002676 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002677 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002678 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002679 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002680 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002681 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2682 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002683 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002684 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002685 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002686 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002687 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002688 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002689
Willy Tarreau4f46a352020-03-23 09:27:28 +01002690 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002691 int i;
2692
2693 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002694 /* stop muxes before acknowledging stopping */
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002695 if (!(stopping_thread_mask & tid_bit)) {
2696 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2697 wake = 1;
2698 }
2699
Willy Tarreau1db42732021-04-06 11:44:07 +02002700 if (_HA_ATOMIC_OR_FETCH(&stopping_thread_mask, tid_bit) == tid_bit) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002701 /* notify all threads that stopping was just set */
2702 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002703 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002704 wake_thread(i);
2705 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002706 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002707
2708 /* stop when there's nothing left to do */
2709 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002710 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2711 /* wake all threads waiting on jobs==0 */
2712 for (i = 0; i < global.nbthread; i++)
2713 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2714 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002715 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002716 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002717 }
2718
Willy Tarreauc49ba522019-12-11 08:12:23 +01002719 /* If we have to sleep, measure how long */
2720 next = wake ? TICK_ETERNITY : next_timer_expiry();
2721
Willy Tarreau58b458d2008-06-29 22:40:23 +02002722 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002723 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002724
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002725 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002726 }
2727}
2728
Christopher Faulet1d17c102017-08-29 15:38:48 +02002729static void *run_thread_poll_loop(void *data)
2730{
Willy Tarreau082b6282019-05-22 14:42:12 +02002731 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002732 struct per_thread_init_fct *ptif;
2733 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002734 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002735 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002736 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2737 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002738
Willy Tarreau43ab05b2021-09-28 09:43:11 +02002739 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02002740 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02002741 clock_set_local_source();
Willy Tarreau91e6df02019-05-03 17:21:18 +02002742
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002743 /* Now, initialize one thread init at a time. This is better since
2744 * some init code is a bit tricky and may release global resources
2745 * after reallocating them locally. This will also ensure there is
2746 * no race on file descriptors allocation.
2747 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002748#ifdef USE_THREAD
2749 pthread_mutex_lock(&init_mutex);
2750#endif
2751 /* The first thread must set the number of threads left */
2752 if (!init_left)
2753 init_left = global.nbthread;
2754 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002755
Willy Tarreau55542642021-10-08 09:33:24 +02002756 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002757
Willy Tarreau082b6282019-05-22 14:42:12 +02002758 /* per-thread alloc calls performed here are not allowed to snoop on
2759 * other threads, so they are free to initialize at their own rhythm
2760 * as long as they act as if they were alone. None of them may rely
2761 * on resources initialized by the other ones.
2762 */
2763 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2764 if (!ptaf->fct()) {
2765 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002766#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002767 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002768#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02002769 exit(1);
2770 }
2771 }
2772
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002773 /* per-thread init calls performed here are not allowed to snoop on
2774 * other threads, so they are free to initialize at their own rhythm
2775 * as long as they act as if they were alone.
2776 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002777 list_for_each_entry(ptif, &per_thread_init_list, list) {
2778 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002779 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002780#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002781 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002782#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002783 exit(1);
2784 }
2785 }
2786
Willy Tarreau71092822019-06-10 09:51:04 +02002787 /* enabling protocols will result in fd_insert() calls to be performed,
2788 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002789 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002790 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002791 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002792 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002793
Willy Tarreau34a150c2019-06-11 09:16:41 +02002794#ifdef USE_THREAD
2795 pthread_cond_broadcast(&init_cond);
2796 pthread_mutex_unlock(&init_mutex);
2797
2798 /* now wait for other threads to finish starting */
2799 pthread_mutex_lock(&init_mutex);
2800 while (init_left)
2801 pthread_cond_wait(&init_cond, &init_mutex);
2802 pthread_mutex_unlock(&init_mutex);
2803#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002804
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002805#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2806 /* Let's refrain from using setuid executables. This way the impact of
2807 * an eventual vulnerability in a library remains limited. It may
2808 * impact external checks but who cares about them anyway ? In the
2809 * worst case it's possible to disable the option. Obviously we do this
2810 * in workers only. We can't hard-fail on this one as it really is
2811 * implementation dependent though we're interested in feedback, hence
2812 * the warning.
2813 */
2814 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2815 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002816 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 +01002817 ha_warning("Failed to disable setuid, please report to developers with detailed "
2818 "information about your operating system. You can silence this warning "
2819 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2820 }
2821 }
2822#endif
2823
Willy Tarreaud96f1122019-12-03 07:07:36 +01002824#if defined(RLIMIT_NPROC)
2825 /* all threads have started, it's now time to prevent any new thread
2826 * or process from starting. Obviously we do this in workers only. We
2827 * can't hard-fail on this one as it really is implementation dependent
2828 * though we're interested in feedback, hence the warning.
2829 */
2830 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2831 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2832 static int warn_fail;
2833
Willy Tarreau18515722021-04-06 11:57:41 +02002834 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002835 ha_warning("Failed to disable forks, please report to developers with detailed "
2836 "information about your operating system. You can silence this warning "
2837 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2838 }
2839 }
2840#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002841 run_poll_loop();
2842
2843 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2844 ptdf->fct();
2845
Willy Tarreau082b6282019-05-22 14:42:12 +02002846 list_for_each_entry(ptff, &per_thread_free_list, list)
2847 ptff->fct();
2848
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002849#ifdef USE_THREAD
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002850 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002851 if (tid > 0)
2852 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002853#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002854 return NULL;
2855}
Christopher Faulet1d17c102017-08-29 15:38:48 +02002856
William Dauchyf9af9d72019-11-17 15:47:16 +01002857/* set uid/gid depending on global settings */
2858static void set_identity(const char *program_name)
2859{
2860 if (global.gid) {
2861 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
2862 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
2863 " without 'uid'/'user' is generally useless.\n", program_name);
2864
2865 if (setgid(global.gid) == -1) {
2866 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
2867 protocol_unbind_all();
2868 exit(1);
2869 }
2870 }
2871
2872 if (global.uid && setuid(global.uid) == -1) {
2873 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
2874 protocol_unbind_all();
2875 exit(1);
2876 }
2877}
2878
Willy Tarreaubaaee002006-06-26 02:48:02 +02002879int main(int argc, char **argv)
2880{
2881 int err, retry;
2882 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02002883 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02002884 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
2885
2886 /* Catch forced CFLAGS that miss 2-complement integer overflow */
2887 if (intovf + 0x7FFFFFFF >= intovf) {
2888 fprintf(stderr,
2889 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
2890 "The source code was miscompiled by the compiler, which usually indicates that\n"
2891 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
2892 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
2893 "and INSTALL files to decide on the best way to pass your local build options.\n"
2894 "\nBuild options :"
2895#ifdef BUILD_TARGET
2896 "\n TARGET = " BUILD_TARGET
2897#endif
2898#ifdef BUILD_CPU
2899 "\n CPU = " BUILD_CPU
2900#endif
2901#ifdef BUILD_CC
2902 "\n CC = " BUILD_CC
2903#endif
2904#ifdef BUILD_CFLAGS
2905 "\n CFLAGS = " BUILD_CFLAGS
2906#endif
2907#ifdef BUILD_OPTIONS
2908 "\n OPTIONS = " BUILD_OPTIONS
2909#endif
2910#ifdef BUILD_DEBUG
2911 "\n DEBUG = " BUILD_DEBUG
2912#endif
2913 "\n\n");
2914 return 1;
2915 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916
Olivier Houchard5fa300d2018-02-03 15:15:21 +01002917 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01002918
Willy Tarreaubf696402019-03-01 10:09:28 +01002919 /* take a copy of initial limits before we possibly change them */
2920 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02002921
2922 if (limit.rlim_max == RLIM_INFINITY)
2923 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01002924 rlim_fd_cur_at_boot = limit.rlim_cur;
2925 rlim_fd_max_at_boot = limit.rlim_max;
2926
Willy Tarreau5794fb02018-11-25 18:43:29 +01002927 /* process all initcalls in order of potential dependency */
2928 RUN_INITCALLS(STG_PREPARE);
2929 RUN_INITCALLS(STG_LOCK);
2930 RUN_INITCALLS(STG_ALLOC);
2931 RUN_INITCALLS(STG_POOL);
2932 RUN_INITCALLS(STG_REGISTER);
2933 RUN_INITCALLS(STG_INIT);
2934
Emeric Bruncf20bf12010-10-22 16:06:11 +02002935 init(argc, argv);
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002936 signal_register_fct(SIGQUIT, dump, SIGQUIT);
2937 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
2938 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02002939 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002940
Willy Tarreaue437c442010-03-17 18:02:46 +01002941 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
2942 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
2943 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002944 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002945 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002946
Willy Tarreaudc23a922011-02-16 11:10:36 +01002947 /* ulimits */
2948 if (!global.rlimit_nofile)
2949 global.rlimit_nofile = global.maxsock;
2950
2951 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01002952 limit.rlim_cur = global.rlimit_nofile;
2953 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
2954
Willy Tarreaudc23a922011-02-16 11:10:36 +01002955 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02002956 getrlimit(RLIMIT_NOFILE, &limit);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002957 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2958 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
2959 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002960 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002961 }
2962 else {
2963 /* try to set it to the max possible at least */
2964 limit.rlim_cur = limit.rlim_max;
2965 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
2966 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02002967
William Dauchya5194602020-03-28 19:29:58 +01002968 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002969 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
2970 global.rlimit_nofile = limit.rlim_cur;
2971 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01002972 }
2973 }
2974
2975 if (global.rlimit_memmax) {
2976 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01002977 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01002978#ifdef RLIMIT_AS
2979 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002980 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2981 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2982 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002983 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002984 }
2985 else
William Dauchya5194602020-03-28 19:29:58 +01002986 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002987 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002988 }
2989#else
2990 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002991 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2992 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2993 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002994 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002995 }
2996 else
William Dauchya5194602020-03-28 19:29:58 +01002997 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002998 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002999 }
3000#endif
3001 }
3002
Olivier Houchardf73629d2017-04-05 22:33:04 +02003003 if (old_unixsocket) {
William Lallemand85b0bd92017-06-01 17:38:53 +02003004 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02003005 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003006 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02003007 if (!(global.mode & MODE_MWORKER))
3008 exit(1);
3009 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02003010 }
3011 }
William Lallemand85b0bd92017-06-01 17:38:53 +02003012 get_cur_unixsocket();
3013
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 /* We will loop at most 100 times with 10 ms delay each time.
3015 * That's at most 1 second. We only send a signal to old pids
3016 * if we cannot grab at least one port.
3017 */
3018 retry = MAX_START_RETRIES;
3019 err = ERR_NONE;
3020 while (retry >= 0) {
3021 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003022 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003023 /* exit the loop on no error or fatal error */
3024 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003025 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003026 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003027 break;
3028
3029 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3030 * listening sockets. So on those platforms, it would be wiser to
3031 * simply send SIGUSR1, which will not be undoable.
3032 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003033 if (tell_old_pids(SIGTTOU) == 0) {
3034 /* no need to wait if we can't contact old pids */
3035 retry = 0;
3036 continue;
3037 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003038 /* give some time to old processes to stop listening */
3039 w.tv_sec = 0;
3040 w.tv_usec = 10*1000;
3041 select(0, NULL, NULL, NULL, &w);
3042 retry--;
3043 }
3044
Willy Tarreaue91bff22020-09-02 11:11:43 +02003045 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003046 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003047 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003048 if (retry != MAX_START_RETRIES && nb_oldpids) {
3049 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003051 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 exit(1);
3053 }
3054
William Lallemand944e6192018-11-21 15:48:31 +01003055 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003056 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057 /* Note: we don't have to send anything to the old pids because we
3058 * never stopped them. */
3059 exit(1);
3060 }
3061
Willy Tarreaue91bff22020-09-02 11:11:43 +02003062 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003063 * the previous process gave us, we don't need them anymore
3064 */
3065 while (xfer_sock_list != NULL) {
3066 struct xfer_sock_list *tmpxfer = xfer_sock_list->next;
3067 close(xfer_sock_list->fd);
3068 free(xfer_sock_list->iface);
3069 free(xfer_sock_list->namespace);
3070 free(xfer_sock_list);
3071 xfer_sock_list = tmpxfer;
3072 }
Willy Tarreaudd815982007-10-16 12:25:14 +02003073
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003075 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3076 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003077
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078 /* MODE_QUIET can inhibit alerts and warnings below this line */
3079
PiBa-NL149a81a2017-12-25 21:03:31 +01003080 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3081 /* either stdin/out/err are already closed or should stay as they are. */
3082 if ((global.mode & MODE_DAEMON)) {
3083 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3084 global.mode &= ~MODE_VERBOSE;
3085 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3086 }
3087 } else {
3088 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3089 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003090 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003091 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003092 }
3093
3094 /* open log & pid files before the chroot */
William Lallemand80293002017-11-06 11:00:03 +01003095 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003096 unlink(global.pidfile);
3097 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3098 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003099 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003100 if (nb_oldpids)
3101 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003102 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 exit(1);
3104 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003105 }
3106
Willy Tarreaub38651a2007-03-24 17:24:39 +01003107 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003108 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3109 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003110 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003111 exit(1);
3112 }
3113
Jackie Tapia749f74c2020-07-22 18:59:40 -05003114 /* If the user is not root, we'll still let them try the configuration
3115 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003116 */
3117 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003118 ha_warning("[%s.main()] Some options which require full privileges"
3119 " might not work well.\n"
3120 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003121
William Lallemand095ba4c2017-06-01 17:38:50 +02003122 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3123
3124 /* chroot if needed */
3125 if (global.chroot != NULL) {
3126 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003127 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003128 if (nb_oldpids)
3129 tell_old_pids(SIGTTIN);
3130 protocol_unbind_all();
3131 exit(1);
3132 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003133 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003134 }
3135
William Lallemand944e6192018-11-21 15:48:31 +01003136 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003137 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138
William Lallemand27edc4b2019-05-07 17:49:33 +02003139 /* send a SIGTERM to workers who have a too high reloads number */
3140 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3141 mworker_kill_max_reloads(SIGTERM);
3142
Willy Tarreaubaaee002006-06-26 02:48:02 +02003143 /* Note that any error at this stage will be fatal because we will not
3144 * be able to restart the old pids.
3145 */
3146
William Dauchyf9af9d72019-11-17 15:47:16 +01003147 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3148 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003149
Willy Tarreaubaaee002006-06-26 02:48:02 +02003150 /* check ulimits */
3151 limit.rlim_cur = limit.rlim_max = 0;
3152 getrlimit(RLIMIT_NOFILE, &limit);
3153 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003154 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3155 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3156 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3157 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3158 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003159 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003160 }
3161 else
3162 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003163 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003164 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3165 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003166 }
3167
William Lallemand944e6192018-11-21 15:48:31 +01003168 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003169 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003170 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003171 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003172
William Lallemand095ba4c2017-06-01 17:38:50 +02003173 /*
3174 * if daemon + mworker: must fork here to let a master
3175 * process live in background before forking children
3176 */
William Lallemand73b85e72017-06-01 17:38:51 +02003177
3178 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3179 && (global.mode & MODE_MWORKER)
3180 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003181 ret = fork();
3182 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003183 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003184 protocol_unbind_all();
3185 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003186 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003187 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003188 } else /* change the process group ID in the child (master process) */
3189 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003190 }
William Lallemande20b6a62017-06-01 17:38:55 +02003191
William Lallemande20b6a62017-06-01 17:38:55 +02003192
William Lallemanddeed7802017-11-06 11:00:04 +01003193 /* if in master-worker mode, write the PID of the father */
3194 if (global.mode & MODE_MWORKER) {
3195 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003196 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003197 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003198 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003199 }
3200
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003202 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003203 if (global.mode & MODE_MWORKER)
3204 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003205
3206 ret = fork();
3207 if (ret < 0) {
3208 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3209 protocol_unbind_all();
3210 exit(1); /* there has been an error */
3211 }
3212 else if (ret == 0) { /* child breaks here */
Willy Tarreau3c032f22021-07-21 10:17:02 +02003213 /* This one must not be exported, it's internal! */
3214 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003215 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003216 }
3217 else { /* parent here */
3218 in_parent = 1;
3219
William Lallemand944e6192018-11-21 15:48:31 +01003220 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3221 char pidstr[100];
3222 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003223 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003224 }
3225 if (global.mode & MODE_MWORKER) {
3226 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003227
William Lallemand5d71a6b2021-11-09 15:25:31 +01003228 ha_notice("New worker (%d) forked\n", ret);
William Lallemand944e6192018-11-21 15:48:31 +01003229 /* find the right mworker_proc */
3230 list_for_each_entry(child, &proc_list, list) {
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003231 if (child->reloads == 0 && child->options & PROC_O_TYPE_WORKER) {
William Lallemand944e6192018-11-21 15:48:31 +01003232 child->timestamp = now.tv_sec;
3233 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003234 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003235 break;
3236 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003237 }
3238 }
William Lallemand944e6192018-11-21 15:48:31 +01003239 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003240
William Lallemand944e6192018-11-21 15:48:31 +01003241 } else {
3242 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003243 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003244 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003245
3246#ifdef USE_CPU_AFFINITY
Willy Tarreau44ea6312021-06-15 08:57:56 +02003247 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 +02003248
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003249#ifdef __FreeBSD__
Willy Tarreau44ea6312021-06-15 08:57:56 +02003250 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003251 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
David Carlier2d0493a2020-12-02 21:14:51 +00003252#elif defined(__linux__) || defined(__DragonFly__)
Willy Tarreau44ea6312021-06-15 08:57:56 +02003253 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003254 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003255#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003256 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003257#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003258 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003259 if (pidfd >= 0) {
3260 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3261 close(pidfd);
3262 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003263
3264 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003265 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266
Willy Tarreaud67ff342021-06-15 07:58:09 +02003267 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003268 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
William Lallemandfab0fdc2021-11-09 18:01:22 +01003269 master = 1;
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003270
3271 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3272 (global.mode & MODE_DAEMON)) {
3273 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003274 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3275 stdio_quiet(-1);
3276
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003277 global.mode &= ~MODE_VERBOSE;
3278 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003279 }
3280
William Lallemandfab0fdc2021-11-09 18:01:22 +01003281 if (global.mode & MODE_MWORKER_WAIT) {
3282 /* only the wait mode handles the master CLI */
3283 mworker_loop();
3284 } else {
3285
3286 /* if not in wait mode, reload in wait mode to free the memory */
William Lallemand836bda22021-11-09 18:16:47 +01003287 ha_notice("Loading success.\n");
William Lallemand68836742021-11-10 10:49:06 +01003288 proc_self->failedreloads = 0; /* reset the number of failure */
William Lallemandfab0fdc2021-11-09 18:01:22 +01003289 mworker_reexec_waitmode();
3290 }
William Lallemand1499b9b2017-06-07 15:04:47 +02003291 /* should never get there */
3292 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003293 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003294#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003295 ssl_free_dh();
3296#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003297 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003298 }
3299
William Lallemandcb11fd22017-06-01 17:38:52 +02003300 /* child must never use the atexit function */
3301 atexit_flag = 0;
3302
William Lallemandbc193052018-09-11 10:06:26 +02003303 /* close useless master sockets */
3304 if (global.mode & MODE_MWORKER) {
3305 struct mworker_proc *child, *it;
3306 master = 0;
3307
William Lallemand309dc9a2018-10-26 14:47:45 +02003308 mworker_cli_proxy_stop();
3309
William Lallemandbc193052018-09-11 10:06:26 +02003310 /* free proc struct of other processes */
3311 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003312 /* close the FD of the master side for all
3313 * workers, we don't need to close the worker
3314 * side of other workers since it's done with
3315 * the bind_proc */
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003316 if (child->ipc_fd[0] >= 0)
3317 close(child->ipc_fd[0]);
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003318 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandce83b4a2018-10-26 14:47:30 +02003319 child->reloads == 0) {
3320 /* keep this struct if this is our pid */
3321 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003322 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003323 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003324 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003325 mworker_free_child(child);
3326 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003327 }
3328 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003329
William Lallemande1340412017-12-28 16:09:36 +01003330 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3331 devnullfd = open("/dev/null", O_RDWR, 0);
3332 if (devnullfd < 0) {
3333 ha_alert("Cannot open /dev/null\n");
3334 exit(EXIT_FAILURE);
3335 }
3336 }
3337
William Lallemand095ba4c2017-06-01 17:38:50 +02003338 /* Must chroot and setgid/setuid in the children */
3339 /* chroot if needed */
3340 if (global.chroot != NULL) {
3341 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003342 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003343 if (nb_oldpids)
3344 tell_old_pids(SIGTTIN);
3345 protocol_unbind_all();
3346 exit(1);
3347 }
3348 }
3349
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003350 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003351 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003352
William Lallemand7f80eb22017-05-26 18:19:55 +02003353 /* pass through every cli socket, and check if it's bound to
3354 * the current process and if it exposes listeners sockets.
3355 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3356 * */
3357
Willy Tarreau4975d142021-03-13 11:00:33 +01003358 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003359 struct bind_conf *bind_conf;
3360
Willy Tarreau4975d142021-03-13 11:00:33 +01003361 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003362 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003363 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3364 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003365 }
3366 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003367 }
3368
William Lallemand2e8fad92018-11-13 16:18:23 +01003369 /*
3370 * This is only done in daemon mode because we might want the
3371 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3372 * we should now close the 3 first FDs to ensure that we can
3373 * detach from the TTY. We MUST NOT do it in other cases since
3374 * it would have already be done, and 0-2 would have been
3375 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003376 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003377 if ((global.mode & MODE_DAEMON) &&
3378 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003379 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003380 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003381 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003382 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3383 }
3384 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003385 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3386 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003387 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003388 }
3389
William Dauchye039f262019-11-17 15:47:15 +01003390 /* try our best to re-enable core dumps depending on system capabilities.
3391 * What is addressed here :
3392 * - remove file size limits
3393 * - remove core size limits
3394 * - mark the process dumpable again if it lost it due to user/group
3395 */
3396 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3397 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3398
3399#if defined(RLIMIT_FSIZE)
3400 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3401 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3402 ha_alert("[%s.main()] Failed to set the raise the maximum "
3403 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003404 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003405 }
3406 else
3407 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003408 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003409 }
3410#endif
3411
3412#if defined(RLIMIT_CORE)
3413 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3414 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3415 ha_alert("[%s.main()] Failed to set the raise the core "
3416 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003417 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003418 }
3419 else
3420 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003421 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003422 }
3423#endif
3424
3425#if defined(USE_PRCTL)
3426 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3427 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3428 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003429#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003430 {
3431 int traceable = PROC_TRACE_CTL_ENABLE;
3432 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3433 ha_warning("[%s.main()] Failed to set the traceable flag, "
3434 "no core will be dumped.\n", argv[0]);
3435 }
William Dauchye039f262019-11-17 15:47:15 +01003436#endif
3437 }
3438
Christopher Faulete3a5e352017-10-24 13:53:54 +02003439 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003440 reset_usermsgs_ctx();
3441
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003442 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003443 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003444
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003445 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003446 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003447
3448 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003449 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003450
3451 /* wait for all threads to terminate */
3452 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003453
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003454 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003455}
3456
Willy Tarreaubaaee002006-06-26 02:48:02 +02003457/*
3458 * Local variables:
3459 * c-indent-level: 8
3460 * c-basic-offset: 8
3461 * End:
3462 */