blob: a26c8f33d2447954f134f92595328e504654630d [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
Willy Tarreaua5357cd2021-05-09 06:14:25 +02002 * HAProxy : High Availability-enabled HTTP/TCP proxy
Willy Tarreau2454d6e2022-02-01 18:06:59 +01003 * Copyright 2000-2022 Willy Tarreau <willy@haproxy.org>.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
Ilya Shipitsin46a030c2020-07-05 16:36:08 +050010 * Please refer to RFC7230 - RFC7235 information about HTTP protocol, and
11 * RFC6265 for information about cookies usage. More generally, the IETF HTTP
Willy Tarreaubaaee002006-06-26 02:48:02 +020012 * Working Group's web site should be consulted for protocol related changes :
13 *
14 * http://ftp.ics.uci.edu/pub/ietf/http/
15 *
16 * Pending bugs (may be not fixed because never reproduced) :
17 * - solaris only : sometimes, an HTTP proxy with only a dispatch address causes
18 * the proxy to terminate (no core) if the client breaks the connection during
19 * the response. Seen on 1.1.8pre4, but never reproduced. May not be related to
20 * the snprintf() bug since requests were simple (GET / HTTP/1.0), but may be
21 * related to missing setsid() (fixed in 1.1.15)
22 * - a proxy with an invalid config will prevent the startup even if disabled.
23 *
24 * ChangeLog has moved to the CHANGELOG file.
25 *
Willy Tarreaubaaee002006-06-26 02:48:02 +020026 */
27
David Carlier7ece0962015-12-08 21:43:09 +000028#define _GNU_SOURCE
Willy Tarreaubaaee002006-06-26 02:48:02 +020029#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <string.h>
33#include <ctype.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020034#include <dirent.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020035#include <sys/stat.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <sys/time.h>
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <netinet/tcp.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42#include <netdb.h>
43#include <fcntl.h>
44#include <errno.h>
45#include <signal.h>
46#include <stdarg.h>
47#include <sys/resource.h>
Tim Duesterhusdfad6a42020-04-18 16:02:47 +020048#include <sys/utsname.h>
Marc-Antoine Perennou992709b2013-02-12 10:53:52 +010049#include <sys/wait.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <time.h>
51#include <syslog.h>
Michael Schererab012dd2013-01-12 18:35:19 +010052#include <grp.h>
Willy Tarreaud10385a2021-10-06 22:22:40 +020053
Willy Tarreau5e03dfa2021-10-06 22:53:51 +020054#ifdef USE_THREAD
55#include <pthread.h>
56#endif
57
Willy Tarreaufc6c0322012-11-16 16:12:27 +010058#ifdef USE_CPU_AFFINITY
Willy Tarreaufc6c0322012-11-16 16:12:27 +010059#include <sched.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000060#if defined(__FreeBSD__) || defined(__DragonFly__)
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020061#include <sys/param.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000062#ifdef __FreeBSD__
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020063#include <sys/cpuset.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000064#endif
David Carlier5e4c8e22019-09-13 05:12:58 +010065#endif
Willy Tarreaufc6c0322012-11-16 16:12:27 +010066#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020067
Willy Tarreau636848a2019-04-15 19:38:50 +020068#if defined(USE_PRCTL)
69#include <sys/prctl.h>
70#endif
71
devnexen@gmail.com21185972021-08-21 09:13:10 +010072#if defined(USE_PROCCTL)
73#include <sys/procctl.h>
74#endif
75
Willy Tarreaubaaee002006-06-26 02:48:02 +020076#ifdef DEBUG_FULL
77#include <assert.h>
78#endif
Tim Duesterhusd6942c82017-11-20 15:58:35 +010079#if defined(USE_SYSTEMD)
80#include <systemd/sd-daemon.h>
81#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020082
Willy Tarreau6c3a6812020-03-06 18:57:15 +010083#include <import/sha1.h>
84
Willy Tarreaub2551052020-06-09 09:07:15 +020085#include <haproxy/acl.h>
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +010086#include <haproxy/action.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020087#include <haproxy/activity.h>
88#include <haproxy/api.h>
89#include <haproxy/arg.h>
90#include <haproxy/auth.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020091#include <haproxy/base64.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020092#include <haproxy/capture-t.h>
Willy Tarreau66243b42021-07-16 15:39:28 +020093#include <haproxy/cfgcond.h>
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +020094#include <haproxy/cfgdiag.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020095#include <haproxy/cfgparse.h>
Willy Tarreauc13ed532020-06-02 10:22:45 +020096#include <haproxy/chunk.h>
Willy Tarreau83487a82020-06-04 20:19:54 +020097#include <haproxy/cli.h>
Willy Tarreau55542642021-10-08 09:33:24 +020098#include <haproxy/clock.h>
Willy Tarreau7ea393d2020-06-04 18:02:10 +020099#include <haproxy/connection.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200100#ifdef USE_CPU_AFFINITY
Amaury Denoyelle982fb532021-04-21 18:39:58 +0200101#include <haproxy/cpuset.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200102#endif
Willy Tarreaueb92deb2020-06-04 10:53:16 +0200103#include <haproxy/dns.h>
Willy Tarreau2741c8c2020-06-02 11:28:02 +0200104#include <haproxy/dynbuf.h>
Willy Tarreau8d366972020-05-27 16:10:29 +0200105#include <haproxy/errors.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200106#include <haproxy/fd.h>
Willy Tarreauc7babd82020-06-04 21:29:29 +0200107#include <haproxy/filters.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200108#include <haproxy/global.h>
Willy Tarreau86416052020-06-04 09:20:54 +0200109#include <haproxy/hlua.h>
Willy Tarreauc761f842020-06-04 11:40:28 +0200110#include <haproxy/http_rules.h>
Willy Tarreau853b2972020-05-27 18:01:47 +0200111#include <haproxy/list.h>
Willy Tarreau213e9902020-06-04 14:58:24 +0200112#include <haproxy/listener.h>
Willy Tarreauaeed4a82020-06-04 22:01:04 +0200113#include <haproxy/log.h>
Willy Tarreaub5abe5b2020-06-04 14:07:37 +0200114#include <haproxy/mworker.h>
Willy Tarreau7a00efb2020-06-02 17:02:59 +0200115#include <haproxy/namespace.h>
Willy Tarreau6131d6a2020-06-02 16:48:09 +0200116#include <haproxy/net_helper.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +0200117#include <haproxy/openssl-compat.h>
Willy Tarreau225a90a2020-06-04 15:06:28 +0200118#include <haproxy/pattern.h>
Willy Tarreau3c2a7c22020-06-04 18:38:21 +0200119#include <haproxy/peers.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200120#include <haproxy/pool.h>
121#include <haproxy/protocol.h>
Willy Tarreaubf3b06b2020-08-26 10:23:40 +0200122#include <haproxy/proto_tcp.h>
Willy Tarreaua264d962020-06-04 22:29:18 +0200123#include <haproxy/proxy.h>
Willy Tarreau7cd8b6e2020-06-02 17:32:26 +0200124#include <haproxy/regex.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200125#include <haproxy/sample.h>
Willy Tarreau1e56f922020-06-04 23:20:13 +0200126#include <haproxy/server.h>
Willy Tarreau48d25b32020-06-04 18:58:52 +0200127#include <haproxy/session.h>
Willy Tarreau3727a8a2020-06-04 17:37:26 +0200128#include <haproxy/signal.h>
Willy Tarreau063d47d2020-08-28 16:29:53 +0200129#include <haproxy/sock.h>
Willy Tarreau25140cc2020-08-28 15:40:33 +0200130#include <haproxy/sock_inet.h>
Willy Tarreau209108d2020-06-04 20:30:20 +0200131#include <haproxy/ssl_sock.h>
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +0200132#include <haproxy/stats-t.h>
Willy Tarreaudfd3de82020-06-04 23:46:14 +0200133#include <haproxy/stream.h>
Willy Tarreaucea0e1b2020-06-04 17:25:40 +0200134#include <haproxy/task.h>
Willy Tarreau3f567e42020-05-28 15:29:19 +0200135#include <haproxy/thread.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200136#include <haproxy/time.h>
137#include <haproxy/tools.h>
138#include <haproxy/uri_auth-t.h>
Willy Tarreaua1718922020-06-04 16:25:31 +0200139#include <haproxy/vars.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200140#include <haproxy/version.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200141
Willy Tarreaubaaee002006-06-26 02:48:02 +0200142
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100143/* array of init calls for older platforms */
144DECLARE_INIT_STAGES;
145
Willy Tarreauf4596402021-04-10 16:53:05 +0200146/* create a read_mostly section to hold variables which are accessed a lot
147 * but which almost never change. The purpose is to isolate them in their
148 * own cache lines where they don't risk to be perturbated by write accesses
149 * to neighbor variables. We need to create an empty aligned variable for
150 * this. The fact that the variable is of size zero means that it will be
151 * eliminated at link time if no other variable uses it, but alignment will
152 * be respected.
153 */
154empty_t __read_mostly_align HA_SECTION("read_mostly") ALIGNED(64);
155
Willy Tarreauf0d3b732021-05-06 16:30:32 +0200156#ifdef BUILD_FEATURES
157const char *build_features = BUILD_FEATURES;
158#else
159const char *build_features = "";
160#endif
161
Willy Tarreau477ecd82010-01-03 21:12:30 +0100162/* list of config files */
163static struct list cfg_cfgfiles = LIST_HEAD_INIT(cfg_cfgfiles);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200164int pid; /* current process id */
165
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100166volatile unsigned long sleeping_thread_mask = 0; /* Threads that are about to sleep in poll() */
Willy Tarreau4b3f27b2020-03-12 17:28:01 +0100167volatile unsigned long stopping_thread_mask = 0; /* Threads acknowledged stopping */
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100168
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169/* global options */
170struct global global = {
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100171 .hard_stop_after = TICK_ETERNITY,
Remi Tricot-Le Bretonb5d968d2022-04-08 18:04:18 +0200172 .close_spread_time = TICK_ETERNITY,
173 .close_spread_end = TICK_ETERNITY,
Amaury Denoyelle0f50cb92021-03-26 18:50:33 +0100174 .numa_cpu_mapping = 1,
Willy Tarreau149ab772019-01-26 14:27:06 +0100175 .nbthread = 0,
William Lallemand5f232402012-04-05 18:02:55 +0200176 .req_count = 0,
William Lallemand0f99e342011-10-12 17:50:54 +0200177 .logsrvs = LIST_HEAD_INIT(global.logsrvs),
William Lallemand9d5f5482012-11-07 16:12:57 +0100178 .maxzlibmem = 0,
William Lallemandd85f9172012-11-09 17:05:39 +0100179 .comp_rate_lim = 0,
Emeric Brun850efd52014-01-29 12:24:34 +0100180 .ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED,
Emeric Bruned760922010-10-22 17:59:25 +0200181 .unix_bind = {
182 .ux = {
183 .uid = -1,
184 .gid = -1,
185 .mode = 0,
186 }
187 },
Willy Tarreau27a674e2009-08-17 07:23:33 +0200188 .tune = {
Willy Tarreau7ac908b2019-02-27 12:02:18 +0100189 .options = GTUNE_LISTENER_MQ,
Willy Tarreauc77d3642018-12-12 06:19:42 +0100190 .bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
Christopher Faulet546c4692020-01-22 14:31:21 +0100191 .maxrewrite = MAXREWRITE,
Willy Tarreaua24adf02014-11-27 01:11:56 +0100192 .reserved_bufs = RESERVED_BUFS,
Willy Tarreauf3045d22015-04-29 16:24:50 +0200193 .pattern_cache = DEFAULT_PAT_LRU_SIZE,
Olivier Houchard88698d92019-04-16 19:07:22 +0200194 .pool_low_ratio = 20,
195 .pool_high_ratio = 25,
Christopher Faulet41ba36f2019-07-19 09:36:45 +0200196 .max_http_hdr = MAX_HTTP_HDR,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200197#ifdef USE_OPENSSL
Emeric Brun46635772012-11-14 11:32:56 +0100198 .sslcachesize = SSLCACHESIZE,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200199#endif
William Lallemandf3747832012-11-09 12:33:10 +0100200 .comp_maxlevel = 1,
Willy Tarreau7e312732014-02-12 16:35:14 +0100201#ifdef DEFAULT_IDLE_TIMER
202 .idle_timer = DEFAULT_IDLE_TIMER,
203#else
204 .idle_timer = 1000, /* 1 second */
205#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200206 },
Emeric Brun76d88952012-10-05 15:47:31 +0200207#ifdef USE_OPENSSL
208#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200209 .maxsslconn = DEFAULT_MAXSSLCONN,
210#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200211#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212 /* others NULL OK */
213};
214
215/*********************************************************************/
216
217int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100218int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200219int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100220int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100221int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100222int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreau392524d2022-02-17 18:10:36 +0100223int arg_mode = 0; /* MODE_DEBUG etc as passed on command line ... */
224char *change_dir = NULL; /* set when -C is passed */
225char *check_condition = NULL; /* check condition passed to -cc */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500227/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 * or kill. We will send them a signal every 10 ms until we can bind to all
229 * our ports. With 200 retries, that's about 2 seconds.
230 */
231#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200232static int *oldpids = NULL;
233static int oldpids_sig; /* use USR1 or TERM */
234
Olivier Houchardf73629d2017-04-05 22:33:04 +0200235/* Path to the unix socket we use to retrieve listener sockets from the old process */
236static const char *old_unixsocket;
237
William Lallemandcb11fd22017-06-01 17:38:52 +0200238int atexit_flag = 0;
239
Willy Tarreaubb545b42010-08-25 12:58:59 +0200240int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241const int zero = 0;
242const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200243const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100245char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200246char *localpeer = NULL;
Willy Tarreau76871a42022-03-08 16:01:40 +0100247static char *kwd_dump = NULL; // list of keyword dumps to produce
Willy Tarreaubaaee002006-06-26 02:48:02 +0200248
William Lallemand00417412020-06-05 14:08:41 +0200249static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200250
William Lallemandbc193052018-09-11 10:06:26 +0200251struct list proc_list = LIST_HEAD_INIT(proc_list);
252
253int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100254unsigned int rlim_fd_cur_at_boot = 0;
255unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200256
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100257/* per-boot randomness */
258unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
259
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200260/* takes the thread config in argument or NULL for any thread */
William Lallemandb3f2be32018-09-11 10:06:18 +0200261static void *run_thread_poll_loop(void *data);
262
Willy Tarreauff055502014-04-28 22:27:06 +0200263/* bitfield of a few warnings to emit just once (WARN_*) */
264unsigned int warned = 0;
265
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200266/* set if experimental features have been used for the current process */
Willy Tarreauedd42682022-02-25 10:10:00 +0100267unsigned int tainted = 0;
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200268
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200269unsigned int experimental_directives_allowed = 0;
270
271int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
272 char **errmsg)
273{
274 if (kw->flags & KWF_EXPERIMENTAL) {
275 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200276 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 +0200277 file, linenum, kw->kw);
278 return 1;
279 }
280 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
281 }
282
283 return 0;
284}
285
William Lallemande7361152018-10-26 14:47:36 +0200286/* master CLI configuration (-S flag) */
287struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100288
289/* These are strings to be reported in the output of "haproxy -vv". They may
290 * either be constants (in which case must_free must be zero) or dynamically
291 * allocated strings to pass to free() on exit, and in this case must_free
292 * must be non-zero.
293 */
294struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
295struct build_opts_str {
296 struct list list;
297 const char *str;
298 int must_free;
299};
300
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301/*********************************************************************/
302/* general purpose functions ***************************************/
303/*********************************************************************/
304
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100305/* used to register some build option strings at boot. Set must_free to
306 * non-zero if the string must be freed upon exit.
307 */
308void hap_register_build_opts(const char *str, int must_free)
309{
310 struct build_opts_str *b;
311
312 b = calloc(1, sizeof(*b));
313 if (!b) {
314 fprintf(stderr, "out of memory\n");
315 exit(1);
316 }
317 b->str = str;
318 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200319 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100320}
321
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200322#define VERSION_MAX_ELTS 7
323
324/* This function splits an haproxy version string into an array of integers.
325 * The syntax of the supported version string is the following:
326 *
327 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
328 *
329 * This validates for example:
330 * 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
331 * 2.4-dev18-f6818d-20
332 *
333 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
334 * one fixed place in the array. The tags take a numeric value called <e> which
335 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
336 * considered as zero (henxe 1.5 and 1.5.0 are the same).
337 *
338 * The resulting values are:
339 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
340 * 1.2.1 1, 2, 1, 0, 3, 0, 0
341 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
342 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
343 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
344 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
345 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
346 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
347 *
348 * The function returns non-zero if the conversion succeeded, or zero if it
349 * failed.
350 */
351int split_version(const char *version, unsigned int *value)
352{
353 const char *p, *s;
354 char *error;
355 int nelts;
356
357 /* Initialize array with zeroes */
358 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
359 value[nelts] = 0;
360 value[4] = 3;
361
362 p = version;
363
364 /* If the version number is empty, return false */
365 if (*p == '\0')
366 return 0;
367
368 /* Convert first number <a> */
369 value[0] = strtol(p, &error, 10);
370 p = error + 1;
371 if (*error == '\0')
372 return 1;
373 if (*error == '-')
374 goto split_version_tag;
375 if (*error != '.')
376 return 0;
377
378 /* Convert first number <b> */
379 value[1] = strtol(p, &error, 10);
380 p = error + 1;
381 if (*error == '\0')
382 return 1;
383 if (*error == '-')
384 goto split_version_tag;
385 if (*error != '.')
386 return 0;
387
388 /* Convert first number <c> */
389 value[2] = strtol(p, &error, 10);
390 p = error + 1;
391 if (*error == '\0')
392 return 1;
393 if (*error == '-')
394 goto split_version_tag;
395 if (*error != '.')
396 return 0;
397
398 /* Convert first number <d> */
399 value[3] = strtol(p, &error, 10);
400 p = error + 1;
401 if (*error == '\0')
402 return 1;
403 if (*error != '-')
404 return 0;
405
406 split_version_tag:
407 /* Check for commit number */
408 if (*p >= '0' && *p <= '9')
409 goto split_version_commit;
410
411 /* Read tag */
412 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
413 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
414 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
415 else
416 goto split_version_commit;
417
418 /* Convert tag number */
419 value[5] = strtol(p, &error, 10);
420 p = error + 1;
421 if (*error == '\0')
422 return 1;
423 if (*error != '-')
424 return 0;
425
426 split_version_commit:
427 /* Search the last "-" */
428 s = strrchr(p, '-');
429 if (s) {
430 s++;
431 if (*s == '\0')
432 return 0;
433 value[6] = strtol(s, &error, 10);
434 if (*error != '\0')
435 value[6] = 0;
436 return 1;
437 }
438
439 /* convert the version */
440 value[6] = strtol(p, &error, 10);
441 if (*error != '\0')
442 value[6] = 0;
443
444 return 1;
445}
446
447/* This function compares the current haproxy version with an arbitrary version
448 * string. It returns:
449 * -1 : the version in argument is older than the current haproxy version
450 * 0 : the version in argument is the same as the current haproxy version
451 * 1 : the version in argument is newer than the current haproxy version
452 *
453 * Or some errors:
454 * -2 : the current haproxy version is not parsable
455 * -3 : the version in argument is not parsable
456 */
457int compare_current_version(const char *version)
458{
459 unsigned int loc[VERSION_MAX_ELTS];
460 unsigned int mod[VERSION_MAX_ELTS];
461 int i;
462
463 /* split versions */
464 if (!split_version(haproxy_version, loc))
465 return -2;
466 if (!split_version(version, mod))
467 return -3;
468
469 /* compare versions */
470 for (i = 0; i < VERSION_MAX_ELTS; i++) {
471 if (mod[i] < loc[i])
472 return -1;
473 else if (mod[i] > loc[i])
474 return 1;
475 }
476 return 0;
477}
478
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100479static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200480{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200481 struct utsname utsname;
482
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200483 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100484 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100485
486 if (strlen(PRODUCT_URL_BUGS) > 0) {
487 char base_version[20];
488 int dots = 0;
489 char *del;
490
491 /* only retrieve the base version without distro-specific extensions */
492 for (del = haproxy_version; *del; del++) {
493 if (*del == '.')
494 dots++;
495 else if (*del < '0' || *del > '9')
496 break;
497 }
498
499 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
500 if (dots < 2)
501 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
502 else
503 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
504 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200505
506 if (uname(&utsname) == 0) {
507 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
508 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200509}
510
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100511static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100512{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100513 struct build_opts_str *item;
514
Willy Tarreau7b066db2007-12-02 11:28:59 +0100515 printf("Build options :"
516#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100517 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100518#endif
519#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100520 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100521#endif
522#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100523 "\n CC = " BUILD_CC
524#endif
525#ifdef BUILD_CFLAGS
526 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100527#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100528#ifdef BUILD_OPTIONS
529 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100530#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100531#ifdef BUILD_DEBUG
532 "\n DEBUG = " BUILD_DEBUG
533#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100534#ifdef BUILD_FEATURES
535 "\n\nFeature list : " BUILD_FEATURES
536#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200537 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100538 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200539 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100540 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200541
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100542 list_for_each_entry(item, &build_opts_list, list) {
543 puts(item->str);
544 }
545
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100546 putchar('\n');
547
Willy Tarreaube5b6852009-10-03 18:57:08 +0200548 list_pollers(stdout);
549 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200550 list_mux_proto(stdout);
551 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100552 list_services(stdout);
553 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100554 list_filters(stdout);
555 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100556}
557
Willy Tarreaubaaee002006-06-26 02:48:02 +0200558/*
559 * This function prints the command line usage and exits
560 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100561static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200562{
563 display_version();
564 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200565 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200567 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100568 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200569 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreauf4b79c42022-02-23 15:20:53 +0100570 " -dM[<byte>,help,...] debug memory (default: poison with <byte>/0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200571 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200572 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200573 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100574#if defined(USE_SYSTEMD)
575 " -Ws master-worker mode with systemd notify support.\n"
576#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200578 " -c check mode : only check config files and exit\n"
Maximilian Maderfc0cceb2021-06-06 00:50:22 +0200579 " -cc check condition : evaluate a condition and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100580 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581 " -m limits the usable amount of memory (in MB)\n"
582 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200583 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200584 " -p writes pids of all children to this file\n"
Willy Tarreaue5733232019-05-22 19:24:06 +0200585#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200586 " -de disables epoll() usage even when available\n"
587#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200588#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200589 " -dk disables kqueue() usage even when available\n"
590#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200591#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000592 " -dv disables event ports usage even when available\n"
593#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200594#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 " -dp disables poll() usage even when available\n"
596#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200597#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100598 " -dS disables splice usage (broken on old kernels)\n"
599#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200600#if defined(USE_GETADDRINFO)
601 " -dG disables getaddrinfo() usage\n"
602#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000603#if defined(SO_REUSEPORT)
604 " -dR disables SO_REUSEPORT usage\n"
605#endif
Willy Tarreau654726d2021-12-28 15:43:11 +0100606#if defined(HA_HAVE_DUMP_LIBS)
607 " -dL dumps loaded object files after config checks\n"
608#endif
Willy Tarreau76871a42022-03-08 16:01:40 +0100609 " -dK{class[,...]} dump registered keywords (use 'help' for list)\n"
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100610 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100611 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200612 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200613 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200614 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200615 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200616 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200617 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100618 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200619 exit(1);
620}
621
622
623
624/*********************************************************************/
625/* more specific functions ***************************************/
626/*********************************************************************/
627
William Lallemand73b85e72017-06-01 17:38:51 +0200628/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
629 * pids the signal was correctly delivered to.
630 */
William Lallemande25473c2019-04-01 11:29:56 +0200631int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200632{
633 int p;
634 int ret = 0;
635 for (p = 0; p < nb_oldpids; p++)
636 if (kill(oldpids[p], sig) == 0)
637 ret++;
638 return ret;
639}
640
William Lallemand75ea0a02017-11-15 19:02:58 +0100641/*
William Lallemand73b85e72017-06-01 17:38:51 +0200642 * remove a pid forom the olpid array and decrease nb_oldpids
643 * return 1 pid was found otherwise return 0
644 */
645
646int delete_oldpid(int pid)
647{
648 int i;
649
650 for (i = 0; i < nb_oldpids; i++) {
651 if (oldpids[i] == pid) {
652 oldpids[i] = oldpids[nb_oldpids - 1];
653 oldpids[nb_oldpids - 1] = 0;
654 nb_oldpids--;
655 return 1;
656 }
657 }
658 return 0;
659}
660
William Lallemand85b0bd92017-06-01 17:38:53 +0200661
William Lallemand73b85e72017-06-01 17:38:51 +0200662/*
663 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800664 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200665 */
William Lallemandfab0fdc2021-11-09 18:01:22 +0100666static void mworker_reexec()
William Lallemand73b85e72017-06-01 17:38:51 +0200667{
William Lallemand00417412020-06-05 14:08:41 +0200668 char **next_argv = NULL;
669 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200670 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200671 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200672 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100673 struct rlimit limit;
William Lallemand2be557f2021-11-24 18:45:37 +0100674 struct mworker_proc *current_child = NULL;
William Lallemand73b85e72017-06-01 17:38:51 +0200675
676 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100677#if defined(USE_SYSTEMD)
678 if (global.tune.options & GTUNE_USE_SYSTEMD)
679 sd_notify(0, "RELOADING=1");
680#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200681 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
682
William Lallemand55a921c2022-01-28 21:17:30 +0100683 mworker_cleanup_proc();
William Lallemandbc193052018-09-11 10:06:26 +0200684 mworker_proc_list_to_env(); /* put the children description in the env */
685
William Lallemandc4810b82021-11-18 10:51:30 +0100686 /* ensure that we close correctly every listeners before reexecuting */
687 mworker_cleanlisteners();
688
William Lallemand7c756a82018-11-26 11:53:40 +0100689 /* during the reload we must ensure that every FDs that can't be
690 * reuse (ie those that are not referenced in the proc_list)
691 * are closed or they will leak. */
692
693 /* close the listeners FD */
694 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200695
William Lallemand67e371e2021-11-25 10:03:44 +0100696 if (fdtab)
697 deinit_pollers();
William Lallemandefd95472021-11-26 14:43:57 +0100698
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500699#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200700 /* close random device FDs */
701 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100702#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100703
Willy Tarreau8dca1952019-03-01 10:21:55 +0100704 /* restore the initial FD limits */
705 limit.rlim_cur = rlim_fd_cur_at_boot;
706 limit.rlim_max = rlim_fd_max_at_boot;
707 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
708 getrlimit(RLIMIT_NOFILE, &limit);
709 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
710 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
711 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
712 }
713
William Lallemand73b85e72017-06-01 17:38:51 +0200714 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200715 while (old_argv[old_argc])
716 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200717
William Lallemand85b0bd92017-06-01 17:38:53 +0200718 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200719 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200720 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200721 if (next_argv == NULL)
722 goto alloc_error;
723
William Lallemand00417412020-06-05 14:08:41 +0200724 /* copy the program name */
725 next_argv[next_argc++] = old_argv[0];
726
727 /* insert the new options just after argv[0] in case we have a -- */
728
William Lallemandbefab9e2021-11-25 00:49:19 +0100729 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
730 /* add -sf <PID>* to argv */
731 if (mworker_child_nb() > 0) {
732 struct mworker_proc *child;
William Lallemand3f128872019-04-01 11:29:59 +0200733
William Lallemandbefab9e2021-11-25 00:49:19 +0100734 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200735
William Lallemandbefab9e2021-11-25 00:49:19 +0100736 list_for_each_entry(child, &proc_list, list) {
737 if (!(child->options & PROC_O_LEAVING) && (child->options & PROC_O_TYPE_WORKER))
738 current_child = child;
William Lallemand2be557f2021-11-24 18:45:37 +0100739
William Lallemandbefab9e2021-11-25 00:49:19 +0100740 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1)
741 continue;
742 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
743 goto alloc_error;
744 msg = NULL;
745 }
William Lallemand73b85e72017-06-01 17:38:51 +0200746 }
William Lallemand2be557f2021-11-24 18:45:37 +0100747
748 if (current_child) {
749 /* add the -x option with the socketpair of the current worker */
750 next_argv[next_argc++] = "-x";
751 if ((next_argv[next_argc++] = memprintf(&msg, "sockpair@%d", current_child->ipc_fd[0])) == NULL)
752 goto alloc_error;
753 msg = NULL;
754 }
William Lallemand85b0bd92017-06-01 17:38:53 +0200755 }
756
William Lallemand00417412020-06-05 14:08:41 +0200757 /* copy the previous options */
758 for (i = 1; i < old_argc; i++)
759 next_argv[next_argc++] = old_argv[i];
760
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200761 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100762 execvp(next_argv[0], next_argv);
Christopher Faulet767a84b2017-11-24 16:50:31 +0100763 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100764 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100765 return;
766
William Lallemand73b85e72017-06-01 17:38:51 +0200767alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100768 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800769 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200770 return;
771}
772
William Lallemandfab0fdc2021-11-09 18:01:22 +0100773/* reexec haproxy in waitmode */
774static void mworker_reexec_waitmode()
775{
776 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
777 mworker_reexec();
778}
779
780/* reload haproxy and emit a warning */
781void mworker_reload()
782{
William Lallemandad221f42021-11-09 18:43:59 +0100783 struct mworker_proc *child;
William Lallemandefd95472021-11-26 14:43:57 +0100784 struct per_thread_deinit_fct *ptdf;
William Lallemandad221f42021-11-09 18:43:59 +0100785
William Lallemand836bda22021-11-09 18:16:47 +0100786 ha_notice("Reloading HAProxy\n");
William Lallemandad221f42021-11-09 18:43:59 +0100787
William Lallemandefd95472021-11-26 14:43:57 +0100788 /* close the poller FD and the thread waker pipe FD */
789 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
790 ptdf->fct();
791
William Lallemandad221f42021-11-09 18:43:59 +0100792 /* increment the number of reloads */
793 list_for_each_entry(child, &proc_list, list) {
794 child->reloads++;
795 }
796
William Lallemandfab0fdc2021-11-09 18:01:22 +0100797 mworker_reexec();
798}
799
William Lallemandb3f2be32018-09-11 10:06:18 +0200800static void mworker_loop()
801{
802
803#if defined(USE_SYSTEMD)
804 if (global.tune.options & GTUNE_USE_SYSTEMD)
805 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
806#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200807 /* Busy polling makes no sense in the master :-) */
808 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200809
William Lallemandbc193052018-09-11 10:06:26 +0200810
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100811 signal_unregister(SIGTTIN);
812 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100813 signal_unregister(SIGUSR1);
814 signal_unregister(SIGHUP);
815 signal_unregister(SIGQUIT);
816
William Lallemandb3f2be32018-09-11 10:06:18 +0200817 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
818 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100819 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
820 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200821 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
822 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
823 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
824 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
825
826 mworker_unblock_signals();
William Lallemand27f3fa52018-12-06 14:05:20 +0100827 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200828
William Lallemandbc193052018-09-11 10:06:26 +0200829 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
830 some SIGCHLD were lost */
831
William Lallemandb3f2be32018-09-11 10:06:18 +0200832 global.nbthread = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200833
William Lallemand2672eb92018-12-14 15:52:39 +0100834#ifdef USE_THREAD
835 tid_bit = 1;
836 all_threads_mask = 1;
837#endif
838
William Lallemandb3f2be32018-09-11 10:06:18 +0200839 jobs++; /* this is the "master" job, we want to take care of the
840 signals even if there is no listener so the poll loop don't
841 leave */
842
843 fork_poller();
Willy Tarreau43ab05b2021-09-28 09:43:11 +0200844 run_thread_poll_loop(NULL);
William Lallemandb3f2be32018-09-11 10:06:18 +0200845}
William Lallemandcb11fd22017-06-01 17:38:52 +0200846
847/*
848 * Reexec the process in failure mode, instead of exiting
849 */
850void reexec_on_failure()
851{
William Lallemand68836742021-11-10 10:49:06 +0100852 struct mworker_proc *child;
853
William Lallemandcb11fd22017-06-01 17:38:52 +0200854 if (!atexit_flag)
855 return;
William Lallemand68836742021-11-10 10:49:06 +0100856
857 /* get the info of the children in the env */
858 if (mworker_env_to_proc_list() < 0) {
859 exit(EXIT_FAILURE);
860 }
861
862 /* increment the number of failed reloads */
863 list_for_each_entry(child, &proc_list, list) {
864 child->failedreloads++;
865 }
866
Willy Tarreaue08acae2022-01-28 18:40:06 +0100867 /* do not keep unused FDs retrieved from the previous process */
868 sock_drop_unused_old_sockets();
869
William Lallemandfab0fdc2021-11-09 18:01:22 +0100870 usermsgs_clr(NULL);
William Lallemand836bda22021-11-09 18:16:47 +0100871 ha_warning("Loading failure!\n");
William Lallemandfab0fdc2021-11-09 18:01:22 +0100872 mworker_reexec_waitmode();
William Lallemandcb11fd22017-06-01 17:38:52 +0200873}
William Lallemand73b85e72017-06-01 17:38:51 +0200874
875
876/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200877 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
878 * a signal zero to all subscribers. This means that it's as easy as
879 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200880 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100881static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882{
883 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200884 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100885 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200886}
887
888/*
889 * upon SIGTTOU, we pause everything
890 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100891static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892{
Willy Tarreau775e0012020-09-24 16:36:26 +0200893 if (protocol_pause_all() & ERR_FATAL) {
894 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200895 ha_warning("%s", msg);
896 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200897 soft_stop();
898 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100899 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900}
901
902/*
903 * upon SIGTTIN, let's have a soft stop.
904 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100905static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200906{
Willy Tarreau775e0012020-09-24 16:36:26 +0200907 if (protocol_resume_all() & ERR_FATAL) {
908 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 +0200909 ha_warning("%s", msg);
910 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200911 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200912}
913
914/*
915 * this function dumps every server's state when the process receives SIGHUP.
916 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100917static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100919 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200920
Christopher Faulet767a84b2017-11-24 16:50:31 +0100921 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200922 while (p) {
923 struct server *s = p->srv;
924
925 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
926 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100927 chunk_printf(&trash,
928 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
929 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200930 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200931 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200932 ha_warning("%s\n", trash.area);
933 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200934 s = s->next;
935 }
936
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200937 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
938 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100939 chunk_printf(&trash,
940 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
941 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200942 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 +0200943 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100944 chunk_printf(&trash,
945 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
946 p->id,
947 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200948 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 +0200949 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100950 chunk_printf(&trash,
951 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
952 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
953 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200954 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 +0200955 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200956 ha_warning("%s\n", trash.area);
957 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200958
959 p = p->next;
960 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200961}
962
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100963static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200965 /* dump memory usage then free everything possible */
966 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100967 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968}
969
William Lallemande1340412017-12-28 16:09:36 +0100970/*
971 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
972 * If <fd> < 0, it opens /dev/null and use it to dup
973 *
974 * In the case of chrooting, you have to open /dev/null before the chroot, and
975 * pass the <fd> to this function
976 */
977static void stdio_quiet(int fd)
978{
979 if (fd < 0)
980 fd = open("/dev/null", O_RDWR, 0);
981
982 if (fd > -1) {
983 fclose(stdin);
984 fclose(stdout);
985 fclose(stderr);
986
987 dup2(fd, 0);
988 dup2(fd, 1);
989 dup2(fd, 2);
990 if (fd > 2)
991 close(fd);
992 return;
993 }
994
995 ha_alert("Cannot open /dev/null\n");
996 exit(EXIT_FAILURE);
997}
998
999
Joseph Herlant03420902018-11-15 10:41:50 -08001000/* This function checks if cfg_cfgfiles contains directories.
1001 * If it finds one, it adds all the files (and only files) it contains
1002 * in cfg_cfgfiles in place of the directory (and removes the directory).
1003 * It adds the files in lexical order.
1004 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001005 * It doesn't add files with name starting with '.'
1006 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001007static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001008{
1009 struct wordlist *wl, *wlb;
1010 char *err = NULL;
1011
1012 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1013 struct stat file_stat;
1014 struct dirent **dir_entries = NULL;
1015 int dir_entries_nb;
1016 int dir_entries_it;
1017
1018 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001019 ha_alert("Cannot open configuration file/directory %s : %s\n",
1020 wl->s,
1021 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001022 exit(1);
1023 }
1024
1025 if (!S_ISDIR(file_stat.st_mode))
1026 continue;
1027
1028 /* from this point wl->s is a directory */
1029
1030 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1031 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001032 ha_alert("Cannot open configuration directory %s : %s\n",
1033 wl->s,
1034 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001035 exit(1);
1036 }
1037
1038 /* for each element in the directory wl->s */
1039 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1040 struct dirent *dir_entry = dir_entries[dir_entries_it];
1041 char *filename = NULL;
1042 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1043
1044 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001045 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001046 */
1047 if (dir_entry->d_name[0] == '.' ||
1048 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1049 goto next_dir_entry;
1050
1051 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001052 ha_alert("Cannot load configuration files %s : out of memory.\n",
1053 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001054 exit(1);
1055 }
1056
1057 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001058 ha_alert("Cannot open configuration file %s : %s\n",
1059 wl->s,
1060 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001061 exit(1);
1062 }
1063
1064 /* don't add anything else than regular file in cfg_cfgfiles
1065 * this way we avoid loops
1066 */
1067 if (!S_ISREG(file_stat.st_mode))
1068 goto next_dir_entry;
1069
1070 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001071 ha_alert("Cannot load configuration files %s : %s\n",
1072 filename,
1073 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001074 exit(1);
1075 }
1076
1077next_dir_entry:
1078 free(filename);
1079 free(dir_entry);
1080 }
1081
1082 free(dir_entries);
1083
1084 /* remove the current directory (wl) from cfg_cfgfiles */
1085 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001086 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001087 free(wl);
1088 }
1089
1090 free(err);
1091}
1092
Willy Tarreaubaaee002006-06-26 02:48:02 +02001093/*
William Lallemand73b85e72017-06-01 17:38:51 +02001094 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001095 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001096 * Return an allocated copy of argv
1097 */
1098
1099static char **copy_argv(int argc, char **argv)
1100{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001101 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001102
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001103 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001104 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001105 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001106 return NULL;
1107 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001108 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001109
William Lallemanddf6c5a82020-06-04 17:40:23 +02001110 /* first copy argv[0] */
1111 *newargv++ = *argv++;
1112 argc--;
1113
1114 while (argc > 0) {
1115 if (**argv != '-') {
1116 /* non options are copied but will fail in the argument parser */
1117 *newargv++ = *argv++;
1118 argc--;
1119
1120 } else {
1121 char *flag;
1122
1123 flag = *argv + 1;
1124
1125 if (flag[0] == '-' && flag[1] == 0) {
1126 /* "--\0" copy every arguments till the end of argv */
1127 *newargv++ = *argv++;
1128 argc--;
1129
1130 while (argc > 0) {
1131 *newargv++ = *argv++;
1132 argc--;
1133 }
1134 } else {
1135 switch (*flag) {
1136 case 's':
1137 /* -sf / -st and their parameters are ignored */
1138 if (flag[1] == 'f' || flag[1] == 't') {
1139 argc--;
1140 argv++;
1141 /* The list can't contain a negative value since the only
1142 way to know the end of this list is by looking for the
1143 next option or the end of the options */
1144 while (argc > 0 && argv[0][0] != '-') {
1145 argc--;
1146 argv++;
1147 }
William Lallemand398da622020-09-02 16:12:23 +02001148 } else {
1149 argc--;
1150 argv++;
1151
William Lallemanddf6c5a82020-06-04 17:40:23 +02001152 }
1153 break;
1154
1155 case 'x':
1156 /* this option and its parameter are ignored */
1157 argc--;
1158 argv++;
1159 if (argc > 0) {
1160 argc--;
1161 argv++;
1162 }
1163 break;
1164
1165 case 'C':
1166 case 'n':
1167 case 'm':
1168 case 'N':
1169 case 'L':
1170 case 'f':
1171 case 'p':
1172 case 'S':
1173 /* these options have only 1 parameter which must be copied and can start with a '-' */
1174 *newargv++ = *argv++;
1175 argc--;
1176 if (argc == 0)
1177 goto error;
1178 *newargv++ = *argv++;
1179 argc--;
1180 break;
1181 default:
1182 /* for other options just copy them without parameters, this is also done
1183 * for options like "--foo", but this will fail in the argument parser.
1184 * */
1185 *newargv++ = *argv++;
1186 argc--;
1187 break;
1188 }
William Lallemand73b85e72017-06-01 17:38:51 +02001189 }
1190 }
William Lallemand73b85e72017-06-01 17:38:51 +02001191 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001192
William Lallemanddf6c5a82020-06-04 17:40:23 +02001193 return retargv;
1194
1195error:
1196 free(retargv);
1197 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001198}
1199
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001200
1201/* Performs basic random seed initialization. The main issue with this is that
1202 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1203 * which means that there will only be 4 billion possible random sequences once
1204 * srandom() is called, regardless of the internal state. Not calling it is
1205 * even worse as we'll always produce the same randoms sequences. What we do
1206 * here is to create an initial sequence from various entropy sources, hash it
1207 * using SHA1 and keep the resulting 160 bits available globally.
1208 *
1209 * We initialize the current process with the first 32 bits before starting the
1210 * polling loop, where all this will be changed to have process specific and
1211 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001212 *
1213 * Before starting threads, it's still possible to call random() as srandom()
1214 * is initialized from this, but after threads and/or processes are started,
1215 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001216 */
1217static void ha_random_boot(char *const *argv)
1218{
1219 unsigned char message[256];
1220 unsigned char *m = message;
1221 struct timeval tv;
1222 blk_SHA_CTX ctx;
1223 unsigned long l;
1224 int fd;
1225 int i;
1226
1227 /* start with current time as pseudo-random seed */
1228 gettimeofday(&tv, NULL);
1229 write_u32(m, tv.tv_sec); m += 4;
1230 write_u32(m, tv.tv_usec); m += 4;
1231
1232 /* PID and PPID add some OS-based randomness */
1233 write_u16(m, getpid()); m += 2;
1234 write_u16(m, getppid()); m += 2;
1235
1236 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1237 fd = open("/dev/urandom", O_RDONLY);
1238 if (fd >= 0) {
1239 i = read(fd, m, 20);
1240 if (i > 0)
1241 m += i;
1242 close(fd);
1243 }
1244
1245 /* take up to 160 bits bytes from openssl (non-blocking) */
1246#ifdef USE_OPENSSL
1247 if (RAND_bytes(m, 20) == 1)
1248 m += 20;
1249#endif
1250
1251 /* take 160 bits from existing random in case it was already initialized */
1252 for (i = 0; i < 5; i++) {
1253 write_u32(m, random());
1254 m += 4;
1255 }
1256
1257 /* stack address (benefit form operating system's ASLR) */
1258 l = (unsigned long)&m;
1259 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1260
1261 /* argv address (benefit form operating system's ASLR) */
1262 l = (unsigned long)&argv;
1263 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1264
1265 /* use tv_usec again after all the operations above */
1266 gettimeofday(&tv, NULL);
1267 write_u32(m, tv.tv_usec); m += 4;
1268
1269 /*
1270 * At this point, ~84-92 bytes have been used
1271 */
1272
1273 /* finish with the hostname */
1274 strncpy((char *)m, hostname, message + sizeof(message) - m);
1275 m += strlen(hostname);
1276
1277 /* total message length */
1278 l = m - message;
1279
1280 memset(&ctx, 0, sizeof(ctx));
1281 blk_SHA1_Init(&ctx);
1282 blk_SHA1_Update(&ctx, message, l);
1283 blk_SHA1_Final(boot_seed, &ctx);
1284
1285 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001286 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001287}
1288
Willy Tarreau5a023f02019-03-01 14:19:31 +01001289/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1290 * setting, and returns it. It may return -1 meaning "unlimited" if some
1291 * unlimited proxies have been found and the global.maxconn value is not yet
1292 * set. It may also return a value greater than maxconn if it's not yet set.
1293 * Note that a value of zero means there is no need for pipes. -1 is never
1294 * returned if global.maxconn is valid.
1295 */
1296static int compute_ideal_maxpipes()
1297{
1298 struct proxy *cur;
1299 int nbfe = 0, nbbe = 0;
1300 int unlimited = 0;
1301 int pipes;
1302 int max;
1303
1304 for (cur = proxies_list; cur; cur = cur->next) {
1305 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1306 if (cur->cap & PR_CAP_FE) {
1307 max = cur->maxconn;
1308 nbfe += max;
1309 if (!max) {
1310 unlimited = 1;
1311 break;
1312 }
1313 }
1314 if (cur->cap & PR_CAP_BE) {
1315 max = cur->fullconn ? cur->fullconn : global.maxconn;
1316 nbbe += max;
1317 if (!max) {
1318 unlimited = 1;
1319 break;
1320 }
1321 }
1322 }
1323 }
1324
1325 pipes = MAX(nbfe, nbbe);
1326 if (global.maxconn) {
1327 if (pipes > global.maxconn || unlimited)
1328 pipes = global.maxconn;
1329 } else if (unlimited) {
1330 pipes = -1;
1331 }
1332
1333 return pipes >= 4 ? pipes / 4 : pipes;
1334}
1335
Willy Tarreauac350932019-03-01 15:43:14 +01001336/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1337 * rlimits and computes an ideal maxconn. It's meant to be called only when
1338 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001339 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1340 * default 100) is returned as it is expected that it will even run on tight
1341 * environments, and will maintain compatibility with previous packages that
1342 * used to rely on this value as the default one. The system will emit a
1343 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001344 */
1345static int compute_ideal_maxconn()
1346{
1347 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1348 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1349 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001350 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001351 int maxconn;
1352
1353 /* we have to take into account these elements :
1354 * - number of engine_fds, which inflates the number of FD needed per
1355 * connection by this number.
1356 * - number of pipes per connection on average : for the unlimited
1357 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1358 * fixed value of 2*pipes.
1359 * - two FDs per connection
1360 */
1361
1362 /* subtract listeners and checks */
1363 remain -= global.maxsock;
1364
Willy Tarreau3f200852019-03-14 19:13:17 +01001365 /* one epoll_fd/kqueue_fd per thread */
1366 remain -= global.nbthread;
1367
1368 /* one wake-up pipe (2 fd) per thread */
1369 remain -= 2 * global.nbthread;
1370
Willy Tarreauac350932019-03-01 15:43:14 +01001371 /* Fixed pipes values : we only subtract them if they're not larger
1372 * than the remaining FDs because pipes are optional.
1373 */
1374 if (pipes >= 0 && pipes * 2 < remain)
1375 remain -= pipes * 2;
1376
1377 if (pipes < 0) {
1378 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1379 * = maxconn * (2 + 0.5 + engine_fds)
1380 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1381 */
1382 maxconn = 2 * remain / (5 + 2 * engine_fds);
1383 } else {
1384 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1385 * = maxconn * (2 + engine_fds)
1386 */
1387 maxconn = remain / (2 + engine_fds);
1388 }
1389
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001390 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001391}
1392
Willy Tarreaua409f302020-03-10 17:08:53 +01001393/* computes the estimated maxsock value for the given maxconn based on the
1394 * possibly set global.maxpipes and existing partial global.maxsock. It may
1395 * temporarily change global.maxconn for the time needed to propagate the
1396 * computations, and will reset it.
1397 */
1398static int compute_ideal_maxsock(int maxconn)
1399{
1400 int maxpipes = global.maxpipes;
1401 int maxsock = global.maxsock;
1402
1403
1404 if (!maxpipes) {
1405 int old_maxconn = global.maxconn;
1406
1407 global.maxconn = maxconn;
1408 maxpipes = compute_ideal_maxpipes();
1409 global.maxconn = old_maxconn;
1410 }
1411
1412 maxsock += maxconn * 2; /* each connection needs two sockets */
1413 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1414 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1415 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1416
1417 /* compute fd used by async engines */
1418 if (global.ssl_used_async_engines) {
1419 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1420
1421 maxsock += maxconn * sides * global.ssl_used_async_engines;
1422 }
1423 return maxsock;
1424}
1425
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001426/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001427 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1428 * value is accepted, non-zero otherwise. This is used to determine if an
1429 * automatic limit may be applied or not. When it is not, the caller knows that
1430 * the highest we can do is the rlim_max at boot. In case of error, we return
1431 * that the setting is possible, so that we defer the error processing to the
1432 * final stage in charge of enforcing this.
1433 */
1434static int check_if_maxsock_permitted(int maxsock)
1435{
1436 struct rlimit orig_limit, test_limit;
1437 int ret;
1438
1439 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1440 return 1;
1441
1442 /* don't go further if we can't even set to what we have */
1443 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1444 return 1;
1445
1446 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1447 test_limit.rlim_cur = test_limit.rlim_max;
1448 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1449
1450 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1451 return 1;
1452
1453 return ret == 0;
1454}
1455
Willy Tarreau34527d52022-02-17 17:45:58 +01001456/* This performs th every basic early initialization at the end of the PREPARE
1457 * init stage. It may only assume that list heads are initialized, but not that
1458 * anything else is correct. It will initialize a number of variables that
1459 * depend on command line and will pre-parse the command line. If it fails, it
1460 * directly exits.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001461 */
Willy Tarreau34527d52022-02-17 17:45:58 +01001462static void init_early(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001463{
Kevinm48936af2010-12-22 16:08:21 +00001464 char *progname;
Willy Tarreau34527d52022-02-17 17:45:58 +01001465 char *tmp;
1466 int len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467
Willy Tarreau34527d52022-02-17 17:45:58 +01001468 /* First, let's initialize most global variables */
1469 totalconn = actconn = listeners = stopping = 0;
1470 killed = pid = 0;
1471
1472 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
1473 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Christopher Faulete3a5e352017-10-24 13:53:54 +02001474 global.mode = MODE_STARTING;
William Lallemand73b85e72017-06-01 17:38:51 +02001475
Willy Tarreau34527d52022-02-17 17:45:58 +01001476 /* if we were in mworker mode, we should restart in mworker mode */
1477 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1478 global.mode |= MODE_MWORKER;
David du Colombier7af46052012-05-16 14:16:48 +02001479
Willy Tarreau34527d52022-02-17 17:45:58 +01001480 /* initialize date, time, and pid */
1481 tzset();
1482 clock_init_process_date();
1483 start_date = now;
1484 pid = getpid();
1485
1486 /* Set local host name and adjust some environment variables.
1487 * NB: POSIX does not make it mandatory for gethostname() to
1488 * NULL-terminate the string in case of truncation, and at least
1489 * FreeBSD appears not to do it.
Emeric Brun2b920a12010-09-23 18:30:22 +02001490 */
1491 memset(hostname, 0, sizeof(hostname));
1492 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001493
Willy Tarreau34527d52022-02-17 17:45:58 +01001494 /* preset some environment variables */
1495 localpeer = strdup(hostname);
1496 if (!localpeer || setenv("HAPROXY_LOCALPEER", localpeer, 1) < 0) {
Dragan Dosen4f014152020-06-18 16:56:47 +02001497 ha_alert("Cannot allocate memory for local peer.\n");
1498 exit(EXIT_FAILURE);
1499 }
Emeric Brun2b920a12010-09-23 18:30:22 +02001500
Willy Tarreau34527d52022-02-17 17:45:58 +01001501 /* Initialize the random generators */
1502#ifdef USE_OPENSSL
1503 /* Initialize SSL random generator. Must be called before chroot for
1504 * access to /dev/urandom, and before ha_random_boot() which may use
1505 * RAND_bytes().
Willy Tarreaubaaee002006-06-26 02:48:02 +02001506 */
Willy Tarreau34527d52022-02-17 17:45:58 +01001507 if (!ssl_initialize_random()) {
1508 ha_alert("OpenSSL random data generator initialization failed.\n");
1509 exit(EXIT_FAILURE);
1510 }
1511#endif
1512 ha_random_boot(argv); // the argv pointer brings some kernel-fed entropy
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001513
Willy Tarreau34527d52022-02-17 17:45:58 +01001514 /* Some CPU affinity stuff may have to be initialized */
1515#ifdef USE_CPU_AFFINITY
1516 {
1517 int i;
1518 ha_cpuset_zero(&cpu_map.proc);
1519 ha_cpuset_zero(&cpu_map.proc_t1);
1520 for (i = 0; i < MAX_THREADS; ++i) {
1521 ha_cpuset_zero(&cpu_map.thread[i]);
1522 }
1523 }
1524#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001525
Willy Tarreau34527d52022-02-17 17:45:58 +01001526 /* extract the program name from argv[0], it will be used for the logs
1527 * and error messages.
1528 */
1529 progname = *argv;
1530 while ((tmp = strchr(progname, '/')) != NULL)
1531 progname = tmp + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001532
Willy Tarreau34527d52022-02-17 17:45:58 +01001533 len = strlen(progname);
1534 progname = strdup(progname);
1535 if (!progname) {
1536 ha_alert("Cannot allocate memory for log_tag.\n");
1537 exit(EXIT_FAILURE);
1538 }
Willy Tarreau84310e22014-02-14 11:59:04 +01001539
Willy Tarreau34527d52022-02-17 17:45:58 +01001540 chunk_initlen(&global.log_tag, progname, len, len);
1541}
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001542
Willy Tarreau392524d2022-02-17 18:10:36 +01001543/* handles program arguments. Very minimal parsing is performed, variables are
1544 * fed with some values, and lists are completed with other ones. In case of
1545 * error, it will exit.
Willy Tarreau34527d52022-02-17 17:45:58 +01001546 */
Willy Tarreau392524d2022-02-17 18:10:36 +01001547static void init_args(int argc, char **argv)
Willy Tarreau34527d52022-02-17 17:45:58 +01001548{
Willy Tarreau34527d52022-02-17 17:45:58 +01001549 char *progname = global.log_tag.area;
Willy Tarreau392524d2022-02-17 18:10:36 +01001550 char *err_msg = NULL;
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001551
Willy Tarreau34527d52022-02-17 17:45:58 +01001552 /* pre-fill in the global tuning options before we let the cmdline
1553 * change them.
1554 */
Willy Tarreau43b78992009-01-25 15:42:27 +01001555 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001556#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001557 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001559#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001560 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001561#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001562#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001563 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001564#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001565#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001566 global.tune.options |= GTUNE_USE_EVPORTS;
1567#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001568#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001569 global.tune.options |= GTUNE_USE_SPLICE;
1570#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001571#if defined(USE_GETADDRINFO)
1572 global.tune.options |= GTUNE_USE_GAI;
1573#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001574#if defined(SO_REUSEPORT)
1575 global.tune.options |= GTUNE_USE_REUSEPORT;
1576#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001577#ifdef USE_THREAD
1578 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1579#endif
William Dauchya5194602020-03-28 19:29:58 +01001580 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581
Willy Tarreau392524d2022-02-17 18:10:36 +01001582 /* keep a copy of original arguments for the master process */
1583 old_argv = copy_argv(argc, argv);
1584 if (!old_argv) {
1585 ha_alert("failed to copy argv.\n");
1586 exit(EXIT_FAILURE);
1587 }
1588
1589 /* skip program name and start */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590 argc--; argv++;
1591 while (argc > 0) {
1592 char *flag;
1593
1594 if (**argv == '-') {
1595 flag = *argv+1;
1596
1597 /* 1 arg */
1598 if (*flag == 'v') {
1599 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001600 if (flag[1] == 'v') /* -vv */
1601 display_build_opts();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001602 exit(0);
1603 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001604#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001606 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001607#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001608#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001609 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001610 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001611#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001612#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001613 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001614 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001615#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001616#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001617 else if (*flag == 'd' && flag[1] == 'v')
1618 global.tune.options &= ~GTUNE_USE_EVPORTS;
1619#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001620#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001621 else if (*flag == 'd' && flag[1] == 'S')
1622 global.tune.options &= ~GTUNE_USE_SPLICE;
1623#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001624#if defined(USE_GETADDRINFO)
1625 else if (*flag == 'd' && flag[1] == 'G')
1626 global.tune.options &= ~GTUNE_USE_GAI;
1627#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001628#if defined(SO_REUSEPORT)
1629 else if (*flag == 'd' && flag[1] == 'R')
1630 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1631#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001632 else if (*flag == 'd' && flag[1] == 'V')
1633 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001634 else if (*flag == 'V')
1635 arg_mode |= MODE_VERBOSE;
1636 else if (*flag == 'd' && flag[1] == 'b')
1637 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001638 else if (*flag == 'd' && flag[1] == 'D')
1639 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001640 else if (*flag == 'd' && flag[1] == 'W')
1641 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreauef301b72022-02-23 14:15:18 +01001642 else if (*flag == 'd' && flag[1] == 'M') {
Willy Tarreau1408b1f2022-02-18 18:54:40 +01001643 int ret = pool_parse_debugging(flag + 2, &err_msg);
1644
1645 if (ret <= -1) {
1646 if (ret < -1)
1647 ha_alert("-dM: %s\n", err_msg);
1648 else
1649 printf("%s\n", err_msg);
1650 ha_free(&err_msg);
1651 exit(ret < -1 ? EXIT_FAILURE : 0);
1652 } else if (ret == 0) {
1653 ha_warning("-dM: %s\n", err_msg);
1654 ha_free(&err_msg);
1655 }
Willy Tarreauef301b72022-02-23 14:15:18 +01001656 }
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001657 else if (*flag == 'd' && flag[1] == 'r')
1658 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreau654726d2021-12-28 15:43:11 +01001659#if defined(HA_HAVE_DUMP_LIBS)
1660 else if (*flag == 'd' && flag[1] == 'L')
1661 arg_mode |= MODE_DUMP_LIBS;
1662#endif
Willy Tarreau76871a42022-03-08 16:01:40 +01001663 else if (*flag == 'd' && flag[1] == 'K') {
1664 arg_mode |= MODE_DUMP_KWD;
1665 kwd_dump = flag + 2;
1666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001667 else if (*flag == 'd')
1668 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001669 else if (*flag == 'c' && flag[1] == 'c') {
1670 arg_mode |= MODE_CHECK_CONDITION;
1671 argv++;
1672 argc--;
1673 check_condition = *argv;
1674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001675 else if (*flag == 'c')
1676 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001677 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001678 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001679 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001680 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001681#if defined(USE_SYSTEMD)
1682 global.tune.options |= GTUNE_USE_SYSTEMD;
1683#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001684 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 +01001685 usage(progname);
1686#endif
1687 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001688 else if (*flag == 'W')
1689 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001690 else if (*flag == 'q')
1691 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001692 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001693 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001694 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001695 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001696 }
William Lallemand4fc09692017-06-19 16:37:19 +02001697 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001698 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001699 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001700
Olivier Houchardf73629d2017-04-05 22:33:04 +02001701 argv++;
1702 argc--;
1703 }
William Lallemande7361152018-10-26 14:47:36 +02001704 else if (*flag == 'S') {
1705 struct wordlist *c;
1706
William Lallemanda6b32492020-06-04 23:49:20 +02001707 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001708 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1709 usage(progname);
1710 }
1711 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1712 ha_alert("Cannot allocate memory\n");
1713 exit(EXIT_FAILURE);
1714 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001715 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001716
1717 argv++;
1718 argc--;
1719 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1721 /* list of pids to finish ('f') or terminate ('t') */
1722
1723 if (flag[1] == 'f')
1724 oldpids_sig = SIGUSR1; /* finish then exit */
1725 else
1726 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001727 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001728 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001729 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1730 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001731 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001732 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001733 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001734 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001735 errno = 0;
1736 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1737 if (errno) {
1738 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1739 flag,
1740 *argv, strerror(errno));
1741 exit(1);
1742 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001743 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001744 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001745 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1746 flag, endptr);
1747 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001748 }
Chris Lane236062f2018-02-05 23:15:44 +00001749 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001750 if (oldpids[nb_oldpids] <= 0)
1751 usage(progname);
1752 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001753 }
1754 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001755 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1756 /* now that's a cfgfile list */
1757 argv++; argc--;
1758 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001759 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001760 ha_alert("Cannot load configuration file/directory %s : %s\n",
1761 *argv,
1762 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001763 exit(1);
1764 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001765 argv++; argc--;
1766 }
1767 break;
1768 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001769 else { /* >=2 args */
1770 argv++; argc--;
1771 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001772 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773
1774 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001775 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001776 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001777 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001778 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001779 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001780 free(localpeer);
1781 if ((localpeer = strdup(*argv)) == NULL) {
1782 ha_alert("Cannot allocate memory for local peer.\n");
1783 exit(EXIT_FAILURE);
1784 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001785 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001786 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001787 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001788 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001789 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001790 ha_alert("Cannot load configuration file/directory %s : %s\n",
1791 *argv,
1792 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001793 exit(1);
1794 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001795 break;
Willy Tarreau392524d2022-02-17 18:10:36 +01001796 case 'p' :
1797 free(global.pidfile);
1798 if ((global.pidfile = strdup(*argv)) == NULL) {
1799 ha_alert("Cannot allocate memory for pidfile.\n");
1800 exit(EXIT_FAILURE);
1801 }
1802 break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001803 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001804 }
1805 }
1806 }
1807 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001808 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001809 argv++; argc--;
1810 }
Willy Tarreau392524d2022-02-17 18:10:36 +01001811 free(err_msg);
1812}
1813
Willy Tarreau76871a42022-03-08 16:01:40 +01001814/* call the various keyword dump functions based on the comma-delimited list of
1815 * classes in kwd_dump.
1816 */
1817static void dump_registered_keywords(void)
1818{
1819 char *end;
1820 int all __maybe_unused = 0;
1821
1822 for (; kwd_dump && *kwd_dump; kwd_dump = end) {
1823 end = strchr(kwd_dump, ',');
1824 if (end)
1825 *(end++) = 0;
1826
1827 if (strcmp(kwd_dump, "help") == 0) {
1828 printf("# List of supported keyword classes:\n");
1829 printf("all: list all keywords\n");
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001830 printf("acl: ACL keywords\n");
Willy Tarreauca1acd62022-03-29 15:02:44 +02001831 printf("cfg: configuration keywords\n");
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001832 printf("cli: CLI keywords\n");
Willy Tarreau29d799d2022-03-29 16:59:49 +02001833 printf("cnv: sample converter keywords\n");
Willy Tarreau3b65e142022-03-29 15:03:09 +02001834 printf("flt: filter names\n");
Willy Tarreauf78813f2022-03-29 16:51:29 +02001835 printf("smp: sample fetch functions\n");
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001836 printf("svc: service names\n");
Willy Tarreau76871a42022-03-08 16:01:40 +01001837 continue;
1838 }
1839 else if (strcmp(kwd_dump, "all") == 0) {
1840 all = 1;
1841 }
Willy Tarreauca1acd62022-03-29 15:02:44 +02001842
Willy Tarreau6ff7d1b2022-03-29 15:36:56 +02001843 if (all || strcmp(kwd_dump, "acl") == 0) {
1844 printf("# List of registered ACL keywords:\n");
1845 acl_dump_kwd();
1846 }
1847
Willy Tarreauca1acd62022-03-29 15:02:44 +02001848 if (all || strcmp(kwd_dump, "cfg") == 0) {
1849 printf("# List of registered configuration keywords:\n");
1850 cfg_dump_registered_keywords();
1851 }
Willy Tarreau3b65e142022-03-29 15:03:09 +02001852
Willy Tarreau06d0e2e2022-03-29 15:25:30 +02001853 if (all || strcmp(kwd_dump, "cli") == 0) {
1854 printf("# List of registered CLI keywords:\n");
1855 cli_list_keywords();
1856 }
1857
Willy Tarreau29d799d2022-03-29 16:59:49 +02001858 if (all || strcmp(kwd_dump, "cnv") == 0) {
1859 printf("# List of registered sample converter functions:\n");
1860 smp_dump_conv_kw();
1861 }
1862
Willy Tarreau3b65e142022-03-29 15:03:09 +02001863 if (all || strcmp(kwd_dump, "flt") == 0) {
1864 printf("# List of registered filter names:\n");
1865 flt_dump_kws(NULL);
1866 }
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001867
Willy Tarreauf78813f2022-03-29 16:51:29 +02001868 if (all || strcmp(kwd_dump, "smp") == 0) {
1869 printf("# List of registered sample fetch functions:\n");
1870 smp_dump_fetch_kw();
1871 }
1872
Willy Tarreau5fcc1002022-03-29 15:10:44 +02001873 if (all || strcmp(kwd_dump, "svc") == 0) {
1874 printf("# List of registered service names:\n");
1875 list_services(NULL);
1876 }
Willy Tarreau76871a42022-03-08 16:01:40 +01001877 }
1878}
1879
Willy Tarreau392524d2022-02-17 18:10:36 +01001880/*
1881 * This function initializes all the necessary variables. It only returns
1882 * if everything is OK. If something fails, it exits.
1883 */
1884static void init(int argc, char **argv)
1885{
1886 char *progname = global.log_tag.area;
1887 int err_code = 0;
1888 struct wordlist *wl;
1889 struct proxy *px;
1890 struct post_check_fct *pcf;
1891 int ideal_maxconn;
1892
1893 if (!init_trash_buffers(1)) {
1894 ha_alert("failed to initialize trash buffers.\n");
1895 exit(1);
1896 }
1897
1898 if (init_acl() != 0)
1899 exit(1);
1900
1901 /* Initialise lua. */
1902 hlua_init();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001903
Christopher Faulete3a5e352017-10-24 13:53:54 +02001904 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001905 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Willy Tarreau76871a42022-03-08 16:01:40 +01001906 | MODE_DIAG | MODE_CHECK_CONDITION | MODE_DUMP_LIBS | MODE_DUMP_KWD));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001907
William Lallemand944e6192018-11-21 15:48:31 +01001908 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001909 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001910 global.mode |= MODE_MWORKER_WAIT;
1911 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001912 }
1913
Willy Tarreau26146192021-07-21 10:01:36 +02001914 if ((global.mode & (MODE_MWORKER | MODE_CHECK | MODE_CHECK_CONDITION)) == MODE_MWORKER &&
1915 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001916 atexit_flag = 1;
1917 atexit(reexec_on_failure);
1918 }
1919
Willy Tarreau576132e2011-09-10 19:26:56 +02001920 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001921 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001922 exit(1);
1923 }
1924
Amaury Denoyelle11124302021-06-04 18:22:08 +02001925 usermsgs_clr("config");
1926
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001927 if (global.mode & MODE_CHECK_CONDITION) {
1928 int result;
1929
1930 uint32_t err;
1931 const char *errptr;
1932 char *errmsg = NULL;
1933
1934 char *args[MAX_LINE_ARGS+1];
1935 int arg = sizeof(args) / sizeof(*args);
1936 size_t outlen = strlen(check_condition) + 1;
Willy Tarreauc8194c32021-07-16 16:38:58 +02001937 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001938
1939 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02001940 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001941 &errptr);
1942
1943 if (err & PARSE_ERR_QUOTE) {
1944 ha_alert("Syntax Error in condition: Unmatched quote.\n");
1945 exit(2);
1946 }
1947
1948 if (err & PARSE_ERR_HEX) {
1949 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
1950 exit(2);
1951 }
1952
1953 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
1954 ha_alert("Error in condition: Line too long.\n");
1955 exit(2);
1956 }
1957
Willy Tarreauc8194c32021-07-16 16:38:58 +02001958 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001959 ha_alert("Error in condition: Too many words.\n");
1960 exit(2);
1961 }
1962
1963 if (err) {
1964 ha_alert("Unhandled error in condition, please report this to the developers.\n");
1965 exit(2);
1966 }
1967
Willy Tarreauc8194c32021-07-16 16:38:58 +02001968 /* remerge all words into a single expression */
1969 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
1970 ;
1971
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001972 result = cfg_eval_condition(args, &errmsg, &errptr);
1973
1974 if (result < 0) {
1975 if (errmsg)
1976 ha_alert("Failed to evaluate condition: %s\n", errmsg);
1977
1978 exit(2);
1979 }
1980
1981 exit(result ? 0 : 1);
1982 }
1983
William Lallemand944e6192018-11-21 15:48:31 +01001984 /* in wait mode, we don't try to read the configuration files */
1985 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001986 char *env_cfgfiles = NULL;
1987 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001988
William Lallemand944e6192018-11-21 15:48:31 +01001989 /* handle cfgfiles that are actually directories */
1990 cfgfiles_expand_directories();
1991
1992 if (LIST_ISEMPTY(&cfg_cfgfiles))
1993 usage(progname);
1994
1995
1996 list_for_each_entry(wl, &cfg_cfgfiles, list) {
1997 int ret;
1998
Christopher Faulet4e366822021-01-12 18:57:38 +01001999 if (env_err == 0) {
2000 if (!memprintf(&env_cfgfiles, "%s%s%s",
2001 (env_cfgfiles ? env_cfgfiles : ""),
2002 (env_cfgfiles ? ";" : ""), wl->s))
2003 env_err = 1;
2004 }
William Lallemand7b302d82019-05-20 11:15:37 +02002005
William Lallemand944e6192018-11-21 15:48:31 +01002006 ret = readcfgfile(wl->s);
2007 if (ret == -1) {
2008 ha_alert("Could not open configuration file %s : %s\n",
2009 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01002010 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002011 exit(1);
2012 }
2013 if (ret & (ERR_ABORT|ERR_FATAL))
2014 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
2015 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01002016 if (err_code & ERR_ABORT) {
2017 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002018 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01002019 }
Willy Tarreauc4382422009-12-06 13:10:44 +01002020 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02002021
William Lallemand944e6192018-11-21 15:48:31 +01002022 /* do not try to resolve arguments nor to spot inconsistencies when
2023 * the configuration contains fatal errors caused by files not found
2024 * or failed memory allocations.
2025 */
2026 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2027 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01002028 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01002029 exit(1);
2030 }
Christopher Faulet4e366822021-01-12 18:57:38 +01002031 if (env_err) {
2032 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
2033 exit(1);
2034 }
2035 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
2036 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02002037
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02002038 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002039 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01002040 struct mworker_proc *tmproc;
2041
William Lallemand482f9a92019-04-12 16:15:00 +02002042 setenv("HAPROXY_MWORKER", "1", 1);
2043
William Lallemand16dd1b32018-11-19 18:46:18 +01002044 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
2045
William Lallemand56be0e02022-01-28 21:11:41 +01002046 tmproc = mworker_proc_new();
William Lallemand16dd1b32018-11-19 18:46:18 +01002047 if (!tmproc) {
2048 ha_alert("Cannot allocate process structures.\n");
2049 exit(EXIT_FAILURE);
2050 }
William Lallemand8f7069a2019-04-12 16:09:23 +02002051 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01002052 tmproc->pid = pid;
2053 tmproc->timestamp = start_date.tv_sec;
William Lallemand16dd1b32018-11-19 18:46:18 +01002054 proc_self = tmproc;
2055
Willy Tarreau2b718102021-04-21 07:32:39 +02002056 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01002057 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002058
William Lallemand56be0e02022-01-28 21:11:41 +01002059 tmproc = mworker_proc_new();
Willy Tarreau6185a032021-06-15 08:02:06 +02002060 if (!tmproc) {
2061 ha_alert("Cannot allocate process structures.\n");
2062 exit(EXIT_FAILURE);
2063 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002064 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
William Lallemandce83b4a2018-10-26 14:47:30 +02002065
Willy Tarreau6185a032021-06-15 08:02:06 +02002066 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
2067 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02002068 }
Willy Tarreau6185a032021-06-15 08:02:06 +02002069
2070 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01002071 }
2072 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
2073 struct wordlist *it, *c;
2074
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02002075 /* get the info of the children in the env */
2076 if (mworker_env_to_proc_list() < 0) {
2077 exit(EXIT_FAILURE);
2078 }
William Lallemande7361152018-10-26 14:47:36 +02002079
William Lallemand550db6d2018-11-06 17:37:12 +01002080 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02002081
William Lallemand550db6d2018-11-06 17:37:12 +01002082 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02002083 ha_alert("Can't create the master's CLI.\n");
2084 exit(EXIT_FAILURE);
2085 }
William Lallemande7361152018-10-26 14:47:36 +02002086
William Lallemand550db6d2018-11-06 17:37:12 +01002087 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
2088
2089 if (mworker_cli_proxy_new_listener(c->s) < 0) {
2090 ha_alert("Can't create the master's CLI.\n");
2091 exit(EXIT_FAILURE);
2092 }
Willy Tarreau2b718102021-04-21 07:32:39 +02002093 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01002094 free(c->s);
2095 free(c);
2096 }
2097 }
William Lallemandce83b4a2018-10-26 14:47:30 +02002098 }
2099
Eric Salama5ba83352021-03-16 15:11:17 +01002100 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
2101 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
2102 }
2103
Christopher Faulet27c8d202021-10-13 09:50:53 +02002104 /* destroy unreferenced defaults proxies */
2105 proxy_destroy_all_unref_defaults();
2106
Willy Tarreaue90904d2021-02-12 14:08:31 +01002107
Willy Tarreaubb925012009-07-23 13:36:36 +02002108 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02002109 for (px = proxies_list; px; px = px->next) {
2110 struct server *srv;
2111 struct post_proxy_check_fct *ppcf;
2112 struct post_server_check_fct *pscf;
2113
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002114 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002115 continue;
2116
Christopher Fauletc1692962019-08-12 09:51:07 +02002117 list_for_each_entry(pscf, &post_server_check_list, list) {
2118 for (srv = px->srv; srv; srv = srv->next)
2119 err_code |= pscf->fct(srv);
2120 }
2121 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2122 err_code |= ppcf->fct(px);
2123 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002124 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002125 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002126 exit(1);
2127 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002128
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002129 err_code |= pattern_finalize_config();
2130 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2131 ha_alert("Failed to finalize pattern config.\n");
2132 exit(1);
2133 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002134
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002135 if (global.rlimit_memmax_all)
2136 global.rlimit_memmax = global.rlimit_memmax_all;
2137
Willy Tarreaue5733232019-05-22 19:24:06 +02002138#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002139 err_code |= netns_init();
2140 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002141 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002142 exit(1);
2143 }
2144#endif
2145
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002146 /* Apply server states */
2147 apply_server_state();
2148
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002149 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002150 srv_compute_all_admin_states(px);
2151
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002152 /* Apply servers' configured address */
2153 err_code |= srv_init_addr();
2154 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002155 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002156 exit(1);
2157 }
2158
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002159 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2160 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2161 exit(1);
2162 }
2163
Willy Tarreau654726d2021-12-28 15:43:11 +01002164#if defined(HA_HAVE_DUMP_LIBS)
2165 if (global.mode & MODE_DUMP_LIBS) {
2166 qfprintf(stdout, "List of loaded object files:\n");
2167 chunk_reset(&trash);
2168 if (dump_libs(&trash, 0))
2169 printf("%s", trash.area);
2170 }
2171#endif
2172
Willy Tarreau76871a42022-03-08 16:01:40 +01002173 if (global.mode & MODE_DUMP_KWD)
2174 dump_registered_keywords();
2175
Willy Tarreaubaaee002006-06-26 02:48:02 +02002176 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002177 struct peers *pr;
2178 struct proxy *px;
2179
Willy Tarreaubebd2122020-04-15 16:06:11 +02002180 if (warned & WARN_ANY)
2181 qfprintf(stdout, "Warnings were found.\n");
2182
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002183 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002184 if (pr->peers_fe)
2185 break;
2186
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002187 for (px = proxies_list; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002188 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002189 break;
2190
Emeric Brunbc5c8212021-08-13 09:32:50 +02002191 if (!px) {
2192 /* We may only have log-forward section */
2193 for (px = cfg_log_forward; px; px = px->next)
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002194 if (!(px->flags & (PR_FL_DISABLED|PR_FL_STOPPED)) && px->li_all)
Emeric Brunbc5c8212021-08-13 09:32:50 +02002195 break;
2196 }
2197
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002198 if (pr || px) {
2199 /* At least one peer or one listener has been found */
2200 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002201 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002202 }
2203 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2204 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002205 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002206
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002207 if (global.mode & MODE_DIAG) {
2208 cfg_run_diagnostics();
2209 }
2210
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002211 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002212 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002213
Willy Tarreaue6945732016-12-21 19:57:00 +01002214 list_for_each_entry(pcf, &post_check_list, list) {
2215 err_code |= pcf->fct();
2216 if (err_code & (ERR_ABORT|ERR_FATAL))
2217 exit(1);
2218 }
2219
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220 if (cfg_maxconn > 0)
2221 global.maxconn = cfg_maxconn;
2222
Willy Tarreau4975d142021-03-13 11:00:33 +01002223 if (global.cli_fe)
2224 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002225
2226 if (cfg_peers) {
2227 /* peers also need to bypass global maxconn */
2228 struct peers *p = cfg_peers;
2229
2230 for (p = cfg_peers; p; p = p->next)
2231 if (p->peers_fe)
2232 global.maxsock += p->peers_fe->maxconn;
2233 }
2234
Willy Tarreaud0256482015-01-15 21:45:22 +01002235 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002236 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2237 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2238 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2239 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002240 *
2241 * If memmax is set, then it depends on which values are set. If
2242 * maxsslconn is set, we use memmax to determine how many cleartext
2243 * connections may be added, and set maxconn to the sum of the two.
2244 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2245 * the remaining amount of memory between memmax and the cleartext
2246 * connections. If neither are set, then it is considered that all
2247 * connections are SSL-capable, and maxconn is computed based on this,
2248 * then maxsslconn accordingly. We need to know if SSL is used on the
2249 * frontends, backends, or both, because when it's used on both sides,
2250 * we need twice the value for maxsslconn, but we only count the
2251 * handshake once since it is not performed on the two sides at the
2252 * same time (frontend-side is terminated before backend-side begins).
2253 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002254 * ssl_handshake_cost during its initialization. In any case, if
2255 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2256 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002257 */
Willy Tarreauac350932019-03-01 15:43:14 +01002258 ideal_maxconn = compute_ideal_maxconn();
2259
Willy Tarreaud0256482015-01-15 21:45:22 +01002260 if (!global.rlimit_memmax) {
2261 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002262 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002263 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2264 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2265 }
2266 }
2267#ifdef USE_OPENSSL
2268 else if (!global.maxconn && !global.maxsslconn &&
2269 (global.ssl_used_frontend || global.ssl_used_backend)) {
2270 /* memmax is set, compute everything automatically. Here we want
2271 * to ensure that all SSL connections will be served. We take
2272 * care of the number of sides where SSL is used, and consider
2273 * the worst case : SSL used on both sides and doing a handshake
2274 * simultaneously. Note that we can't have more than maxconn
2275 * handshakes at a time by definition, so for the worst case of
2276 * two SSL conns per connection, we count a single handshake.
2277 */
2278 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2279 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002280 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002281
2282 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2283 mem -= global.maxzlibmem;
2284 mem = mem * MEM_USABLE_RATIO;
2285
Willy Tarreau304e17e2020-03-10 17:54:54 +01002286 /* Principle: we test once to set maxconn according to the free
2287 * memory. If it results in values the system rejects, we try a
2288 * second time by respecting rlim_fd_max. If it fails again, we
2289 * go back to the initial value and will let the final code
2290 * dealing with rlimit report the error. That's up to 3 attempts.
2291 */
2292 do {
2293 global.maxconn = mem /
2294 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2295 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2296 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002297
Willy Tarreau304e17e2020-03-10 17:54:54 +01002298 if (retried == 1)
2299 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2300 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002301#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002302 if (global.maxconn > SYSTEM_MAXCONN)
2303 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002304#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002305 global.maxsslconn = sides * global.maxconn;
2306
2307 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2308 break;
2309 } while (retried++ < 2);
2310
Willy Tarreaud0256482015-01-15 21:45:22 +01002311 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2312 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2313 global.maxconn, global.maxsslconn);
2314 }
2315 else if (!global.maxsslconn &&
2316 (global.ssl_used_frontend || global.ssl_used_backend)) {
2317 /* memmax and maxconn are known, compute maxsslconn automatically.
2318 * maxsslconn being forced, we don't know how many of it will be
2319 * on each side if both sides are being used. The worst case is
2320 * when all connections use only one SSL instance because
2321 * handshakes may be on two sides at the same time.
2322 */
2323 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2324 int64_t mem = global.rlimit_memmax * 1048576ULL;
2325 int64_t sslmem;
2326
2327 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2328 mem -= global.maxzlibmem;
2329 mem = mem * MEM_USABLE_RATIO;
2330
Willy Tarreau87b09662015-04-03 00:22:06 +02002331 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002332 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2333 global.maxsslconn = round_2dig(global.maxsslconn);
2334
2335 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002336 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2337 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2338 "without SSL is %d, but %d was found and SSL is in use.\n",
2339 global.rlimit_memmax,
2340 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2341 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002342 exit(1);
2343 }
2344
2345 if (global.maxsslconn > sides * global.maxconn)
2346 global.maxsslconn = sides * global.maxconn;
2347
2348 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2349 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2350 }
2351#endif
2352 else if (!global.maxconn) {
2353 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2354 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2355 int64_t mem = global.rlimit_memmax * 1048576ULL;
2356 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002357 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002358
2359 if (global.ssl_used_frontend || global.ssl_used_backend)
2360 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2361
2362 mem -= global.maxzlibmem;
2363 mem = mem * MEM_USABLE_RATIO;
2364
2365 clearmem = mem;
2366 if (sides)
2367 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2368
Willy Tarreau304e17e2020-03-10 17:54:54 +01002369 /* Principle: we test once to set maxconn according to the free
2370 * memory. If it results in values the system rejects, we try a
2371 * second time by respecting rlim_fd_max. If it fails again, we
2372 * go back to the initial value and will let the final code
2373 * dealing with rlimit report the error. That's up to 3 attempts.
2374 */
2375 do {
2376 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2377 if (retried == 1)
2378 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2379 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002380#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002381 if (global.maxconn > SYSTEM_MAXCONN)
2382 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002383#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002384
Willy Tarreau304e17e2020-03-10 17:54:54 +01002385 if (clearmem <= 0 || !global.maxconn) {
2386 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2387 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2388 "is %d, but %d was found.\n",
2389 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002390 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002391 global.maxsslconn);
2392 exit(1);
2393 }
2394
2395 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2396 break;
2397 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002398
2399 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2400 if (sides && global.maxsslconn > sides * global.maxconn) {
2401 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2402 "to be limited to %d. Better reduce global.maxsslconn to get more "
2403 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2404 }
2405 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2406 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002407 }
2408
Willy Tarreaua409f302020-03-10 17:08:53 +01002409 global.maxsock = compute_ideal_maxsock(global.maxconn);
2410 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002411 if (!global.maxpipes)
2412 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002413
Olivier Houchard88698d92019-04-16 19:07:22 +02002414 /* update connection pool thresholds */
2415 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2416 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2417
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002418 proxy_adjust_all_maxconn();
2419
Willy Tarreau1db37712007-06-03 17:16:49 +02002420 if (global.tune.maxpollevents <= 0)
2421 global.tune.maxpollevents = MAX_POLL_EVENTS;
2422
Willy Tarreau060a7612021-03-10 11:06:26 +01002423 if (global.tune.runqueue_depth <= 0) {
2424 /* tests on various thread counts from 1 to 64 have shown an
2425 * optimal queue depth following roughly 1/sqrt(threads).
2426 */
2427 int s = my_flsl(global.nbthread);
2428 s += (global.nbthread / s); // roughly twice the sqrt.
2429 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2430 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002431
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002432 if (global.tune.recv_enough == 0)
2433 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2434
Willy Tarreau27a674e2009-08-17 07:23:33 +02002435 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2436 global.tune.maxrewrite = global.tune.bufsize / 2;
2437
Amaury Denoyelle11124302021-06-04 18:22:08 +02002438 usermsgs_clr(NULL);
2439
Willy Tarreaubaaee002006-06-26 02:48:02 +02002440 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2441 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002442 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002443 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2444 }
2445
William Lallemand095ba4c2017-06-01 17:38:50 +02002446 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002447 /* command line daemon mode inhibits foreground and debug modes mode */
2448 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002449 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002451
2452 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453
William Lallemand095ba4c2017-06-01 17:38:50 +02002454 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002455 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002456 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457 }
2458
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002459 if (global.nbthread < 1)
2460 global.nbthread = 1;
2461
Christopher Faulet3ef26392017-08-29 16:46:57 +02002462 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002463 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002464 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002465 exit(1);
2466 }
2467
Christopher Faulet96d44832017-11-14 22:02:30 +01002468 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002469 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002470 exit(1);
2471 }
2472
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002473 /*
2474 * Note: we could register external pollers here.
2475 * Built-in pollers have been registered before main().
2476 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002477
Willy Tarreau43b78992009-01-25 15:42:27 +01002478 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002479 disable_poller("kqueue");
2480
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002481 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2482 disable_poller("evports");
2483
Willy Tarreau43b78992009-01-25 15:42:27 +01002484 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002485 disable_poller("epoll");
2486
Willy Tarreau43b78992009-01-25 15:42:27 +01002487 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002488 disable_poller("poll");
2489
Willy Tarreau43b78992009-01-25 15:42:27 +01002490 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002491 disable_poller("select");
2492
2493 /* Note: we could disable any poller by name here */
2494
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002495 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002496 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002497 fprintf(stderr, "\n");
2498 list_filters(stderr);
2499 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002500
Willy Tarreau4f60f162007-04-08 16:39:58 +02002501 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002502 ha_alert("No polling mechanism available.\n"
2503 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2504 " is too low on this platform to support maxconn and the number of listeners\n"
2505 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2506 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2507 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2508 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2509 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2510 " check build settings using 'haproxy -vv'.\n\n",
2511 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002512 exit(1);
2513 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002514 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2515 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002516 }
2517
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002518 if (!global.node)
2519 global.node = strdup(hostname);
2520
Willy Tarreau02b092f2020-10-07 18:36:54 +02002521 /* stop disabled proxies */
2522 for (px = proxies_list; px; px = px->next) {
Christopher Fauletdfd10ab2021-10-06 14:24:19 +02002523 if (px->flags & (PR_FL_DISABLED|PR_FL_STOPPED))
Willy Tarreau02b092f2020-10-07 18:36:54 +02002524 stop_proxy(px);
2525 }
2526
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002527 if (!hlua_post_init())
2528 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529}
2530
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002531void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002533 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002534 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002535 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002536 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002537 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002538 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002539 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002540 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002541 struct per_thread_init_fct *tif, *tifb;
2542 struct per_thread_deinit_fct *tdf, *tdfb;
2543 struct per_thread_alloc_fct *taf, *tafb;
2544 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002545 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002546 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002547 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002548 int cur_fd;
2549
2550 /* At this point the listeners state is weird:
2551 * - most listeners are still bound and referenced in their protocol
2552 * - some might be zombies that are not in their proto anymore, but
2553 * still appear in their proxy's listeners with a valid FD.
2554 * - some might be stopped and still appear in their proxy as FD #-1
2555 * - among all of them, some might be inherited hence shared and we're
2556 * not allowed to pause them or whatever, we must just close them.
2557 * - finally some are not listeners (pipes, logs, stdout, etc) and
2558 * must be left intact.
2559 *
2560 * The safe way to proceed is to unbind (and close) whatever is not yet
2561 * unbound so that no more receiver/listener remains alive. Then close
2562 * remaining listener FDs, which correspond to zombie listeners (those
2563 * belonging to disabled proxies that were in another process).
2564 * objt_listener() would be cleaner here but not converted yet.
2565 */
2566 protocol_unbind_all();
2567
2568 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002569 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002570 continue;
2571
Willy Tarreaua74cb382020-10-15 21:29:49 +02002572 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002573 struct listener *l = fdtab[cur_fd].owner;
2574
2575 BUG_ON(l->state != LI_INIT);
2576 unbind_listener(l);
2577 }
2578 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002579
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002580 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002582 /* build a list of unique uri_auths */
2583 if (!ua)
2584 ua = p->uri_auth;
2585 else {
2586 /* check if p->uri_auth is unique */
2587 for (uap = ua; uap; uap=uap->next)
2588 if (uap == p->uri_auth)
2589 break;
2590
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002591 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002592 /* add it, if it is */
2593 p->uri_auth->next = ua;
2594 ua = p->uri_auth;
2595 }
William Lallemand0f99e342011-10-12 17:50:54 +02002596 }
2597
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002598 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002599 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002600 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002601 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002602
Christopher Faulet27c8d202021-10-13 09:50:53 +02002603 /* destroy all referenced defaults proxies */
2604 proxy_destroy_all_unref_defaults();
2605
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002606 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002607 struct stat_scope *scope, *scopep;
2608
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002609 uap = ua;
2610 ua = ua->next;
2611
Willy Tarreaua534fea2008-08-03 12:19:50 +02002612 free(uap->uri_prefix);
2613 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002614 free(uap->node);
2615 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002616
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002617 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002618 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002619
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002620 scope = uap->scope;
2621 while (scope) {
2622 scopep = scope;
2623 scope = scope->next;
2624
2625 free(scopep->px_id);
2626 free(scopep);
2627 }
2628
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002629 free(uap);
2630 }
2631
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002632 userlist_free(userlist);
2633
David Carlier834cb2e2015-09-25 12:02:25 +01002634 cfg_unregister_sections();
2635
Christopher Faulet0132d062017-07-26 15:33:35 +02002636 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002637
Willy Tarreau05554e62016-12-21 20:46:26 +01002638 list_for_each_entry(pdf, &post_deinit_list, list)
2639 pdf->fct();
2640
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002641 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002642 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002643 ha_free(&global.chroot);
2644 ha_free(&global.pidfile);
2645 ha_free(&global.node);
2646 ha_free(&global.desc);
2647 ha_free(&oldpids);
2648 ha_free(&old_argv);
2649 ha_free(&localpeer);
2650 ha_free(&global.server_state_base);
2651 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002652 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002653 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002654
William Lallemand0f99e342011-10-12 17:50:54 +02002655 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002656 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002657 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002658 free(log);
2659 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002660 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002661 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002662 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002663 free(wl);
2664 }
2665
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002666 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2667 if (bol->must_free)
2668 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002669 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002670 free(bol);
2671 }
2672
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002673 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002674 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002675 free(pxdf);
2676 }
2677
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002678 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002679 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002680 free(pdf);
2681 }
2682
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002683 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002684 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002685 free(srvdf);
2686 }
2687
Tim Duesterhusfc854942020-09-10 19:46:42 +02002688 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002689 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002690 free(pcf);
2691 }
2692
Tim Duesterhus34bef072020-07-04 11:49:50 +02002693 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002694 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002695 free(pscf);
2696 }
2697
Tim Duesterhus53508d62020-09-10 19:46:40 +02002698 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002699 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002700 free(ppcf);
2701 }
2702
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002703 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002704 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002705 free(tif);
2706 }
2707
2708 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002709 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002710 free(tdf);
2711 }
2712
2713 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002714 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002715 free(taf);
2716 }
2717
2718 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002719 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002720 free(tff);
2721 }
2722
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002723 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002724 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002725 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002726} /* end deinit() */
2727
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002728__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002729{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002730 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002731 deinit();
2732 exit(status);
2733}
William Lallemand72160322018-11-06 17:37:16 +01002734
Willy Tarreau918ff602011-07-25 16:33:49 +02002735/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002736void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002737{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002738 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002739
Willy Tarreau55542642021-10-08 09:33:24 +02002740 clock_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002741 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002742 wake_expired_tasks();
2743
William Lallemand1aab50b2018-06-07 09:46:01 +02002744 /* check if we caught some signals and process them in the
2745 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002746 if (signal_queue_len && tid == 0) {
2747 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002748 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002749 }
2750
2751 /* Process a few tasks */
2752 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002753
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002754 /* also stop if we failed to cleanly stop all tasks */
2755 if (killed > 1)
2756 break;
2757
Willy Tarreau10146c92015-04-13 20:44:19 +02002758 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002759 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002760 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002761 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002762 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002763 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2764 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002765 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002766 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002767 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002768 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002769 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002770 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002771
Willy Tarreau4f46a352020-03-23 09:27:28 +01002772 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002773 int i;
2774
2775 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002776 /* stop muxes before acknowledging stopping */
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002777 if (!(stopping_thread_mask & tid_bit)) {
2778 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2779 wake = 1;
2780 }
2781
Willy Tarreau1db42732021-04-06 11:44:07 +02002782 if (_HA_ATOMIC_OR_FETCH(&stopping_thread_mask, tid_bit) == tid_bit) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002783 /* notify all threads that stopping was just set */
2784 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002785 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002786 wake_thread(i);
2787 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002788 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002789
2790 /* stop when there's nothing left to do */
2791 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002792 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2793 /* wake all threads waiting on jobs==0 */
2794 for (i = 0; i < global.nbthread; i++)
2795 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2796 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002797 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002798 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002799 }
2800
Willy Tarreauc49ba522019-12-11 08:12:23 +01002801 /* If we have to sleep, measure how long */
2802 next = wake ? TICK_ETERNITY : next_timer_expiry();
2803
Willy Tarreau58b458d2008-06-29 22:40:23 +02002804 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002805 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002806
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002807 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002808 }
2809}
2810
Christopher Faulet1d17c102017-08-29 15:38:48 +02002811static void *run_thread_poll_loop(void *data)
2812{
Willy Tarreau082b6282019-05-22 14:42:12 +02002813 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002814 struct per_thread_init_fct *ptif;
2815 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002816 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002817 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002818 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2819 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002820
Willy Tarreau43ab05b2021-09-28 09:43:11 +02002821 ha_set_thread(data);
Willy Tarreaufb641d72021-09-28 10:15:47 +02002822 set_thread_cpu_affinity();
Willy Tarreau44c58da2021-10-08 12:27:54 +02002823 clock_set_local_source();
Willy Tarreau91e6df02019-05-03 17:21:18 +02002824
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002825 /* Now, initialize one thread init at a time. This is better since
2826 * some init code is a bit tricky and may release global resources
2827 * after reallocating them locally. This will also ensure there is
2828 * no race on file descriptors allocation.
2829 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002830#ifdef USE_THREAD
2831 pthread_mutex_lock(&init_mutex);
2832#endif
2833 /* The first thread must set the number of threads left */
2834 if (!init_left)
2835 init_left = global.nbthread;
2836 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002837
Willy Tarreau55542642021-10-08 09:33:24 +02002838 clock_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002839
Willy Tarreau082b6282019-05-22 14:42:12 +02002840 /* per-thread alloc calls performed here are not allowed to snoop on
2841 * other threads, so they are free to initialize at their own rhythm
2842 * as long as they act as if they were alone. None of them may rely
2843 * on resources initialized by the other ones.
2844 */
2845 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2846 if (!ptaf->fct()) {
2847 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002848#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002849 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002850#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02002851 exit(1);
2852 }
2853 }
2854
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002855 /* per-thread init calls performed here are not allowed to snoop on
2856 * other threads, so they are free to initialize at their own rhythm
2857 * as long as they act as if they were alone.
2858 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002859 list_for_each_entry(ptif, &per_thread_init_list, list) {
2860 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002861 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002862#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002863 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002864#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002865 exit(1);
2866 }
2867 }
2868
Willy Tarreau71092822019-06-10 09:51:04 +02002869 /* enabling protocols will result in fd_insert() calls to be performed,
2870 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002871 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002872 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002873 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002874 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002875
Willy Tarreau34a150c2019-06-11 09:16:41 +02002876#ifdef USE_THREAD
2877 pthread_cond_broadcast(&init_cond);
2878 pthread_mutex_unlock(&init_mutex);
2879
2880 /* now wait for other threads to finish starting */
2881 pthread_mutex_lock(&init_mutex);
2882 while (init_left)
2883 pthread_cond_wait(&init_cond, &init_mutex);
2884 pthread_mutex_unlock(&init_mutex);
2885#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002886
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002887#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2888 /* Let's refrain from using setuid executables. This way the impact of
2889 * an eventual vulnerability in a library remains limited. It may
2890 * impact external checks but who cares about them anyway ? In the
2891 * worst case it's possible to disable the option. Obviously we do this
2892 * in workers only. We can't hard-fail on this one as it really is
2893 * implementation dependent though we're interested in feedback, hence
2894 * the warning.
2895 */
2896 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2897 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002898 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 +01002899 ha_warning("Failed to disable setuid, please report to developers with detailed "
2900 "information about your operating system. You can silence this warning "
2901 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2902 }
2903 }
2904#endif
2905
Willy Tarreaud96f1122019-12-03 07:07:36 +01002906#if defined(RLIMIT_NPROC)
2907 /* all threads have started, it's now time to prevent any new thread
2908 * or process from starting. Obviously we do this in workers only. We
2909 * can't hard-fail on this one as it really is implementation dependent
2910 * though we're interested in feedback, hence the warning.
2911 */
2912 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2913 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2914 static int warn_fail;
2915
Willy Tarreau18515722021-04-06 11:57:41 +02002916 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002917 ha_warning("Failed to disable forks, please report to developers with detailed "
2918 "information about your operating system. You can silence this warning "
2919 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2920 }
2921 }
2922#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002923 run_poll_loop();
2924
2925 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2926 ptdf->fct();
2927
Willy Tarreau082b6282019-05-22 14:42:12 +02002928 list_for_each_entry(ptff, &per_thread_free_list, list)
2929 ptff->fct();
2930
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002931#ifdef USE_THREAD
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002932 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002933 if (tid > 0)
2934 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002935#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002936 return NULL;
2937}
Christopher Faulet1d17c102017-08-29 15:38:48 +02002938
William Dauchyf9af9d72019-11-17 15:47:16 +01002939/* set uid/gid depending on global settings */
2940static void set_identity(const char *program_name)
2941{
2942 if (global.gid) {
2943 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
2944 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
2945 " without 'uid'/'user' is generally useless.\n", program_name);
2946
2947 if (setgid(global.gid) == -1) {
2948 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
2949 protocol_unbind_all();
2950 exit(1);
2951 }
2952 }
2953
2954 if (global.uid && setuid(global.uid) == -1) {
2955 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
2956 protocol_unbind_all();
2957 exit(1);
2958 }
2959}
2960
Willy Tarreaubaaee002006-06-26 02:48:02 +02002961int main(int argc, char **argv)
2962{
2963 int err, retry;
2964 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02002965 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02002966 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
2967
2968 /* Catch forced CFLAGS that miss 2-complement integer overflow */
2969 if (intovf + 0x7FFFFFFF >= intovf) {
2970 fprintf(stderr,
2971 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
2972 "The source code was miscompiled by the compiler, which usually indicates that\n"
2973 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
2974 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
2975 "and INSTALL files to decide on the best way to pass your local build options.\n"
2976 "\nBuild options :"
2977#ifdef BUILD_TARGET
2978 "\n TARGET = " BUILD_TARGET
2979#endif
2980#ifdef BUILD_CPU
2981 "\n CPU = " BUILD_CPU
2982#endif
2983#ifdef BUILD_CC
2984 "\n CC = " BUILD_CC
2985#endif
2986#ifdef BUILD_CFLAGS
2987 "\n CFLAGS = " BUILD_CFLAGS
2988#endif
2989#ifdef BUILD_OPTIONS
2990 "\n OPTIONS = " BUILD_OPTIONS
2991#endif
2992#ifdef BUILD_DEBUG
2993 "\n DEBUG = " BUILD_DEBUG
2994#endif
2995 "\n\n");
2996 return 1;
2997 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998
Olivier Houchard5fa300d2018-02-03 15:15:21 +01002999 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003000
Willy Tarreaubf696402019-03-01 10:09:28 +01003001 /* take a copy of initial limits before we possibly change them */
3002 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02003003
3004 if (limit.rlim_max == RLIM_INFINITY)
3005 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01003006 rlim_fd_cur_at_boot = limit.rlim_cur;
3007 rlim_fd_max_at_boot = limit.rlim_max;
3008
Willy Tarreau5794fb02018-11-25 18:43:29 +01003009 /* process all initcalls in order of potential dependency */
3010 RUN_INITCALLS(STG_PREPARE);
3011 RUN_INITCALLS(STG_LOCK);
Willy Tarreau3ebe4d92022-02-18 14:51:49 +01003012 RUN_INITCALLS(STG_REGISTER);
Willy Tarreau34527d52022-02-17 17:45:58 +01003013
3014 /* now's time to initialize early boot variables */
3015 init_early(argc, argv);
3016
Willy Tarreau18f96d02022-02-23 17:25:00 +01003017 /* handles argument parsing */
3018 init_args(argc, argv);
3019
Willy Tarreau5794fb02018-11-25 18:43:29 +01003020 RUN_INITCALLS(STG_ALLOC);
3021 RUN_INITCALLS(STG_POOL);
Willy Tarreau5794fb02018-11-25 18:43:29 +01003022 RUN_INITCALLS(STG_INIT);
3023
Willy Tarreau34527d52022-02-17 17:45:58 +01003024 /* this is the late init where the config is parsed */
Emeric Bruncf20bf12010-10-22 16:06:11 +02003025 init(argc, argv);
Willy Tarreau34527d52022-02-17 17:45:58 +01003026
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003027 signal_register_fct(SIGQUIT, dump, SIGQUIT);
3028 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
3029 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02003030 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003031
Willy Tarreaue437c442010-03-17 18:02:46 +01003032 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
3033 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
3034 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02003035 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003036 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003037
Willy Tarreaudc23a922011-02-16 11:10:36 +01003038 /* ulimits */
3039 if (!global.rlimit_nofile)
3040 global.rlimit_nofile = global.maxsock;
3041
3042 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01003043 limit.rlim_cur = global.rlimit_nofile;
3044 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
3045
Willy Tarreaudc23a922011-02-16 11:10:36 +01003046 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02003047 getrlimit(RLIMIT_NOFILE, &limit);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003048 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3049 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
3050 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003051 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003052 }
3053 else {
3054 /* try to set it to the max possible at least */
3055 limit.rlim_cur = limit.rlim_max;
3056 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
3057 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02003058
William Dauchya5194602020-03-28 19:29:58 +01003059 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003060 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
3061 global.rlimit_nofile = limit.rlim_cur;
3062 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01003063 }
3064 }
3065
3066 if (global.rlimit_memmax) {
3067 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01003068 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01003069#ifdef RLIMIT_AS
3070 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003071 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3072 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3073 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003074 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003075 }
3076 else
William Dauchya5194602020-03-28 19:29:58 +01003077 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003078 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003079 }
3080#else
3081 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003082 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3083 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3084 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003085 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003086 }
3087 else
William Dauchya5194602020-03-28 19:29:58 +01003088 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003089 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003090 }
3091#endif
3092 }
3093
William Lallemandf82afbb2022-01-07 18:19:42 +01003094 /* Try to get the listeners FD from the previous process using
3095 * _getsocks on the stat socket, it must never been done in wait mode
3096 * and check mode
3097 */
3098 if (old_unixsocket &&
3099 !(global.mode & (MODE_MWORKER_WAIT|MODE_CHECK|MODE_CHECK_CONDITION))) {
William Lallemand85b0bd92017-06-01 17:38:53 +02003100 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02003101 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003102 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02003103 if (!(global.mode & MODE_MWORKER))
3104 exit(1);
3105 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02003106 }
3107 }
William Lallemand85b0bd92017-06-01 17:38:53 +02003108
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 /* We will loop at most 100 times with 10 ms delay each time.
3110 * That's at most 1 second. We only send a signal to old pids
3111 * if we cannot grab at least one port.
3112 */
3113 retry = MAX_START_RETRIES;
3114 err = ERR_NONE;
3115 while (retry >= 0) {
3116 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003117 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003118 /* exit the loop on no error or fatal error */
3119 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003121 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 break;
3123
3124 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3125 * listening sockets. So on those platforms, it would be wiser to
3126 * simply send SIGUSR1, which will not be undoable.
3127 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003128 if (tell_old_pids(SIGTTOU) == 0) {
3129 /* no need to wait if we can't contact old pids */
3130 retry = 0;
3131 continue;
3132 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133 /* give some time to old processes to stop listening */
3134 w.tv_sec = 0;
3135 w.tv_usec = 10*1000;
3136 select(0, NULL, NULL, NULL, &w);
3137 retry--;
3138 }
3139
Willy Tarreaue91bff22020-09-02 11:11:43 +02003140 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003141 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003142 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003143 if (retry != MAX_START_RETRIES && nb_oldpids) {
3144 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003146 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 exit(1);
3148 }
3149
William Lallemand944e6192018-11-21 15:48:31 +01003150 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003151 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003152 /* Note: we don't have to send anything to the old pids because we
3153 * never stopped them. */
3154 exit(1);
3155 }
3156
Willy Tarreaue91bff22020-09-02 11:11:43 +02003157 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003158 * the previous process gave us, we don't need them anymore
3159 */
Willy Tarreaub5101162022-01-28 18:28:18 +01003160 sock_drop_unused_old_sockets();
Willy Tarreaudd815982007-10-16 12:25:14 +02003161
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003163 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3164 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003165
Willy Tarreaubaaee002006-06-26 02:48:02 +02003166 /* MODE_QUIET can inhibit alerts and warnings below this line */
3167
PiBa-NL149a81a2017-12-25 21:03:31 +01003168 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3169 /* either stdin/out/err are already closed or should stay as they are. */
3170 if ((global.mode & MODE_DAEMON)) {
3171 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3172 global.mode &= ~MODE_VERBOSE;
3173 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3174 }
3175 } else {
3176 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3177 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003178 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003179 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 }
3181
3182 /* open log & pid files before the chroot */
William Lallemand7b820a62022-02-14 09:02:14 +01003183 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) &&
3184 !(global.mode & MODE_MWORKER_WAIT) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003185 unlink(global.pidfile);
3186 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3187 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003188 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003189 if (nb_oldpids)
3190 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003191 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003192 exit(1);
3193 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 }
3195
Willy Tarreaub38651a2007-03-24 17:24:39 +01003196 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003197 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3198 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003199 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003200 exit(1);
3201 }
3202
Jackie Tapia749f74c2020-07-22 18:59:40 -05003203 /* If the user is not root, we'll still let them try the configuration
3204 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003205 */
3206 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003207 ha_warning("[%s.main()] Some options which require full privileges"
3208 " might not work well.\n"
3209 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003210
William Lallemand095ba4c2017-06-01 17:38:50 +02003211 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3212
3213 /* chroot if needed */
3214 if (global.chroot != NULL) {
3215 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003216 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003217 if (nb_oldpids)
3218 tell_old_pids(SIGTTIN);
3219 protocol_unbind_all();
3220 exit(1);
3221 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003222 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003223 }
3224
William Lallemand944e6192018-11-21 15:48:31 +01003225 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003226 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003227
William Lallemand27edc4b2019-05-07 17:49:33 +02003228 /* send a SIGTERM to workers who have a too high reloads number */
3229 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3230 mworker_kill_max_reloads(SIGTERM);
3231
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232 /* Note that any error at this stage will be fatal because we will not
3233 * be able to restart the old pids.
3234 */
3235
William Dauchyf9af9d72019-11-17 15:47:16 +01003236 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3237 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003238
Willy Tarreaubaaee002006-06-26 02:48:02 +02003239 /* check ulimits */
3240 limit.rlim_cur = limit.rlim_max = 0;
3241 getrlimit(RLIMIT_NOFILE, &limit);
3242 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003243 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3244 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3245 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3246 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3247 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003248 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003249 }
3250 else
3251 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003252 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003253 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3254 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003255 }
3256
William Lallemand944e6192018-11-21 15:48:31 +01003257 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003258 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003259 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003260 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003261
William Lallemand095ba4c2017-06-01 17:38:50 +02003262 /*
3263 * if daemon + mworker: must fork here to let a master
3264 * process live in background before forking children
3265 */
William Lallemand73b85e72017-06-01 17:38:51 +02003266
3267 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3268 && (global.mode & MODE_MWORKER)
3269 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003270 ret = fork();
3271 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003272 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003273 protocol_unbind_all();
3274 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003275 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003276 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003277 } else /* change the process group ID in the child (master process) */
3278 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003279 }
William Lallemande20b6a62017-06-01 17:38:55 +02003280
William Lallemande20b6a62017-06-01 17:38:55 +02003281
William Lallemanddeed7802017-11-06 11:00:04 +01003282 /* if in master-worker mode, write the PID of the father */
3283 if (global.mode & MODE_MWORKER) {
3284 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003285 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003286 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003287 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003288 }
3289
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003291 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003292 if (global.mode & MODE_MWORKER)
3293 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003294
3295 ret = fork();
3296 if (ret < 0) {
3297 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3298 protocol_unbind_all();
3299 exit(1); /* there has been an error */
3300 }
3301 else if (ret == 0) { /* child breaks here */
Willy Tarreau3c032f22021-07-21 10:17:02 +02003302 /* This one must not be exported, it's internal! */
3303 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003304 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003305 }
3306 else { /* parent here */
3307 in_parent = 1;
3308
William Lallemand944e6192018-11-21 15:48:31 +01003309 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3310 char pidstr[100];
3311 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003312 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003313 }
3314 if (global.mode & MODE_MWORKER) {
3315 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003316
William Lallemand5d71a6b2021-11-09 15:25:31 +01003317 ha_notice("New worker (%d) forked\n", ret);
William Lallemand944e6192018-11-21 15:48:31 +01003318 /* find the right mworker_proc */
3319 list_for_each_entry(child, &proc_list, list) {
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003320 if (child->reloads == 0 && child->options & PROC_O_TYPE_WORKER) {
William Lallemand944e6192018-11-21 15:48:31 +01003321 child->timestamp = now.tv_sec;
3322 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003323 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003324 break;
3325 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003326 }
3327 }
William Lallemand944e6192018-11-21 15:48:31 +01003328 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003329
William Lallemand944e6192018-11-21 15:48:31 +01003330 } else {
3331 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003332 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003333 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003334
3335#ifdef USE_CPU_AFFINITY
Willy Tarreau44ea6312021-06-15 08:57:56 +02003336 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 +02003337
David CARLIERdf91cbd2022-01-06 18:53:50 +00003338#if defined(CPUSET_USE_CPUSET) || defined(__DragonFly__)
David CARLIERbb10dad2022-01-08 09:59:38 +00003339 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003340 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
David CARLIERdf91cbd2022-01-06 18:53:50 +00003341#elif defined(__FreeBSD__)
David CARLIERbb10dad2022-01-08 09:59:38 +00003342 struct hap_cpuset *set = &cpu_map.proc;
David CARLIERdf91cbd2022-01-06 18:53:50 +00003343 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003344#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003345 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003346#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003347 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003348 if (pidfd >= 0) {
3349 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3350 close(pidfd);
3351 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003352
3353 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003354 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355
Willy Tarreaud67ff342021-06-15 07:58:09 +02003356 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003357 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
William Lallemandfab0fdc2021-11-09 18:01:22 +01003358 master = 1;
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003359
3360 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3361 (global.mode & MODE_DAEMON)) {
3362 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003363 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3364 stdio_quiet(-1);
3365
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003366 global.mode &= ~MODE_VERBOSE;
3367 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003368 }
3369
William Lallemandfab0fdc2021-11-09 18:01:22 +01003370 if (global.mode & MODE_MWORKER_WAIT) {
3371 /* only the wait mode handles the master CLI */
3372 mworker_loop();
3373 } else {
3374
3375 /* if not in wait mode, reload in wait mode to free the memory */
William Lallemand836bda22021-11-09 18:16:47 +01003376 ha_notice("Loading success.\n");
William Lallemand68836742021-11-10 10:49:06 +01003377 proc_self->failedreloads = 0; /* reset the number of failure */
William Lallemandfab0fdc2021-11-09 18:01:22 +01003378 mworker_reexec_waitmode();
3379 }
William Lallemand1499b9b2017-06-07 15:04:47 +02003380 /* should never get there */
3381 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003382 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003383#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003384 ssl_free_dh();
3385#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003386 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003387 }
3388
William Lallemandcb11fd22017-06-01 17:38:52 +02003389 /* child must never use the atexit function */
3390 atexit_flag = 0;
3391
William Lallemandbc193052018-09-11 10:06:26 +02003392 /* close useless master sockets */
3393 if (global.mode & MODE_MWORKER) {
3394 struct mworker_proc *child, *it;
3395 master = 0;
3396
William Lallemand309dc9a2018-10-26 14:47:45 +02003397 mworker_cli_proxy_stop();
3398
William Lallemandbc193052018-09-11 10:06:26 +02003399 /* free proc struct of other processes */
3400 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003401 /* close the FD of the master side for all
3402 * workers, we don't need to close the worker
3403 * side of other workers since it's done with
3404 * the bind_proc */
William Lallemand7e018782022-01-28 21:56:24 +01003405 if (child->ipc_fd[0] >= 0) {
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003406 close(child->ipc_fd[0]);
William Lallemand7e018782022-01-28 21:56:24 +01003407 child->ipc_fd[0] = -1;
3408 }
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003409 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandce83b4a2018-10-26 14:47:30 +02003410 child->reloads == 0) {
3411 /* keep this struct if this is our pid */
3412 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003413 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003414 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003415 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003416 mworker_free_child(child);
3417 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003418 }
3419 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003420
William Lallemande1340412017-12-28 16:09:36 +01003421 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3422 devnullfd = open("/dev/null", O_RDWR, 0);
3423 if (devnullfd < 0) {
3424 ha_alert("Cannot open /dev/null\n");
3425 exit(EXIT_FAILURE);
3426 }
3427 }
3428
William Lallemand095ba4c2017-06-01 17:38:50 +02003429 /* Must chroot and setgid/setuid in the children */
3430 /* chroot if needed */
3431 if (global.chroot != NULL) {
3432 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003433 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003434 if (nb_oldpids)
3435 tell_old_pids(SIGTTIN);
3436 protocol_unbind_all();
3437 exit(1);
3438 }
3439 }
3440
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003441 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003442 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003443
William Lallemand7f80eb22017-05-26 18:19:55 +02003444 /* pass through every cli socket, and check if it's bound to
3445 * the current process and if it exposes listeners sockets.
3446 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3447 * */
3448
Willy Tarreau4975d142021-03-13 11:00:33 +01003449 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003450 struct bind_conf *bind_conf;
3451
Willy Tarreau4975d142021-03-13 11:00:33 +01003452 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003453 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003454 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3455 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003456 }
3457 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003458 }
3459
William Lallemand2e8fad92018-11-13 16:18:23 +01003460 /*
3461 * This is only done in daemon mode because we might want the
3462 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3463 * we should now close the 3 first FDs to ensure that we can
3464 * detach from the TTY. We MUST NOT do it in other cases since
3465 * it would have already be done, and 0-2 would have been
3466 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003467 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003468 if ((global.mode & MODE_DAEMON) &&
3469 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003470 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003471 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003472 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003473 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3474 }
3475 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003476 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3477 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003478 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003479 }
3480
William Dauchye039f262019-11-17 15:47:15 +01003481 /* try our best to re-enable core dumps depending on system capabilities.
3482 * What is addressed here :
3483 * - remove file size limits
3484 * - remove core size limits
3485 * - mark the process dumpable again if it lost it due to user/group
3486 */
3487 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3488 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3489
3490#if defined(RLIMIT_FSIZE)
3491 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3492 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3493 ha_alert("[%s.main()] Failed to set the raise the maximum "
3494 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003495 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003496 }
3497 else
3498 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003499 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003500 }
3501#endif
3502
3503#if defined(RLIMIT_CORE)
3504 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3505 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3506 ha_alert("[%s.main()] Failed to set the raise the core "
3507 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003508 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003509 }
3510 else
3511 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003512 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003513 }
3514#endif
3515
3516#if defined(USE_PRCTL)
3517 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3518 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3519 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003520#elif defined(USE_PROCCTL)
Willy Tarreau28345c62021-10-08 15:55:13 +02003521 {
3522 int traceable = PROC_TRACE_CTL_ENABLE;
3523 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3524 ha_warning("[%s.main()] Failed to set the traceable flag, "
3525 "no core will be dumped.\n", argv[0]);
3526 }
William Dauchye039f262019-11-17 15:47:15 +01003527#endif
3528 }
3529
Christopher Faulete3a5e352017-10-24 13:53:54 +02003530 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003531 reset_usermsgs_ctx();
3532
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003533 /* start threads 2 and above */
Willy Tarreaud10385a2021-10-06 22:22:40 +02003534 setup_extra_threads(&run_thread_poll_loop);
William Lallemand1aab50b2018-06-07 09:46:01 +02003535
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003536 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003537 haproxy_unblock_signals();
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003538
3539 /* Finally, start the poll loop for the first thread */
Willy Tarreau43ab05b2021-09-28 09:43:11 +02003540 run_thread_poll_loop(&ha_thread_info[0]);
Willy Tarreau2d5d4e02021-09-28 10:36:57 +02003541
3542 /* wait for all threads to terminate */
3543 wait_for_threads_completion();
Christopher Faulet1d17c102017-08-29 15:38:48 +02003544
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003545 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003546}
3547
Willy Tarreaubaaee002006-06-26 02:48:02 +02003548/*
3549 * Local variables:
3550 * c-indent-level: 8
3551 * c-basic-offset: 8
3552 * End:
3553 */