blob: 32a08441d782730ee5717059624c76e70aa1cd58 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
Willy Tarreaua5357cd2021-05-09 06:14:25 +02002 * HAProxy : High Availability-enabled HTTP/TCP proxy
Willy Tarreau421ed392021-01-06 17:41:32 +01003 * Copyright 2000-2021 Willy Tarreau <willy@haproxy.org>.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
Ilya Shipitsin46a030c2020-07-05 16:36:08 +050010 * Please refer to RFC7230 - RFC7235 information about HTTP protocol, and
11 * RFC6265 for information about cookies usage. More generally, the IETF HTTP
Willy Tarreaubaaee002006-06-26 02:48:02 +020012 * Working Group's web site should be consulted for protocol related changes :
13 *
14 * http://ftp.ics.uci.edu/pub/ietf/http/
15 *
16 * Pending bugs (may be not fixed because never reproduced) :
17 * - solaris only : sometimes, an HTTP proxy with only a dispatch address causes
18 * the proxy to terminate (no core) if the client breaks the connection during
19 * the response. Seen on 1.1.8pre4, but never reproduced. May not be related to
20 * the snprintf() bug since requests were simple (GET / HTTP/1.0), but may be
21 * related to missing setsid() (fixed in 1.1.15)
22 * - a proxy with an invalid config will prevent the startup even if disabled.
23 *
24 * ChangeLog has moved to the CHANGELOG file.
25 *
Willy Tarreaubaaee002006-06-26 02:48:02 +020026 */
27
David Carlier7ece0962015-12-08 21:43:09 +000028#define _GNU_SOURCE
Willy Tarreaubaaee002006-06-26 02:48:02 +020029#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <string.h>
33#include <ctype.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020034#include <dirent.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020035#include <sys/stat.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <sys/time.h>
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <netinet/tcp.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42#include <netdb.h>
43#include <fcntl.h>
44#include <errno.h>
45#include <signal.h>
46#include <stdarg.h>
47#include <sys/resource.h>
Tim Duesterhusdfad6a42020-04-18 16:02:47 +020048#include <sys/utsname.h>
Marc-Antoine Perennou992709b2013-02-12 10:53:52 +010049#include <sys/wait.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <time.h>
51#include <syslog.h>
Michael Schererab012dd2013-01-12 18:35:19 +010052#include <grp.h>
Willy Tarreaufc6c0322012-11-16 16:12:27 +010053#ifdef USE_CPU_AFFINITY
Willy Tarreaufc6c0322012-11-16 16:12:27 +010054#include <sched.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000055#if defined(__FreeBSD__) || defined(__DragonFly__)
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020056#include <sys/param.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000057#ifdef __FreeBSD__
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020058#include <sys/cpuset.h>
David Carlier42d9e5a2018-11-12 16:22:19 +000059#endif
David Carlier6d5c8412017-11-29 11:02:32 +000060#include <pthread_np.h>
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +020061#endif
David Carlier5e4c8e22019-09-13 05:12:58 +010062#ifdef __APPLE__
63#include <mach/mach_types.h>
64#include <mach/thread_act.h>
65#include <mach/thread_policy.h>
66#endif
Willy Tarreaufc6c0322012-11-16 16:12:27 +010067#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020068
Willy Tarreau636848a2019-04-15 19:38:50 +020069#if defined(USE_PRCTL)
70#include <sys/prctl.h>
71#endif
72
devnexen@gmail.com21185972021-08-21 09:13:10 +010073#if defined(USE_PROCCTL)
74#include <sys/procctl.h>
75#endif
76
Willy Tarreaubaaee002006-06-26 02:48:02 +020077#ifdef DEBUG_FULL
78#include <assert.h>
79#endif
Tim Duesterhusd6942c82017-11-20 15:58:35 +010080#if defined(USE_SYSTEMD)
81#include <systemd/sd-daemon.h>
82#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +020083
Willy Tarreau6c3a6812020-03-06 18:57:15 +010084#include <import/sha1.h>
85
Willy Tarreaub2551052020-06-09 09:07:15 +020086#include <haproxy/acl.h>
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +010087#include <haproxy/action.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020088#include <haproxy/activity.h>
89#include <haproxy/api.h>
90#include <haproxy/arg.h>
91#include <haproxy/auth.h>
Willy Tarreau8d366972020-05-27 16:10:29 +020092#include <haproxy/base64.h>
Willy Tarreaub2551052020-06-09 09:07:15 +020093#include <haproxy/capture-t.h>
Willy Tarreau66243b42021-07-16 15:39:28 +020094#include <haproxy/cfgcond.h>
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +020095#include <haproxy/cfgdiag.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020096#include <haproxy/cfgparse.h>
Willy Tarreauc13ed532020-06-02 10:22:45 +020097#include <haproxy/chunk.h>
Willy Tarreau83487a82020-06-04 20:19:54 +020098#include <haproxy/cli.h>
Willy Tarreau7ea393d2020-06-04 18:02:10 +020099#include <haproxy/connection.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200100#ifdef USE_CPU_AFFINITY
Amaury Denoyelle982fb532021-04-21 18:39:58 +0200101#include <haproxy/cpuset.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200102#endif
Willy Tarreaueb92deb2020-06-04 10:53:16 +0200103#include <haproxy/dns.h>
Willy Tarreau2741c8c2020-06-02 11:28:02 +0200104#include <haproxy/dynbuf.h>
Willy Tarreau8d366972020-05-27 16:10:29 +0200105#include <haproxy/errors.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200106#include <haproxy/fd.h>
Willy Tarreauc7babd82020-06-04 21:29:29 +0200107#include <haproxy/filters.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200108#include <haproxy/global.h>
Willy Tarreau86416052020-06-04 09:20:54 +0200109#include <haproxy/hlua.h>
Willy Tarreauc761f842020-06-04 11:40:28 +0200110#include <haproxy/http_rules.h>
Willy Tarreau853b2972020-05-27 18:01:47 +0200111#include <haproxy/list.h>
Willy Tarreau213e9902020-06-04 14:58:24 +0200112#include <haproxy/listener.h>
Willy Tarreauaeed4a82020-06-04 22:01:04 +0200113#include <haproxy/log.h>
Willy Tarreaub5abe5b2020-06-04 14:07:37 +0200114#include <haproxy/mworker.h>
Willy Tarreau7a00efb2020-06-02 17:02:59 +0200115#include <haproxy/namespace.h>
Willy Tarreau6131d6a2020-06-02 16:48:09 +0200116#include <haproxy/net_helper.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +0200117#include <haproxy/openssl-compat.h>
Willy Tarreau225a90a2020-06-04 15:06:28 +0200118#include <haproxy/pattern.h>
Willy Tarreau3c2a7c22020-06-04 18:38:21 +0200119#include <haproxy/peers.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200120#include <haproxy/pool.h>
121#include <haproxy/protocol.h>
Willy Tarreaubf3b06b2020-08-26 10:23:40 +0200122#include <haproxy/proto_tcp.h>
Willy Tarreaua264d962020-06-04 22:29:18 +0200123#include <haproxy/proxy.h>
Willy Tarreau7cd8b6e2020-06-02 17:32:26 +0200124#include <haproxy/regex.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200125#include <haproxy/sample.h>
Willy Tarreau1e56f922020-06-04 23:20:13 +0200126#include <haproxy/server.h>
Willy Tarreau48d25b32020-06-04 18:58:52 +0200127#include <haproxy/session.h>
Willy Tarreau3727a8a2020-06-04 17:37:26 +0200128#include <haproxy/signal.h>
Willy Tarreau063d47d2020-08-28 16:29:53 +0200129#include <haproxy/sock.h>
Willy Tarreau25140cc2020-08-28 15:40:33 +0200130#include <haproxy/sock_inet.h>
Willy Tarreau209108d2020-06-04 20:30:20 +0200131#include <haproxy/ssl_sock.h>
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +0200132#include <haproxy/stats-t.h>
Willy Tarreaudfd3de82020-06-04 23:46:14 +0200133#include <haproxy/stream.h>
Willy Tarreaucea0e1b2020-06-04 17:25:40 +0200134#include <haproxy/task.h>
Willy Tarreau3f567e42020-05-28 15:29:19 +0200135#include <haproxy/thread.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200136#include <haproxy/time.h>
137#include <haproxy/tools.h>
138#include <haproxy/uri_auth-t.h>
Willy Tarreaua1718922020-06-04 16:25:31 +0200139#include <haproxy/vars.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200140#include <haproxy/version.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200141
Willy Tarreaubaaee002006-06-26 02:48:02 +0200142
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100143/* array of init calls for older platforms */
144DECLARE_INIT_STAGES;
145
Willy Tarreauf4596402021-04-10 16:53:05 +0200146/* create a read_mostly section to hold variables which are accessed a lot
147 * but which almost never change. The purpose is to isolate them in their
148 * own cache lines where they don't risk to be perturbated by write accesses
149 * to neighbor variables. We need to create an empty aligned variable for
150 * this. The fact that the variable is of size zero means that it will be
151 * eliminated at link time if no other variable uses it, but alignment will
152 * be respected.
153 */
154empty_t __read_mostly_align HA_SECTION("read_mostly") ALIGNED(64);
155
Willy Tarreauf0d3b732021-05-06 16:30:32 +0200156#ifdef BUILD_FEATURES
157const char *build_features = BUILD_FEATURES;
158#else
159const char *build_features = "";
160#endif
161
Willy Tarreau477ecd82010-01-03 21:12:30 +0100162/* list of config files */
163static struct list cfg_cfgfiles = LIST_HEAD_INIT(cfg_cfgfiles);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200164int pid; /* current process id */
165
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100166volatile unsigned long sleeping_thread_mask = 0; /* Threads that are about to sleep in poll() */
Willy Tarreau4b3f27b2020-03-12 17:28:01 +0100167volatile unsigned long stopping_thread_mask = 0; /* Threads acknowledged stopping */
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100168
Willy Tarreaubaaee002006-06-26 02:48:02 +0200169/* global options */
170struct global global = {
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100171 .hard_stop_after = TICK_ETERNITY,
Amaury Denoyelle0f50cb92021-03-26 18:50:33 +0100172 .numa_cpu_mapping = 1,
Willy Tarreau149ab772019-01-26 14:27:06 +0100173 .nbthread = 0,
William Lallemand5f232402012-04-05 18:02:55 +0200174 .req_count = 0,
William Lallemand0f99e342011-10-12 17:50:54 +0200175 .logsrvs = LIST_HEAD_INIT(global.logsrvs),
William Lallemand9d5f5482012-11-07 16:12:57 +0100176 .maxzlibmem = 0,
William Lallemandd85f9172012-11-09 17:05:39 +0100177 .comp_rate_lim = 0,
Emeric Brun850efd52014-01-29 12:24:34 +0100178 .ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED,
Emeric Bruned760922010-10-22 17:59:25 +0200179 .unix_bind = {
180 .ux = {
181 .uid = -1,
182 .gid = -1,
183 .mode = 0,
184 }
185 },
Willy Tarreau27a674e2009-08-17 07:23:33 +0200186 .tune = {
Willy Tarreau7ac908b2019-02-27 12:02:18 +0100187 .options = GTUNE_LISTENER_MQ,
Willy Tarreauc77d3642018-12-12 06:19:42 +0100188 .bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
Christopher Faulet546c4692020-01-22 14:31:21 +0100189 .maxrewrite = MAXREWRITE,
Willy Tarreaua24adf02014-11-27 01:11:56 +0100190 .reserved_bufs = RESERVED_BUFS,
Willy Tarreauf3045d22015-04-29 16:24:50 +0200191 .pattern_cache = DEFAULT_PAT_LRU_SIZE,
Olivier Houchard88698d92019-04-16 19:07:22 +0200192 .pool_low_ratio = 20,
193 .pool_high_ratio = 25,
Christopher Faulet41ba36f2019-07-19 09:36:45 +0200194 .max_http_hdr = MAX_HTTP_HDR,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200195#ifdef USE_OPENSSL
Emeric Brun46635772012-11-14 11:32:56 +0100196 .sslcachesize = SSLCACHESIZE,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200197#endif
William Lallemandf3747832012-11-09 12:33:10 +0100198 .comp_maxlevel = 1,
Willy Tarreau7e312732014-02-12 16:35:14 +0100199#ifdef DEFAULT_IDLE_TIMER
200 .idle_timer = DEFAULT_IDLE_TIMER,
201#else
202 .idle_timer = 1000, /* 1 second */
203#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200204 },
Emeric Brun76d88952012-10-05 15:47:31 +0200205#ifdef USE_OPENSSL
206#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200207 .maxsslconn = DEFAULT_MAXSSLCONN,
208#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200209#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200210 /* others NULL OK */
211};
212
213/*********************************************************************/
214
215int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100216int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200217int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100218int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100219int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100220int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500222/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 * or kill. We will send them a signal every 10 ms until we can bind to all
224 * our ports. With 200 retries, that's about 2 seconds.
225 */
226#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227static int *oldpids = NULL;
228static int oldpids_sig; /* use USR1 or TERM */
229
Olivier Houchardf73629d2017-04-05 22:33:04 +0200230/* Path to the unix socket we use to retrieve listener sockets from the old process */
231static const char *old_unixsocket;
232
William Lallemand85b0bd92017-06-01 17:38:53 +0200233static char *cur_unixsocket = NULL;
234
William Lallemandcb11fd22017-06-01 17:38:52 +0200235int atexit_flag = 0;
236
Willy Tarreaubb545b42010-08-25 12:58:59 +0200237int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238const int zero = 0;
239const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200240const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100242char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200243char *localpeer = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
William Lallemand00417412020-06-05 14:08:41 +0200245static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200246
William Lallemandbc193052018-09-11 10:06:26 +0200247struct list proc_list = LIST_HEAD_INIT(proc_list);
248
249int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100250unsigned int rlim_fd_cur_at_boot = 0;
251unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200252
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100253/* per-boot randomness */
254unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
255
William Lallemandb3f2be32018-09-11 10:06:18 +0200256static void *run_thread_poll_loop(void *data);
257
Willy Tarreauff055502014-04-28 22:27:06 +0200258/* bitfield of a few warnings to emit just once (WARN_*) */
259unsigned int warned = 0;
260
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200261/* set if experimental features have been used for the current process */
262static unsigned int tainted = 0;
263
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200264unsigned int experimental_directives_allowed = 0;
265
266int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
267 char **errmsg)
268{
269 if (kw->flags & KWF_EXPERIMENTAL) {
270 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200271 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 +0200272 file, linenum, kw->kw);
273 return 1;
274 }
275 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
276 }
277
278 return 0;
279}
280
William Lallemande7361152018-10-26 14:47:36 +0200281/* master CLI configuration (-S flag) */
282struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100283
284/* These are strings to be reported in the output of "haproxy -vv". They may
285 * either be constants (in which case must_free must be zero) or dynamically
286 * allocated strings to pass to free() on exit, and in this case must_free
287 * must be non-zero.
288 */
289struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
290struct build_opts_str {
291 struct list list;
292 const char *str;
293 int must_free;
294};
295
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296/*********************************************************************/
297/* general purpose functions ***************************************/
298/*********************************************************************/
299
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100300/* used to register some build option strings at boot. Set must_free to
301 * non-zero if the string must be freed upon exit.
302 */
303void hap_register_build_opts(const char *str, int must_free)
304{
305 struct build_opts_str *b;
306
307 b = calloc(1, sizeof(*b));
308 if (!b) {
309 fprintf(stderr, "out of memory\n");
310 exit(1);
311 }
312 b->str = str;
313 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200314 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100315}
316
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200317#define VERSION_MAX_ELTS 7
318
319/* This function splits an haproxy version string into an array of integers.
320 * The syntax of the supported version string is the following:
321 *
322 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
323 *
324 * This validates for example:
325 * 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
326 * 2.4-dev18-f6818d-20
327 *
328 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
329 * one fixed place in the array. The tags take a numeric value called <e> which
330 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
331 * considered as zero (henxe 1.5 and 1.5.0 are the same).
332 *
333 * The resulting values are:
334 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
335 * 1.2.1 1, 2, 1, 0, 3, 0, 0
336 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
337 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
338 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
339 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
340 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
341 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
342 *
343 * The function returns non-zero if the conversion succeeded, or zero if it
344 * failed.
345 */
346int split_version(const char *version, unsigned int *value)
347{
348 const char *p, *s;
349 char *error;
350 int nelts;
351
352 /* Initialize array with zeroes */
353 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
354 value[nelts] = 0;
355 value[4] = 3;
356
357 p = version;
358
359 /* If the version number is empty, return false */
360 if (*p == '\0')
361 return 0;
362
363 /* Convert first number <a> */
364 value[0] = strtol(p, &error, 10);
365 p = error + 1;
366 if (*error == '\0')
367 return 1;
368 if (*error == '-')
369 goto split_version_tag;
370 if (*error != '.')
371 return 0;
372
373 /* Convert first number <b> */
374 value[1] = strtol(p, &error, 10);
375 p = error + 1;
376 if (*error == '\0')
377 return 1;
378 if (*error == '-')
379 goto split_version_tag;
380 if (*error != '.')
381 return 0;
382
383 /* Convert first number <c> */
384 value[2] = strtol(p, &error, 10);
385 p = error + 1;
386 if (*error == '\0')
387 return 1;
388 if (*error == '-')
389 goto split_version_tag;
390 if (*error != '.')
391 return 0;
392
393 /* Convert first number <d> */
394 value[3] = strtol(p, &error, 10);
395 p = error + 1;
396 if (*error == '\0')
397 return 1;
398 if (*error != '-')
399 return 0;
400
401 split_version_tag:
402 /* Check for commit number */
403 if (*p >= '0' && *p <= '9')
404 goto split_version_commit;
405
406 /* Read tag */
407 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
408 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
409 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
410 else
411 goto split_version_commit;
412
413 /* Convert tag number */
414 value[5] = strtol(p, &error, 10);
415 p = error + 1;
416 if (*error == '\0')
417 return 1;
418 if (*error != '-')
419 return 0;
420
421 split_version_commit:
422 /* Search the last "-" */
423 s = strrchr(p, '-');
424 if (s) {
425 s++;
426 if (*s == '\0')
427 return 0;
428 value[6] = strtol(s, &error, 10);
429 if (*error != '\0')
430 value[6] = 0;
431 return 1;
432 }
433
434 /* convert the version */
435 value[6] = strtol(p, &error, 10);
436 if (*error != '\0')
437 value[6] = 0;
438
439 return 1;
440}
441
442/* This function compares the current haproxy version with an arbitrary version
443 * string. It returns:
444 * -1 : the version in argument is older than the current haproxy version
445 * 0 : the version in argument is the same as the current haproxy version
446 * 1 : the version in argument is newer than the current haproxy version
447 *
448 * Or some errors:
449 * -2 : the current haproxy version is not parsable
450 * -3 : the version in argument is not parsable
451 */
452int compare_current_version(const char *version)
453{
454 unsigned int loc[VERSION_MAX_ELTS];
455 unsigned int mod[VERSION_MAX_ELTS];
456 int i;
457
458 /* split versions */
459 if (!split_version(haproxy_version, loc))
460 return -2;
461 if (!split_version(version, mod))
462 return -3;
463
464 /* compare versions */
465 for (i = 0; i < VERSION_MAX_ELTS; i++) {
466 if (mod[i] < loc[i])
467 return -1;
468 else if (mod[i] > loc[i])
469 return 1;
470 }
471 return 0;
472}
473
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100474static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200475{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200476 struct utsname utsname;
477
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200478 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100479 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100480
481 if (strlen(PRODUCT_URL_BUGS) > 0) {
482 char base_version[20];
483 int dots = 0;
484 char *del;
485
486 /* only retrieve the base version without distro-specific extensions */
487 for (del = haproxy_version; *del; del++) {
488 if (*del == '.')
489 dots++;
490 else if (*del < '0' || *del > '9')
491 break;
492 }
493
494 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
495 if (dots < 2)
496 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
497 else
498 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
499 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200500
501 if (uname(&utsname) == 0) {
502 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
503 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200504}
505
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100506static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100507{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100508 struct build_opts_str *item;
509
Willy Tarreau7b066db2007-12-02 11:28:59 +0100510 printf("Build options :"
511#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100512 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100513#endif
514#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100515 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100516#endif
517#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100518 "\n CC = " BUILD_CC
519#endif
520#ifdef BUILD_CFLAGS
521 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100522#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100523#ifdef BUILD_OPTIONS
524 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100525#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100526#ifdef BUILD_DEBUG
527 "\n DEBUG = " BUILD_DEBUG
528#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100529#ifdef BUILD_FEATURES
530 "\n\nFeature list : " BUILD_FEATURES
531#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200532 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100533 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200534 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100535 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200536
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100537 list_for_each_entry(item, &build_opts_list, list) {
538 puts(item->str);
539 }
540
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100541 putchar('\n');
542
Willy Tarreaube5b6852009-10-03 18:57:08 +0200543 list_pollers(stdout);
544 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200545 list_mux_proto(stdout);
546 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100547 list_services(stdout);
548 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100549 list_filters(stdout);
550 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100551}
552
Willy Tarreaubaaee002006-06-26 02:48:02 +0200553/*
554 * This function prints the command line usage and exits
555 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100556static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200557{
558 display_version();
559 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200560 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200561 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200562 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100563 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200564 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreau6e064432012-05-08 15:40:42 +0200565 " -dM[<byte>] poisons memory with <byte> (defaults to 0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200567 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200568 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100569#if defined(USE_SYSTEMD)
570 " -Ws master-worker mode with systemd notify support.\n"
571#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200572 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200573 " -c check mode : only check config files and exit\n"
Maximilian Maderfc0cceb2021-06-06 00:50:22 +0200574 " -cc check condition : evaluate a condition and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100575 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200576 " -m limits the usable amount of memory (in MB)\n"
577 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200578 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579 " -p writes pids of all children to this file\n"
Willy Tarreaue5733232019-05-22 19:24:06 +0200580#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581 " -de disables epoll() usage even when available\n"
582#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200583#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200584 " -dk disables kqueue() usage even when available\n"
585#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200586#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000587 " -dv disables event ports usage even when available\n"
588#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200589#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200590 " -dp disables poll() usage even when available\n"
591#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200592#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100593 " -dS disables splice usage (broken on old kernels)\n"
594#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200595#if defined(USE_GETADDRINFO)
596 " -dG disables getaddrinfo() usage\n"
597#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000598#if defined(SO_REUSEPORT)
599 " -dR disables SO_REUSEPORT usage\n"
600#endif
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100601 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100602 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200603 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200604 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200605 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200606 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200607 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100609 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610 exit(1);
611}
612
613
614
615/*********************************************************************/
616/* more specific functions ***************************************/
617/*********************************************************************/
618
William Lallemand73b85e72017-06-01 17:38:51 +0200619/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
620 * pids the signal was correctly delivered to.
621 */
William Lallemande25473c2019-04-01 11:29:56 +0200622int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200623{
624 int p;
625 int ret = 0;
626 for (p = 0; p < nb_oldpids; p++)
627 if (kill(oldpids[p], sig) == 0)
628 ret++;
629 return ret;
630}
631
William Lallemand75ea0a02017-11-15 19:02:58 +0100632/*
William Lallemand73b85e72017-06-01 17:38:51 +0200633 * remove a pid forom the olpid array and decrease nb_oldpids
634 * return 1 pid was found otherwise return 0
635 */
636
637int delete_oldpid(int pid)
638{
639 int i;
640
641 for (i = 0; i < nb_oldpids; i++) {
642 if (oldpids[i] == pid) {
643 oldpids[i] = oldpids[nb_oldpids - 1];
644 oldpids[nb_oldpids - 1] = 0;
645 nb_oldpids--;
646 return 1;
647 }
648 }
649 return 0;
650}
651
William Lallemand85b0bd92017-06-01 17:38:53 +0200652
653static void get_cur_unixsocket()
654{
655 /* if -x was used, try to update the stat socket if not available anymore */
Willy Tarreau4975d142021-03-13 11:00:33 +0100656 if (global.cli_fe) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200657 struct bind_conf *bind_conf;
658
659 /* pass through all stats socket */
Willy Tarreau4975d142021-03-13 11:00:33 +0100660 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200661 struct listener *l;
662
663 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
664
Willy Tarreau37159062020-08-27 07:48:42 +0200665 if (l->rx.addr.ss_family == AF_UNIX &&
William Lallemand85b0bd92017-06-01 17:38:53 +0200666 (bind_conf->level & ACCESS_FD_LISTENERS)) {
667 const struct sockaddr_un *un;
668
Willy Tarreau37159062020-08-27 07:48:42 +0200669 un = (struct sockaddr_un *)&l->rx.addr;
William Lallemand85b0bd92017-06-01 17:38:53 +0200670 /* priority to old_unixsocket */
671 if (!cur_unixsocket) {
672 cur_unixsocket = strdup(un->sun_path);
673 } else {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100674 if (old_unixsocket && strcmp(un->sun_path, old_unixsocket) == 0) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200675 free(cur_unixsocket);
676 cur_unixsocket = strdup(old_unixsocket);
677 return;
678 }
679 }
680 }
681 }
682 }
683 }
684 if (!cur_unixsocket && old_unixsocket)
685 cur_unixsocket = strdup(old_unixsocket);
686}
687
William Lallemand73b85e72017-06-01 17:38:51 +0200688/*
689 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800690 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200691 */
William Lallemanda57b7e32018-12-14 21:11:31 +0100692void mworker_reload()
William Lallemand73b85e72017-06-01 17:38:51 +0200693{
William Lallemand00417412020-06-05 14:08:41 +0200694 char **next_argv = NULL;
695 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200696 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200697 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200698 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100699 struct rlimit limit;
William Lallemand7c756a82018-11-26 11:53:40 +0100700 struct per_thread_deinit_fct *ptdf;
William Lallemand73b85e72017-06-01 17:38:51 +0200701
702 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100703#if defined(USE_SYSTEMD)
704 if (global.tune.options & GTUNE_USE_SYSTEMD)
705 sd_notify(0, "RELOADING=1");
706#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200707 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
708
William Lallemandbc193052018-09-11 10:06:26 +0200709 mworker_proc_list_to_env(); /* put the children description in the env */
710
William Lallemand7c756a82018-11-26 11:53:40 +0100711 /* during the reload we must ensure that every FDs that can't be
712 * reuse (ie those that are not referenced in the proc_list)
713 * are closed or they will leak. */
714
715 /* close the listeners FD */
716 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200717
718 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
719 /* close the poller FD and the thread waker pipe FD */
720 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
721 ptdf->fct();
722 if (fdtab)
723 deinit_pollers();
724 }
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500725#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200726 /* close random device FDs */
727 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100728#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100729
Willy Tarreau8dca1952019-03-01 10:21:55 +0100730 /* restore the initial FD limits */
731 limit.rlim_cur = rlim_fd_cur_at_boot;
732 limit.rlim_max = rlim_fd_max_at_boot;
733 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
734 getrlimit(RLIMIT_NOFILE, &limit);
735 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
736 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
737 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
738 }
739
William Lallemand73b85e72017-06-01 17:38:51 +0200740 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200741 while (old_argv[old_argc])
742 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200743
William Lallemand85b0bd92017-06-01 17:38:53 +0200744 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200745 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200746 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200747 if (next_argv == NULL)
748 goto alloc_error;
749
William Lallemand00417412020-06-05 14:08:41 +0200750 /* copy the program name */
751 next_argv[next_argc++] = old_argv[0];
752
753 /* insert the new options just after argv[0] in case we have a -- */
754
William Lallemand73b85e72017-06-01 17:38:51 +0200755 /* add -sf <PID>* to argv */
William Lallemand3f128872019-04-01 11:29:59 +0200756 if (mworker_child_nb() > 0) {
757 struct mworker_proc *child;
758
William Lallemand73b85e72017-06-01 17:38:51 +0200759 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200760
761 list_for_each_entry(child, &proc_list, list) {
William Lallemand677e2f22019-11-19 17:04:18 +0100762 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1 )
William Lallemand3f128872019-04-01 11:29:59 +0200763 continue;
William Lallemand00417412020-06-05 14:08:41 +0200764 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
William Lallemand73b85e72017-06-01 17:38:51 +0200765 goto alloc_error;
766 msg = NULL;
767 }
768 }
William Lallemand2bf6d622017-06-20 11:20:23 +0200769 /* add the -x option with the stat socket */
William Lallemand85b0bd92017-06-01 17:38:53 +0200770 if (cur_unixsocket) {
William Lallemand2bf6d622017-06-20 11:20:23 +0200771 next_argv[next_argc++] = "-x";
772 next_argv[next_argc++] = (char *)cur_unixsocket;
William Lallemand85b0bd92017-06-01 17:38:53 +0200773 }
774
William Lallemand00417412020-06-05 14:08:41 +0200775 /* copy the previous options */
776 for (i = 1; i < old_argc; i++)
777 next_argv[next_argc++] = old_argv[i];
778
Christopher Faulet767a84b2017-11-24 16:50:31 +0100779 ha_warning("Reexecuting Master process\n");
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200780 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100781 execvp(next_argv[0], next_argv);
William Lallemand73b85e72017-06-01 17:38:51 +0200782
Christopher Faulet767a84b2017-11-24 16:50:31 +0100783 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100784 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100785 return;
786
William Lallemand73b85e72017-06-01 17:38:51 +0200787alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100788 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800789 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200790 return;
791}
792
William Lallemandb3f2be32018-09-11 10:06:18 +0200793static void mworker_loop()
794{
795
796#if defined(USE_SYSTEMD)
797 if (global.tune.options & GTUNE_USE_SYSTEMD)
798 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
799#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200800 /* Busy polling makes no sense in the master :-) */
801 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200802
William Lallemandbc193052018-09-11 10:06:26 +0200803 master = 1;
804
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100805 signal_unregister(SIGTTIN);
806 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100807 signal_unregister(SIGUSR1);
808 signal_unregister(SIGHUP);
809 signal_unregister(SIGQUIT);
810
William Lallemandb3f2be32018-09-11 10:06:18 +0200811 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
812 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100813 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
814 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200815 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
816 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
817 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
818 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
819
820 mworker_unblock_signals();
821 mworker_cleanlisteners();
William Lallemand27f3fa52018-12-06 14:05:20 +0100822 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200823
William Lallemandbc193052018-09-11 10:06:26 +0200824 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
825 some SIGCHLD were lost */
826
William Lallemandb3f2be32018-09-11 10:06:18 +0200827 global.nbthread = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200828
William Lallemand2672eb92018-12-14 15:52:39 +0100829#ifdef USE_THREAD
830 tid_bit = 1;
831 all_threads_mask = 1;
832#endif
833
William Lallemandb3f2be32018-09-11 10:06:18 +0200834 jobs++; /* this is the "master" job, we want to take care of the
835 signals even if there is no listener so the poll loop don't
836 leave */
837
838 fork_poller();
Willy Tarreaub4f7cc32019-05-03 09:27:30 +0200839 run_thread_poll_loop(0);
William Lallemandb3f2be32018-09-11 10:06:18 +0200840}
William Lallemandcb11fd22017-06-01 17:38:52 +0200841
842/*
843 * Reexec the process in failure mode, instead of exiting
844 */
845void reexec_on_failure()
846{
847 if (!atexit_flag)
848 return;
849
850 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
851
Christopher Faulet767a84b2017-11-24 16:50:31 +0100852 ha_warning("Reexecuting Master process in waitpid mode\n");
William Lallemandcb11fd22017-06-01 17:38:52 +0200853 mworker_reload();
William Lallemandcb11fd22017-06-01 17:38:52 +0200854}
William Lallemand73b85e72017-06-01 17:38:51 +0200855
856
857/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200858 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
859 * a signal zero to all subscribers. This means that it's as easy as
860 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200861 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100862static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200863{
864 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200865 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100866 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200867}
868
869/*
870 * upon SIGTTOU, we pause everything
871 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100872static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200873{
Willy Tarreau775e0012020-09-24 16:36:26 +0200874 if (protocol_pause_all() & ERR_FATAL) {
875 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200876 ha_warning("%s", msg);
877 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200878 soft_stop();
879 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100880 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200881}
882
883/*
884 * upon SIGTTIN, let's have a soft stop.
885 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100886static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887{
Willy Tarreau775e0012020-09-24 16:36:26 +0200888 if (protocol_resume_all() & ERR_FATAL) {
889 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 +0200890 ha_warning("%s", msg);
891 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200892 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200893}
894
895/*
896 * this function dumps every server's state when the process receives SIGHUP.
897 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100898static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200899{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100900 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200901
Christopher Faulet767a84b2017-11-24 16:50:31 +0100902 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200903 while (p) {
904 struct server *s = p->srv;
905
906 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
907 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100908 chunk_printf(&trash,
909 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
910 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200911 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreaua0570452021-06-18 09:30:30 +0200912 s->cur_sess, s->queue.length, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200913 ha_warning("%s\n", trash.area);
914 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200915 s = s->next;
916 }
917
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200918 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
919 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100920 chunk_printf(&trash,
921 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
922 p->id,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200923 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 +0200924 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100925 chunk_printf(&trash,
926 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
927 p->id,
928 (p->srv_bck) ? "is running on backup servers" : "has no server available",
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200929 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 +0200930 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100931 chunk_printf(&trash,
932 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
933 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
934 p->id, p->srv_act, p->srv_bck,
Willy Tarreau7f3c1df2021-06-18 09:22:21 +0200935 p->feconn, p->beconn, p->totpend, p->queue.length, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200936 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200937 ha_warning("%s\n", trash.area);
938 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200939
940 p = p->next;
941 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200942}
943
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100944static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200946 /* dump memory usage then free everything possible */
947 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100948 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949}
950
William Lallemande1340412017-12-28 16:09:36 +0100951/*
952 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
953 * If <fd> < 0, it opens /dev/null and use it to dup
954 *
955 * In the case of chrooting, you have to open /dev/null before the chroot, and
956 * pass the <fd> to this function
957 */
958static void stdio_quiet(int fd)
959{
960 if (fd < 0)
961 fd = open("/dev/null", O_RDWR, 0);
962
963 if (fd > -1) {
964 fclose(stdin);
965 fclose(stdout);
966 fclose(stderr);
967
968 dup2(fd, 0);
969 dup2(fd, 1);
970 dup2(fd, 2);
971 if (fd > 2)
972 close(fd);
973 return;
974 }
975
976 ha_alert("Cannot open /dev/null\n");
977 exit(EXIT_FAILURE);
978}
979
980
Joseph Herlant03420902018-11-15 10:41:50 -0800981/* This function checks if cfg_cfgfiles contains directories.
982 * If it finds one, it adds all the files (and only files) it contains
983 * in cfg_cfgfiles in place of the directory (and removes the directory).
984 * It adds the files in lexical order.
985 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200986 * It doesn't add files with name starting with '.'
987 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100988static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200989{
990 struct wordlist *wl, *wlb;
991 char *err = NULL;
992
993 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
994 struct stat file_stat;
995 struct dirent **dir_entries = NULL;
996 int dir_entries_nb;
997 int dir_entries_it;
998
999 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001000 ha_alert("Cannot open configuration file/directory %s : %s\n",
1001 wl->s,
1002 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001003 exit(1);
1004 }
1005
1006 if (!S_ISDIR(file_stat.st_mode))
1007 continue;
1008
1009 /* from this point wl->s is a directory */
1010
1011 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1012 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001013 ha_alert("Cannot open configuration directory %s : %s\n",
1014 wl->s,
1015 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001016 exit(1);
1017 }
1018
1019 /* for each element in the directory wl->s */
1020 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1021 struct dirent *dir_entry = dir_entries[dir_entries_it];
1022 char *filename = NULL;
1023 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1024
1025 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001026 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001027 */
1028 if (dir_entry->d_name[0] == '.' ||
1029 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1030 goto next_dir_entry;
1031
1032 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001033 ha_alert("Cannot load configuration files %s : out of memory.\n",
1034 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001035 exit(1);
1036 }
1037
1038 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001039 ha_alert("Cannot open configuration file %s : %s\n",
1040 wl->s,
1041 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001042 exit(1);
1043 }
1044
1045 /* don't add anything else than regular file in cfg_cfgfiles
1046 * this way we avoid loops
1047 */
1048 if (!S_ISREG(file_stat.st_mode))
1049 goto next_dir_entry;
1050
1051 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001052 ha_alert("Cannot load configuration files %s : %s\n",
1053 filename,
1054 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001055 exit(1);
1056 }
1057
1058next_dir_entry:
1059 free(filename);
1060 free(dir_entry);
1061 }
1062
1063 free(dir_entries);
1064
1065 /* remove the current directory (wl) from cfg_cfgfiles */
1066 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001067 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001068 free(wl);
1069 }
1070
1071 free(err);
1072}
1073
Willy Tarreaubaaee002006-06-26 02:48:02 +02001074/*
William Lallemand73b85e72017-06-01 17:38:51 +02001075 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001076 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001077 * Return an allocated copy of argv
1078 */
1079
1080static char **copy_argv(int argc, char **argv)
1081{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001082 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001083
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001084 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001085 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001086 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001087 return NULL;
1088 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001089 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001090
William Lallemanddf6c5a82020-06-04 17:40:23 +02001091 /* first copy argv[0] */
1092 *newargv++ = *argv++;
1093 argc--;
1094
1095 while (argc > 0) {
1096 if (**argv != '-') {
1097 /* non options are copied but will fail in the argument parser */
1098 *newargv++ = *argv++;
1099 argc--;
1100
1101 } else {
1102 char *flag;
1103
1104 flag = *argv + 1;
1105
1106 if (flag[0] == '-' && flag[1] == 0) {
1107 /* "--\0" copy every arguments till the end of argv */
1108 *newargv++ = *argv++;
1109 argc--;
1110
1111 while (argc > 0) {
1112 *newargv++ = *argv++;
1113 argc--;
1114 }
1115 } else {
1116 switch (*flag) {
1117 case 's':
1118 /* -sf / -st and their parameters are ignored */
1119 if (flag[1] == 'f' || flag[1] == 't') {
1120 argc--;
1121 argv++;
1122 /* The list can't contain a negative value since the only
1123 way to know the end of this list is by looking for the
1124 next option or the end of the options */
1125 while (argc > 0 && argv[0][0] != '-') {
1126 argc--;
1127 argv++;
1128 }
William Lallemand398da622020-09-02 16:12:23 +02001129 } else {
1130 argc--;
1131 argv++;
1132
William Lallemanddf6c5a82020-06-04 17:40:23 +02001133 }
1134 break;
1135
1136 case 'x':
1137 /* this option and its parameter are ignored */
1138 argc--;
1139 argv++;
1140 if (argc > 0) {
1141 argc--;
1142 argv++;
1143 }
1144 break;
1145
1146 case 'C':
1147 case 'n':
1148 case 'm':
1149 case 'N':
1150 case 'L':
1151 case 'f':
1152 case 'p':
1153 case 'S':
1154 /* these options have only 1 parameter which must be copied and can start with a '-' */
1155 *newargv++ = *argv++;
1156 argc--;
1157 if (argc == 0)
1158 goto error;
1159 *newargv++ = *argv++;
1160 argc--;
1161 break;
1162 default:
1163 /* for other options just copy them without parameters, this is also done
1164 * for options like "--foo", but this will fail in the argument parser.
1165 * */
1166 *newargv++ = *argv++;
1167 argc--;
1168 break;
1169 }
William Lallemand73b85e72017-06-01 17:38:51 +02001170 }
1171 }
William Lallemand73b85e72017-06-01 17:38:51 +02001172 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001173
William Lallemanddf6c5a82020-06-04 17:40:23 +02001174 return retargv;
1175
1176error:
1177 free(retargv);
1178 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001179}
1180
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001181
1182/* Performs basic random seed initialization. The main issue with this is that
1183 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1184 * which means that there will only be 4 billion possible random sequences once
1185 * srandom() is called, regardless of the internal state. Not calling it is
1186 * even worse as we'll always produce the same randoms sequences. What we do
1187 * here is to create an initial sequence from various entropy sources, hash it
1188 * using SHA1 and keep the resulting 160 bits available globally.
1189 *
1190 * We initialize the current process with the first 32 bits before starting the
1191 * polling loop, where all this will be changed to have process specific and
1192 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001193 *
1194 * Before starting threads, it's still possible to call random() as srandom()
1195 * is initialized from this, but after threads and/or processes are started,
1196 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001197 */
1198static void ha_random_boot(char *const *argv)
1199{
1200 unsigned char message[256];
1201 unsigned char *m = message;
1202 struct timeval tv;
1203 blk_SHA_CTX ctx;
1204 unsigned long l;
1205 int fd;
1206 int i;
1207
1208 /* start with current time as pseudo-random seed */
1209 gettimeofday(&tv, NULL);
1210 write_u32(m, tv.tv_sec); m += 4;
1211 write_u32(m, tv.tv_usec); m += 4;
1212
1213 /* PID and PPID add some OS-based randomness */
1214 write_u16(m, getpid()); m += 2;
1215 write_u16(m, getppid()); m += 2;
1216
1217 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1218 fd = open("/dev/urandom", O_RDONLY);
1219 if (fd >= 0) {
1220 i = read(fd, m, 20);
1221 if (i > 0)
1222 m += i;
1223 close(fd);
1224 }
1225
1226 /* take up to 160 bits bytes from openssl (non-blocking) */
1227#ifdef USE_OPENSSL
1228 if (RAND_bytes(m, 20) == 1)
1229 m += 20;
1230#endif
1231
1232 /* take 160 bits from existing random in case it was already initialized */
1233 for (i = 0; i < 5; i++) {
1234 write_u32(m, random());
1235 m += 4;
1236 }
1237
1238 /* stack address (benefit form operating system's ASLR) */
1239 l = (unsigned long)&m;
1240 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1241
1242 /* argv address (benefit form operating system's ASLR) */
1243 l = (unsigned long)&argv;
1244 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1245
1246 /* use tv_usec again after all the operations above */
1247 gettimeofday(&tv, NULL);
1248 write_u32(m, tv.tv_usec); m += 4;
1249
1250 /*
1251 * At this point, ~84-92 bytes have been used
1252 */
1253
1254 /* finish with the hostname */
1255 strncpy((char *)m, hostname, message + sizeof(message) - m);
1256 m += strlen(hostname);
1257
1258 /* total message length */
1259 l = m - message;
1260
1261 memset(&ctx, 0, sizeof(ctx));
1262 blk_SHA1_Init(&ctx);
1263 blk_SHA1_Update(&ctx, message, l);
1264 blk_SHA1_Final(boot_seed, &ctx);
1265
1266 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001267 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001268}
1269
Willy Tarreau5a023f02019-03-01 14:19:31 +01001270/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1271 * setting, and returns it. It may return -1 meaning "unlimited" if some
1272 * unlimited proxies have been found and the global.maxconn value is not yet
1273 * set. It may also return a value greater than maxconn if it's not yet set.
1274 * Note that a value of zero means there is no need for pipes. -1 is never
1275 * returned if global.maxconn is valid.
1276 */
1277static int compute_ideal_maxpipes()
1278{
1279 struct proxy *cur;
1280 int nbfe = 0, nbbe = 0;
1281 int unlimited = 0;
1282 int pipes;
1283 int max;
1284
1285 for (cur = proxies_list; cur; cur = cur->next) {
1286 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1287 if (cur->cap & PR_CAP_FE) {
1288 max = cur->maxconn;
1289 nbfe += max;
1290 if (!max) {
1291 unlimited = 1;
1292 break;
1293 }
1294 }
1295 if (cur->cap & PR_CAP_BE) {
1296 max = cur->fullconn ? cur->fullconn : global.maxconn;
1297 nbbe += max;
1298 if (!max) {
1299 unlimited = 1;
1300 break;
1301 }
1302 }
1303 }
1304 }
1305
1306 pipes = MAX(nbfe, nbbe);
1307 if (global.maxconn) {
1308 if (pipes > global.maxconn || unlimited)
1309 pipes = global.maxconn;
1310 } else if (unlimited) {
1311 pipes = -1;
1312 }
1313
1314 return pipes >= 4 ? pipes / 4 : pipes;
1315}
1316
Willy Tarreauac350932019-03-01 15:43:14 +01001317/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1318 * rlimits and computes an ideal maxconn. It's meant to be called only when
1319 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001320 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1321 * default 100) is returned as it is expected that it will even run on tight
1322 * environments, and will maintain compatibility with previous packages that
1323 * used to rely on this value as the default one. The system will emit a
1324 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001325 */
1326static int compute_ideal_maxconn()
1327{
1328 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1329 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1330 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001331 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001332 int maxconn;
1333
1334 /* we have to take into account these elements :
1335 * - number of engine_fds, which inflates the number of FD needed per
1336 * connection by this number.
1337 * - number of pipes per connection on average : for the unlimited
1338 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1339 * fixed value of 2*pipes.
1340 * - two FDs per connection
1341 */
1342
1343 /* subtract listeners and checks */
1344 remain -= global.maxsock;
1345
Willy Tarreau3f200852019-03-14 19:13:17 +01001346 /* one epoll_fd/kqueue_fd per thread */
1347 remain -= global.nbthread;
1348
1349 /* one wake-up pipe (2 fd) per thread */
1350 remain -= 2 * global.nbthread;
1351
Willy Tarreauac350932019-03-01 15:43:14 +01001352 /* Fixed pipes values : we only subtract them if they're not larger
1353 * than the remaining FDs because pipes are optional.
1354 */
1355 if (pipes >= 0 && pipes * 2 < remain)
1356 remain -= pipes * 2;
1357
1358 if (pipes < 0) {
1359 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1360 * = maxconn * (2 + 0.5 + engine_fds)
1361 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1362 */
1363 maxconn = 2 * remain / (5 + 2 * engine_fds);
1364 } else {
1365 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1366 * = maxconn * (2 + engine_fds)
1367 */
1368 maxconn = remain / (2 + engine_fds);
1369 }
1370
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001371 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001372}
1373
Willy Tarreaua409f302020-03-10 17:08:53 +01001374/* computes the estimated maxsock value for the given maxconn based on the
1375 * possibly set global.maxpipes and existing partial global.maxsock. It may
1376 * temporarily change global.maxconn for the time needed to propagate the
1377 * computations, and will reset it.
1378 */
1379static int compute_ideal_maxsock(int maxconn)
1380{
1381 int maxpipes = global.maxpipes;
1382 int maxsock = global.maxsock;
1383
1384
1385 if (!maxpipes) {
1386 int old_maxconn = global.maxconn;
1387
1388 global.maxconn = maxconn;
1389 maxpipes = compute_ideal_maxpipes();
1390 global.maxconn = old_maxconn;
1391 }
1392
1393 maxsock += maxconn * 2; /* each connection needs two sockets */
1394 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1395 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1396 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1397
1398 /* compute fd used by async engines */
1399 if (global.ssl_used_async_engines) {
1400 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1401
1402 maxsock += maxconn * sides * global.ssl_used_async_engines;
1403 }
1404 return maxsock;
1405}
1406
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001407/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001408 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1409 * value is accepted, non-zero otherwise. This is used to determine if an
1410 * automatic limit may be applied or not. When it is not, the caller knows that
1411 * the highest we can do is the rlim_max at boot. In case of error, we return
1412 * that the setting is possible, so that we defer the error processing to the
1413 * final stage in charge of enforcing this.
1414 */
1415static int check_if_maxsock_permitted(int maxsock)
1416{
1417 struct rlimit orig_limit, test_limit;
1418 int ret;
1419
1420 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1421 return 1;
1422
1423 /* don't go further if we can't even set to what we have */
1424 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1425 return 1;
1426
1427 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1428 test_limit.rlim_cur = test_limit.rlim_max;
1429 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1430
1431 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1432 return 1;
1433
1434 return ret == 0;
1435}
1436
Amaury Denoyelle484454d2021-05-05 16:18:45 +02001437void mark_tainted(const enum tainted_flags flag)
1438{
1439 HA_ATOMIC_OR(&tainted, flag);
1440}
1441
1442unsigned int get_tainted()
1443{
1444 int tainted_state;
1445 HA_ATOMIC_STORE(&tainted_state, tainted);
1446 return tainted_state;
1447}
Willy Tarreau304e17e2020-03-10 17:54:54 +01001448
William Lallemand73b85e72017-06-01 17:38:51 +02001449/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 * This function initializes all the necessary variables. It only returns
1451 * if everything is OK. If something fails, it exits.
1452 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001453static void init(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454{
Willy Tarreaubaaee002006-06-26 02:48:02 +02001455 int arg_mode = 0; /* MODE_DEBUG, ... */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001456 char *tmp;
1457 char *cfg_pidfile = NULL;
Willy Tarreau058e9072009-07-20 09:30:05 +02001458 int err_code = 0;
Maxime de Roucy0f503922016-05-13 23:52:55 +02001459 char *err_msg = NULL;
Willy Tarreau477ecd82010-01-03 21:12:30 +01001460 struct wordlist *wl;
Kevinm48936af2010-12-22 16:08:21 +00001461 char *progname;
Willy Tarreau576132e2011-09-10 19:26:56 +02001462 char *change_dir = NULL;
Christopher Fauletd7c91962015-04-30 11:48:27 +02001463 struct proxy *px;
Willy Tarreaue6945732016-12-21 19:57:00 +01001464 struct post_check_fct *pcf;
Willy Tarreauac350932019-03-01 15:43:14 +01001465 int ideal_maxconn;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001466 char *check_condition = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467
Christopher Faulete3a5e352017-10-24 13:53:54 +02001468 global.mode = MODE_STARTING;
William Lallemand00417412020-06-05 14:08:41 +02001469 old_argv = copy_argv(argc, argv);
1470 if (!old_argv) {
William Lallemanddf6c5a82020-06-04 17:40:23 +02001471 ha_alert("failed to copy argv.\n");
1472 exit(1);
1473 }
William Lallemand73b85e72017-06-01 17:38:51 +02001474
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001475 if (!init_trash_buffers(1)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001476 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet748919a2017-07-26 14:59:46 +02001477 exit(1);
1478 }
David du Colombier7af46052012-05-16 14:16:48 +02001479
Emeric Brun2b920a12010-09-23 18:30:22 +02001480 /* NB: POSIX does not make it mandatory for gethostname() to NULL-terminate
1481 * the string in case of truncation, and at least FreeBSD appears not to do
1482 * it.
1483 */
1484 memset(hostname, 0, sizeof(hostname));
1485 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001486
1487 if ((localpeer = strdup(hostname)) == NULL) {
1488 ha_alert("Cannot allocate memory for local peer.\n");
1489 exit(EXIT_FAILURE);
1490 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001491 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Emeric Brun2b920a12010-09-23 18:30:22 +02001492
William Lallemand24c928c2020-01-14 17:58:18 +01001493 /* we were in mworker mode, we should restart in mworker mode */
1494 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1495 global.mode |= MODE_MWORKER;
1496
Willy Tarreaubaaee002006-06-26 02:48:02 +02001497 /*
1498 * Initialize the previously static variables.
1499 */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001500
Willy Tarreau173d9952018-01-26 21:48:23 +01001501 totalconn = actconn = listeners = stopping = 0;
Cyril Bonté203ec5a2017-03-23 22:44:13 +01001502 killed = 0;
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001503
Willy Tarreaubaaee002006-06-26 02:48:02 +02001504
1505#ifdef HAPROXY_MEMMAX
Willy Tarreau70060452015-12-14 12:46:07 +01001506 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001507#endif
1508
Benoit GARNIERb413c2a2016-03-27 11:08:03 +02001509 tzset();
Willy Tarreauc4c80fb2021-04-11 15:00:34 +02001510 tv_init_process_date();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001511 start_date = now;
1512
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001513 ha_random_boot(argv);
Willy Tarreau84310e22014-02-14 11:59:04 +01001514
Willy Tarreau8ed669b2013-01-11 15:49:37 +01001515 if (init_acl() != 0)
1516 exit(1);
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001517
Amaury Denoyellec593bcd2021-05-19 15:35:29 +02001518#ifdef USE_OPENSSL
1519 /* Initialize the random generator.
1520 * Must be called before chroot for access to /dev/urandom
1521 */
1522 if (!ssl_initialize_random()) {
1523 ha_alert("OpenSSL random data generator initialization failed.\n");
1524 exit(1);
1525 }
1526#endif
1527
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001528 /* Initialise lua. */
1529 hlua_init();
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001530
Christopher Fauletff2613e2016-11-09 11:36:17 +01001531 /* Initialize process vars */
Willy Tarreaub7bfcb32021-08-31 08:13:25 +02001532 vars_init_head(&proc_vars, SCOPE_PROC);
Christopher Fauletff2613e2016-11-09 11:36:17 +01001533
Willy Tarreau43b78992009-01-25 15:42:27 +01001534 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001535#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001536 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001538#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001539 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001540#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001541#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001542 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001543#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001544#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001545 global.tune.options |= GTUNE_USE_EVPORTS;
1546#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001547#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001548 global.tune.options |= GTUNE_USE_SPLICE;
1549#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001550#if defined(USE_GETADDRINFO)
1551 global.tune.options |= GTUNE_USE_GAI;
1552#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001553#if defined(SO_REUSEPORT)
1554 global.tune.options |= GTUNE_USE_REUSEPORT;
1555#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001556#ifdef USE_THREAD
1557 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1558#endif
William Dauchya5194602020-03-28 19:29:58 +01001559 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560
1561 pid = getpid();
1562 progname = *argv;
1563 while ((tmp = strchr(progname, '/')) != NULL)
1564 progname = tmp + 1;
1565
Kevinm48936af2010-12-22 16:08:21 +00001566 /* the process name is used for the logs only */
Eric Salama7cea6062020-10-02 11:58:19 +02001567 chunk_initlen(&global.log_tag, strdup(progname), strlen(progname), strlen(progname));
1568 if (b_orig(&global.log_tag) == NULL) {
1569 chunk_destroy(&global.log_tag);
1570 ha_alert("Cannot allocate memory for log_tag.\n");
1571 exit(EXIT_FAILURE);
1572 }
Kevinm48936af2010-12-22 16:08:21 +00001573
Willy Tarreaubaaee002006-06-26 02:48:02 +02001574 argc--; argv++;
1575 while (argc > 0) {
1576 char *flag;
1577
1578 if (**argv == '-') {
1579 flag = *argv+1;
1580
1581 /* 1 arg */
1582 if (*flag == 'v') {
1583 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001584 if (flag[1] == 'v') /* -vv */
1585 display_build_opts();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 exit(0);
1587 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001588#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001590 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001592#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001593 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001594 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001595#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001596#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001597 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001598 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001599#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001600#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001601 else if (*flag == 'd' && flag[1] == 'v')
1602 global.tune.options &= ~GTUNE_USE_EVPORTS;
1603#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001604#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001605 else if (*flag == 'd' && flag[1] == 'S')
1606 global.tune.options &= ~GTUNE_USE_SPLICE;
1607#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001608#if defined(USE_GETADDRINFO)
1609 else if (*flag == 'd' && flag[1] == 'G')
1610 global.tune.options &= ~GTUNE_USE_GAI;
1611#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001612#if defined(SO_REUSEPORT)
1613 else if (*flag == 'd' && flag[1] == 'R')
1614 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1615#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001616 else if (*flag == 'd' && flag[1] == 'V')
1617 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001618 else if (*flag == 'V')
1619 arg_mode |= MODE_VERBOSE;
1620 else if (*flag == 'd' && flag[1] == 'b')
1621 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001622 else if (*flag == 'd' && flag[1] == 'D')
1623 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001624 else if (*flag == 'd' && flag[1] == 'W')
1625 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreau6e064432012-05-08 15:40:42 +02001626 else if (*flag == 'd' && flag[1] == 'M')
1627 mem_poison_byte = flag[2] ? strtol(flag + 2, NULL, 0) : 'P';
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001628 else if (*flag == 'd' && flag[1] == 'r')
1629 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001630 else if (*flag == 'd')
1631 arg_mode |= MODE_DEBUG;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001632 else if (*flag == 'c' && flag[1] == 'c') {
1633 arg_mode |= MODE_CHECK_CONDITION;
1634 argv++;
1635 argc--;
1636 check_condition = *argv;
1637 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001638 else if (*flag == 'c')
1639 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001640 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001641 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001642 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001643 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001644#if defined(USE_SYSTEMD)
1645 global.tune.options |= GTUNE_USE_SYSTEMD;
1646#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001647 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 +01001648 usage(progname);
1649#endif
1650 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001651 else if (*flag == 'W')
1652 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001653 else if (*flag == 'q')
1654 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001655 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001656 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001657 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001658 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001659 }
William Lallemand4fc09692017-06-19 16:37:19 +02001660 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001661 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001662 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001663
Olivier Houchardf73629d2017-04-05 22:33:04 +02001664 argv++;
1665 argc--;
1666 }
William Lallemande7361152018-10-26 14:47:36 +02001667 else if (*flag == 'S') {
1668 struct wordlist *c;
1669
William Lallemanda6b32492020-06-04 23:49:20 +02001670 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001671 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1672 usage(progname);
1673 }
1674 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1675 ha_alert("Cannot allocate memory\n");
1676 exit(EXIT_FAILURE);
1677 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001678 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001679
1680 argv++;
1681 argc--;
1682 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001683 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1684 /* list of pids to finish ('f') or terminate ('t') */
1685
1686 if (flag[1] == 'f')
1687 oldpids_sig = SIGUSR1; /* finish then exit */
1688 else
1689 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001690 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001691 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001692 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1693 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001694 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001695 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001696 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001697 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001698 errno = 0;
1699 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1700 if (errno) {
1701 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1702 flag,
1703 *argv, strerror(errno));
1704 exit(1);
1705 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001706 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001707 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001708 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1709 flag, endptr);
1710 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001711 }
Chris Lane236062f2018-02-05 23:15:44 +00001712 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001713 if (oldpids[nb_oldpids] <= 0)
1714 usage(progname);
1715 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001716 }
1717 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001718 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1719 /* now that's a cfgfile list */
1720 argv++; argc--;
1721 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001722 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001723 ha_alert("Cannot load configuration file/directory %s : %s\n",
1724 *argv,
1725 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001726 exit(1);
1727 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001728 argv++; argc--;
1729 }
1730 break;
1731 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001732 else { /* >=2 args */
1733 argv++; argc--;
1734 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001735 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736
1737 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001738 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001740 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001741 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001742 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001743 free(localpeer);
1744 if ((localpeer = strdup(*argv)) == NULL) {
1745 ha_alert("Cannot allocate memory for local peer.\n");
1746 exit(EXIT_FAILURE);
1747 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001748 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001749 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001750 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001751 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001752 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001753 ha_alert("Cannot load configuration file/directory %s : %s\n",
1754 *argv,
1755 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001756 exit(1);
1757 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001758 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001759 case 'p' : cfg_pidfile = *argv; break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001760 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001761 }
1762 }
1763 }
1764 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001765 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001766 argv++; argc--;
1767 }
1768
Christopher Faulete3a5e352017-10-24 13:53:54 +02001769 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001770 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001771 | MODE_DIAG | MODE_CHECK_CONDITION));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001772
William Lallemand944e6192018-11-21 15:48:31 +01001773 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001774 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001775 global.mode |= MODE_MWORKER_WAIT;
1776 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001777 }
1778
Willy Tarreau26146192021-07-21 10:01:36 +02001779 if ((global.mode & (MODE_MWORKER | MODE_CHECK | MODE_CHECK_CONDITION)) == MODE_MWORKER &&
1780 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001781 atexit_flag = 1;
1782 atexit(reexec_on_failure);
1783 }
1784
Willy Tarreau576132e2011-09-10 19:26:56 +02001785 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001786 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001787 exit(1);
1788 }
1789
Willy Tarreaubaaee002006-06-26 02:48:02 +02001790 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001791
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001792#ifdef USE_CPU_AFFINITY
1793 {
1794 int i;
Willy Tarreau44ea6312021-06-15 08:57:56 +02001795 ha_cpuset_zero(&cpu_map.proc);
1796 ha_cpuset_zero(&cpu_map.proc_t1);
Willy Tarreau26f42a02021-05-14 08:26:38 +02001797 for (i = 0; i < MAX_THREADS; ++i) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02001798 ha_cpuset_zero(&cpu_map.thread[i]);
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001799 }
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001800 }
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001801#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001802
Amaury Denoyelle11124302021-06-04 18:22:08 +02001803 usermsgs_clr("config");
1804
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001805 if (global.mode & MODE_CHECK_CONDITION) {
1806 int result;
1807
1808 uint32_t err;
1809 const char *errptr;
1810 char *errmsg = NULL;
1811
1812 char *args[MAX_LINE_ARGS+1];
1813 int arg = sizeof(args) / sizeof(*args);
1814 size_t outlen = strlen(check_condition) + 1;
Willy Tarreauc8194c32021-07-16 16:38:58 +02001815 char *w;
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001816
1817 err = parse_line(check_condition, check_condition, &outlen, args, &arg,
Willy Tarreaua87e7822021-07-16 19:14:54 +02001818 PARSE_OPT_ENV | PARSE_OPT_WORD_EXPAND | PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001819 &errptr);
1820
1821 if (err & PARSE_ERR_QUOTE) {
1822 ha_alert("Syntax Error in condition: Unmatched quote.\n");
1823 exit(2);
1824 }
1825
1826 if (err & PARSE_ERR_HEX) {
1827 ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
1828 exit(2);
1829 }
1830
1831 if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
1832 ha_alert("Error in condition: Line too long.\n");
1833 exit(2);
1834 }
1835
Willy Tarreauc8194c32021-07-16 16:38:58 +02001836 if (err & PARSE_ERR_TOOMANY) {
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001837 ha_alert("Error in condition: Too many words.\n");
1838 exit(2);
1839 }
1840
1841 if (err) {
1842 ha_alert("Unhandled error in condition, please report this to the developers.\n");
1843 exit(2);
1844 }
1845
Willy Tarreauc8194c32021-07-16 16:38:58 +02001846 /* remerge all words into a single expression */
1847 for (w = *args; (w += strlen(w)) < check_condition + outlen - 1; *w = ' ')
1848 ;
1849
Maximilian Maderfc0cceb2021-06-06 00:50:22 +02001850 result = cfg_eval_condition(args, &errmsg, &errptr);
1851
1852 if (result < 0) {
1853 if (errmsg)
1854 ha_alert("Failed to evaluate condition: %s\n", errmsg);
1855
1856 exit(2);
1857 }
1858
1859 exit(result ? 0 : 1);
1860 }
1861
William Lallemand944e6192018-11-21 15:48:31 +01001862 /* in wait mode, we don't try to read the configuration files */
1863 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001864 char *env_cfgfiles = NULL;
1865 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001866
William Lallemand944e6192018-11-21 15:48:31 +01001867 /* handle cfgfiles that are actually directories */
1868 cfgfiles_expand_directories();
1869
1870 if (LIST_ISEMPTY(&cfg_cfgfiles))
1871 usage(progname);
1872
1873
1874 list_for_each_entry(wl, &cfg_cfgfiles, list) {
1875 int ret;
1876
Christopher Faulet4e366822021-01-12 18:57:38 +01001877 if (env_err == 0) {
1878 if (!memprintf(&env_cfgfiles, "%s%s%s",
1879 (env_cfgfiles ? env_cfgfiles : ""),
1880 (env_cfgfiles ? ";" : ""), wl->s))
1881 env_err = 1;
1882 }
William Lallemand7b302d82019-05-20 11:15:37 +02001883
William Lallemand944e6192018-11-21 15:48:31 +01001884 ret = readcfgfile(wl->s);
1885 if (ret == -1) {
1886 ha_alert("Could not open configuration file %s : %s\n",
1887 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01001888 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001889 exit(1);
1890 }
1891 if (ret & (ERR_ABORT|ERR_FATAL))
1892 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
1893 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01001894 if (err_code & ERR_ABORT) {
1895 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001896 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01001897 }
Willy Tarreauc4382422009-12-06 13:10:44 +01001898 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001899
William Lallemand944e6192018-11-21 15:48:31 +01001900 /* do not try to resolve arguments nor to spot inconsistencies when
1901 * the configuration contains fatal errors caused by files not found
1902 * or failed memory allocations.
1903 */
1904 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1905 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01001906 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001907 exit(1);
1908 }
Christopher Faulet4e366822021-01-12 18:57:38 +01001909 if (env_err) {
1910 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
1911 exit(1);
1912 }
1913 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
1914 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02001915
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02001916 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001917 if (global.mode & MODE_MWORKER) {
William Lallemand16dd1b32018-11-19 18:46:18 +01001918 struct mworker_proc *tmproc;
1919
William Lallemand482f9a92019-04-12 16:15:00 +02001920 setenv("HAPROXY_MWORKER", "1", 1);
1921
William Lallemand16dd1b32018-11-19 18:46:18 +01001922 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
1923
William Lallemandf3a86832019-04-01 11:29:58 +02001924 tmproc = calloc(1, sizeof(*tmproc));
William Lallemand16dd1b32018-11-19 18:46:18 +01001925 if (!tmproc) {
1926 ha_alert("Cannot allocate process structures.\n");
1927 exit(EXIT_FAILURE);
1928 }
William Lallemand8f7069a2019-04-12 16:09:23 +02001929 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01001930 tmproc->reloads = 0;
William Lallemand16dd1b32018-11-19 18:46:18 +01001931 tmproc->pid = pid;
1932 tmproc->timestamp = start_date.tv_sec;
1933 tmproc->ipc_fd[0] = -1;
1934 tmproc->ipc_fd[1] = -1;
1935
1936 proc_self = tmproc;
1937
Willy Tarreau2b718102021-04-21 07:32:39 +02001938 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01001939 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001940
Willy Tarreau6185a032021-06-15 08:02:06 +02001941 tmproc = calloc(1, sizeof(*tmproc));
1942 if (!tmproc) {
1943 ha_alert("Cannot allocate process structures.\n");
1944 exit(EXIT_FAILURE);
1945 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001946
Willy Tarreau6185a032021-06-15 08:02:06 +02001947 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
1948 tmproc->pid = -1;
1949 tmproc->reloads = 0;
1950 tmproc->timestamp = -1;
Willy Tarreau6185a032021-06-15 08:02:06 +02001951 tmproc->ipc_fd[0] = -1;
1952 tmproc->ipc_fd[1] = -1;
William Lallemandce83b4a2018-10-26 14:47:30 +02001953
Willy Tarreau6185a032021-06-15 08:02:06 +02001954 if (mworker_cli_sockpair_new(tmproc, 0) < 0) {
1955 exit(EXIT_FAILURE);
William Lallemandce83b4a2018-10-26 14:47:30 +02001956 }
Willy Tarreau6185a032021-06-15 08:02:06 +02001957
1958 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand944e6192018-11-21 15:48:31 +01001959 }
1960 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
1961 struct wordlist *it, *c;
1962
Remi Tricot-Le Breton1f4fa902021-05-19 10:45:12 +02001963 /* get the info of the children in the env */
1964 if (mworker_env_to_proc_list() < 0) {
1965 exit(EXIT_FAILURE);
1966 }
William Lallemande7361152018-10-26 14:47:36 +02001967
William Lallemand550db6d2018-11-06 17:37:12 +01001968 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02001969
William Lallemand550db6d2018-11-06 17:37:12 +01001970 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02001971 ha_alert("Can't create the master's CLI.\n");
1972 exit(EXIT_FAILURE);
1973 }
William Lallemande7361152018-10-26 14:47:36 +02001974
William Lallemand550db6d2018-11-06 17:37:12 +01001975 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
1976
1977 if (mworker_cli_proxy_new_listener(c->s) < 0) {
1978 ha_alert("Can't create the master's CLI.\n");
1979 exit(EXIT_FAILURE);
1980 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001981 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01001982 free(c->s);
1983 free(c);
1984 }
1985 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001986 }
1987
Eric Salama5ba83352021-03-16 15:11:17 +01001988 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
1989 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
1990 }
1991
Willy Tarreaue90904d2021-02-12 14:08:31 +01001992 /* defaults sections are not needed anymore */
1993 proxy_destroy_all_defaults();
1994
Willy Tarreaubb925012009-07-23 13:36:36 +02001995 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02001996 for (px = proxies_list; px; px = px->next) {
1997 struct server *srv;
1998 struct post_proxy_check_fct *ppcf;
1999 struct post_server_check_fct *pscf;
2000
Christopher Fauletd5bd8242020-11-02 16:20:13 +01002001 if (px->disabled)
2002 continue;
2003
Christopher Fauletc1692962019-08-12 09:51:07 +02002004 list_for_each_entry(pscf, &post_server_check_list, list) {
2005 for (srv = px->srv; srv; srv = srv->next)
2006 err_code |= pscf->fct(srv);
2007 }
2008 list_for_each_entry(ppcf, &post_proxy_check_list, list)
2009 err_code |= ppcf->fct(px);
2010 }
Willy Tarreaubb925012009-07-23 13:36:36 +02002011 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002012 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02002013 exit(1);
2014 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002015
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01002016 err_code |= pattern_finalize_config();
2017 if (err_code & (ERR_ABORT|ERR_FATAL)) {
2018 ha_alert("Failed to finalize pattern config.\n");
2019 exit(1);
2020 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002021
Willy Tarreau79c9bdf2021-07-17 12:31:08 +02002022 if (global.rlimit_memmax_all)
2023 global.rlimit_memmax = global.rlimit_memmax_all;
2024
Willy Tarreaue5733232019-05-22 19:24:06 +02002025#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002026 err_code |= netns_init();
2027 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002028 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002029 exit(1);
2030 }
2031#endif
2032
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002033 /* Apply server states */
2034 apply_server_state();
2035
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002036 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002037 srv_compute_all_admin_states(px);
2038
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002039 /* Apply servers' configured address */
2040 err_code |= srv_init_addr();
2041 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002042 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002043 exit(1);
2044 }
2045
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002046 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2047 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2048 exit(1);
2049 }
2050
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002052 struct peers *pr;
2053 struct proxy *px;
2054
Willy Tarreaubebd2122020-04-15 16:06:11 +02002055 if (warned & WARN_ANY)
2056 qfprintf(stdout, "Warnings were found.\n");
2057
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002058 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002059 if (pr->peers_fe)
2060 break;
2061
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002062 for (px = proxies_list; px; px = px->next)
Willy Tarreauc3914d42020-09-24 08:39:22 +02002063 if (!px->disabled && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002064 break;
2065
Emeric Brunbc5c8212021-08-13 09:32:50 +02002066 if (!px) {
2067 /* We may only have log-forward section */
2068 for (px = cfg_log_forward; px; px = px->next)
2069 if (!px->disabled && px->li_all)
2070 break;
2071 }
2072
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002073 if (pr || px) {
2074 /* At least one peer or one listener has been found */
2075 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002076 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002077 }
2078 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2079 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002080 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002081
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002082 if (global.mode & MODE_DIAG) {
2083 cfg_run_diagnostics();
2084 }
2085
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002086 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002087 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002088
Willy Tarreaue6945732016-12-21 19:57:00 +01002089 list_for_each_entry(pcf, &post_check_list, list) {
2090 err_code |= pcf->fct();
2091 if (err_code & (ERR_ABORT|ERR_FATAL))
2092 exit(1);
2093 }
2094
Willy Tarreaubaaee002006-06-26 02:48:02 +02002095 if (cfg_maxconn > 0)
2096 global.maxconn = cfg_maxconn;
2097
Willy Tarreau4975d142021-03-13 11:00:33 +01002098 if (global.cli_fe)
2099 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002100
2101 if (cfg_peers) {
2102 /* peers also need to bypass global maxconn */
2103 struct peers *p = cfg_peers;
2104
2105 for (p = cfg_peers; p; p = p->next)
2106 if (p->peers_fe)
2107 global.maxsock += p->peers_fe->maxconn;
2108 }
2109
Willy Tarreaubaaee002006-06-26 02:48:02 +02002110 if (cfg_pidfile) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002111 free(global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002112 global.pidfile = strdup(cfg_pidfile);
2113 }
2114
Willy Tarreaud0256482015-01-15 21:45:22 +01002115 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002116 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2117 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2118 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2119 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002120 *
2121 * If memmax is set, then it depends on which values are set. If
2122 * maxsslconn is set, we use memmax to determine how many cleartext
2123 * connections may be added, and set maxconn to the sum of the two.
2124 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2125 * the remaining amount of memory between memmax and the cleartext
2126 * connections. If neither are set, then it is considered that all
2127 * connections are SSL-capable, and maxconn is computed based on this,
2128 * then maxsslconn accordingly. We need to know if SSL is used on the
2129 * frontends, backends, or both, because when it's used on both sides,
2130 * we need twice the value for maxsslconn, but we only count the
2131 * handshake once since it is not performed on the two sides at the
2132 * same time (frontend-side is terminated before backend-side begins).
2133 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002134 * ssl_handshake_cost during its initialization. In any case, if
2135 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2136 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002137 */
Willy Tarreauac350932019-03-01 15:43:14 +01002138 ideal_maxconn = compute_ideal_maxconn();
2139
Willy Tarreaud0256482015-01-15 21:45:22 +01002140 if (!global.rlimit_memmax) {
2141 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002142 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002143 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2144 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2145 }
2146 }
2147#ifdef USE_OPENSSL
2148 else if (!global.maxconn && !global.maxsslconn &&
2149 (global.ssl_used_frontend || global.ssl_used_backend)) {
2150 /* memmax is set, compute everything automatically. Here we want
2151 * to ensure that all SSL connections will be served. We take
2152 * care of the number of sides where SSL is used, and consider
2153 * the worst case : SSL used on both sides and doing a handshake
2154 * simultaneously. Note that we can't have more than maxconn
2155 * handshakes at a time by definition, so for the worst case of
2156 * two SSL conns per connection, we count a single handshake.
2157 */
2158 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2159 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002160 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002161
2162 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2163 mem -= global.maxzlibmem;
2164 mem = mem * MEM_USABLE_RATIO;
2165
Willy Tarreau304e17e2020-03-10 17:54:54 +01002166 /* Principle: we test once to set maxconn according to the free
2167 * memory. If it results in values the system rejects, we try a
2168 * second time by respecting rlim_fd_max. If it fails again, we
2169 * go back to the initial value and will let the final code
2170 * dealing with rlimit report the error. That's up to 3 attempts.
2171 */
2172 do {
2173 global.maxconn = mem /
2174 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2175 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2176 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002177
Willy Tarreau304e17e2020-03-10 17:54:54 +01002178 if (retried == 1)
2179 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2180 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002181#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002182 if (global.maxconn > SYSTEM_MAXCONN)
2183 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002184#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002185 global.maxsslconn = sides * global.maxconn;
2186
2187 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2188 break;
2189 } while (retried++ < 2);
2190
Willy Tarreaud0256482015-01-15 21:45:22 +01002191 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2192 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2193 global.maxconn, global.maxsslconn);
2194 }
2195 else if (!global.maxsslconn &&
2196 (global.ssl_used_frontend || global.ssl_used_backend)) {
2197 /* memmax and maxconn are known, compute maxsslconn automatically.
2198 * maxsslconn being forced, we don't know how many of it will be
2199 * on each side if both sides are being used. The worst case is
2200 * when all connections use only one SSL instance because
2201 * handshakes may be on two sides at the same time.
2202 */
2203 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2204 int64_t mem = global.rlimit_memmax * 1048576ULL;
2205 int64_t sslmem;
2206
2207 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2208 mem -= global.maxzlibmem;
2209 mem = mem * MEM_USABLE_RATIO;
2210
Willy Tarreau87b09662015-04-03 00:22:06 +02002211 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002212 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2213 global.maxsslconn = round_2dig(global.maxsslconn);
2214
2215 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002216 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2217 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2218 "without SSL is %d, but %d was found and SSL is in use.\n",
2219 global.rlimit_memmax,
2220 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2221 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002222 exit(1);
2223 }
2224
2225 if (global.maxsslconn > sides * global.maxconn)
2226 global.maxsslconn = sides * global.maxconn;
2227
2228 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2229 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2230 }
2231#endif
2232 else if (!global.maxconn) {
2233 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2234 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2235 int64_t mem = global.rlimit_memmax * 1048576ULL;
2236 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002237 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002238
2239 if (global.ssl_used_frontend || global.ssl_used_backend)
2240 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2241
2242 mem -= global.maxzlibmem;
2243 mem = mem * MEM_USABLE_RATIO;
2244
2245 clearmem = mem;
2246 if (sides)
2247 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2248
Willy Tarreau304e17e2020-03-10 17:54:54 +01002249 /* Principle: we test once to set maxconn according to the free
2250 * memory. If it results in values the system rejects, we try a
2251 * second time by respecting rlim_fd_max. If it fails again, we
2252 * go back to the initial value and will let the final code
2253 * dealing with rlimit report the error. That's up to 3 attempts.
2254 */
2255 do {
2256 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2257 if (retried == 1)
2258 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2259 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002260#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002261 if (global.maxconn > SYSTEM_MAXCONN)
2262 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002263#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002264
Willy Tarreau304e17e2020-03-10 17:54:54 +01002265 if (clearmem <= 0 || !global.maxconn) {
2266 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2267 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2268 "is %d, but %d was found.\n",
2269 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002270 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002271 global.maxsslconn);
2272 exit(1);
2273 }
2274
2275 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2276 break;
2277 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002278
2279 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2280 if (sides && global.maxsslconn > sides * global.maxconn) {
2281 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2282 "to be limited to %d. Better reduce global.maxsslconn to get more "
2283 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2284 }
2285 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2286 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002287 }
2288
Willy Tarreaua409f302020-03-10 17:08:53 +01002289 global.maxsock = compute_ideal_maxsock(global.maxconn);
2290 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002291 if (!global.maxpipes)
2292 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002293
Olivier Houchard88698d92019-04-16 19:07:22 +02002294 /* update connection pool thresholds */
2295 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2296 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2297
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002298 proxy_adjust_all_maxconn();
2299
Willy Tarreau1db37712007-06-03 17:16:49 +02002300 if (global.tune.maxpollevents <= 0)
2301 global.tune.maxpollevents = MAX_POLL_EVENTS;
2302
Willy Tarreau060a7612021-03-10 11:06:26 +01002303 if (global.tune.runqueue_depth <= 0) {
2304 /* tests on various thread counts from 1 to 64 have shown an
2305 * optimal queue depth following roughly 1/sqrt(threads).
2306 */
2307 int s = my_flsl(global.nbthread);
2308 s += (global.nbthread / s); // roughly twice the sqrt.
2309 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2310 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002311
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002312 if (global.tune.recv_enough == 0)
2313 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2314
Willy Tarreau27a674e2009-08-17 07:23:33 +02002315 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2316 global.tune.maxrewrite = global.tune.bufsize / 2;
2317
Amaury Denoyelle11124302021-06-04 18:22:08 +02002318 usermsgs_clr(NULL);
2319
Willy Tarreaubaaee002006-06-26 02:48:02 +02002320 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2321 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002322 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002323 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2324 }
2325
William Lallemand095ba4c2017-06-01 17:38:50 +02002326 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002327 /* command line daemon mode inhibits foreground and debug modes mode */
2328 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002329 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002330 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002331
2332 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002333
William Lallemand095ba4c2017-06-01 17:38:50 +02002334 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002335 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002336 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002337 }
2338
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002339 if (global.nbthread < 1)
2340 global.nbthread = 1;
2341
Christopher Faulet3ef26392017-08-29 16:46:57 +02002342 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002343 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002344 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002345 exit(1);
2346 }
2347
Christopher Faulet96d44832017-11-14 22:02:30 +01002348 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002349 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002350 exit(1);
2351 }
2352
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002353 /*
2354 * Note: we could register external pollers here.
2355 * Built-in pollers have been registered before main().
2356 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002357
Willy Tarreau43b78992009-01-25 15:42:27 +01002358 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002359 disable_poller("kqueue");
2360
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002361 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2362 disable_poller("evports");
2363
Willy Tarreau43b78992009-01-25 15:42:27 +01002364 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002365 disable_poller("epoll");
2366
Willy Tarreau43b78992009-01-25 15:42:27 +01002367 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002368 disable_poller("poll");
2369
Willy Tarreau43b78992009-01-25 15:42:27 +01002370 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002371 disable_poller("select");
2372
2373 /* Note: we could disable any poller by name here */
2374
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002375 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002376 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002377 fprintf(stderr, "\n");
2378 list_filters(stderr);
2379 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002380
Willy Tarreau4f60f162007-04-08 16:39:58 +02002381 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002382 ha_alert("No polling mechanism available.\n"
2383 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2384 " is too low on this platform to support maxconn and the number of listeners\n"
2385 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2386 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2387 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2388 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2389 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2390 " check build settings using 'haproxy -vv'.\n\n",
2391 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002392 exit(1);
2393 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002394 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2395 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002396 }
2397
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002398 if (!global.node)
2399 global.node = strdup(hostname);
2400
Willy Tarreau02b092f2020-10-07 18:36:54 +02002401 /* stop disabled proxies */
2402 for (px = proxies_list; px; px = px->next) {
Willy Tarreauc3914d42020-09-24 08:39:22 +02002403 if (px->disabled)
Willy Tarreau02b092f2020-10-07 18:36:54 +02002404 stop_proxy(px);
2405 }
2406
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002407 if (!hlua_post_init())
2408 exit(1);
Thomas Holmes6abded42015-05-12 16:23:58 +01002409
Maxime de Roucy0f503922016-05-13 23:52:55 +02002410 free(err_msg);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002411}
2412
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002413void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002414{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002415 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002416 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002417 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002418 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002419 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002420 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002421 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002422 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002423 struct per_thread_init_fct *tif, *tifb;
2424 struct per_thread_deinit_fct *tdf, *tdfb;
2425 struct per_thread_alloc_fct *taf, *tafb;
2426 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002427 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002428 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002429 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002430 int cur_fd;
2431
2432 /* At this point the listeners state is weird:
2433 * - most listeners are still bound and referenced in their protocol
2434 * - some might be zombies that are not in their proto anymore, but
2435 * still appear in their proxy's listeners with a valid FD.
2436 * - some might be stopped and still appear in their proxy as FD #-1
2437 * - among all of them, some might be inherited hence shared and we're
2438 * not allowed to pause them or whatever, we must just close them.
2439 * - finally some are not listeners (pipes, logs, stdout, etc) and
2440 * must be left intact.
2441 *
2442 * The safe way to proceed is to unbind (and close) whatever is not yet
2443 * unbound so that no more receiver/listener remains alive. Then close
2444 * remaining listener FDs, which correspond to zombie listeners (those
2445 * belonging to disabled proxies that were in another process).
2446 * objt_listener() would be cleaner here but not converted yet.
2447 */
2448 protocol_unbind_all();
2449
2450 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002451 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002452 continue;
2453
Willy Tarreaua74cb382020-10-15 21:29:49 +02002454 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002455 struct listener *l = fdtab[cur_fd].owner;
2456
2457 BUG_ON(l->state != LI_INIT);
2458 unbind_listener(l);
2459 }
2460 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002461
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002462 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002464 /* build a list of unique uri_auths */
2465 if (!ua)
2466 ua = p->uri_auth;
2467 else {
2468 /* check if p->uri_auth is unique */
2469 for (uap = ua; uap; uap=uap->next)
2470 if (uap == p->uri_auth)
2471 break;
2472
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002473 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002474 /* add it, if it is */
2475 p->uri_auth->next = ua;
2476 ua = p->uri_auth;
2477 }
William Lallemand0f99e342011-10-12 17:50:54 +02002478 }
2479
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002480 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002481 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002482 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002484
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002485 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002486 struct stat_scope *scope, *scopep;
2487
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002488 uap = ua;
2489 ua = ua->next;
2490
Willy Tarreaua534fea2008-08-03 12:19:50 +02002491 free(uap->uri_prefix);
2492 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002493 free(uap->node);
2494 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002495
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002496 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002497 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002498
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002499 scope = uap->scope;
2500 while (scope) {
2501 scopep = scope;
2502 scope = scope->next;
2503
2504 free(scopep->px_id);
2505 free(scopep);
2506 }
2507
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002508 free(uap);
2509 }
2510
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002511 userlist_free(userlist);
2512
David Carlier834cb2e2015-09-25 12:02:25 +01002513 cfg_unregister_sections();
2514
Christopher Faulet0132d062017-07-26 15:33:35 +02002515 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002516
Willy Tarreau05554e62016-12-21 20:46:26 +01002517 list_for_each_entry(pdf, &post_deinit_list, list)
2518 pdf->fct();
2519
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002520 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002521 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002522 ha_free(&global.chroot);
2523 ha_free(&global.pidfile);
2524 ha_free(&global.node);
2525 ha_free(&global.desc);
2526 ha_free(&oldpids);
2527 ha_free(&old_argv);
2528 ha_free(&localpeer);
2529 ha_free(&global.server_state_base);
2530 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002531 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002532 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002533
William Lallemand0f99e342011-10-12 17:50:54 +02002534 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002535 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002536 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002537 free(log);
2538 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002539 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002540 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002541 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002542 free(wl);
2543 }
2544
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002545 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2546 if (bol->must_free)
2547 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002548 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002549 free(bol);
2550 }
2551
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002552 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002553 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002554 free(pxdf);
2555 }
2556
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002557 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002558 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002559 free(pdf);
2560 }
2561
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002562 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002563 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002564 free(srvdf);
2565 }
2566
Tim Duesterhusfc854942020-09-10 19:46:42 +02002567 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002568 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002569 free(pcf);
2570 }
2571
Tim Duesterhus34bef072020-07-04 11:49:50 +02002572 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002573 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002574 free(pscf);
2575 }
2576
Tim Duesterhus53508d62020-09-10 19:46:40 +02002577 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002578 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002579 free(ppcf);
2580 }
2581
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002582 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002583 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002584 free(tif);
2585 }
2586
2587 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002588 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002589 free(tdf);
2590 }
2591
2592 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002593 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002594 free(taf);
2595 }
2596
2597 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002598 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002599 free(tff);
2600 }
2601
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002602 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002603 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002604 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002605} /* end deinit() */
2606
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002607__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002608{
Amaury Denoyelle7afa5c12021-08-09 15:02:56 +02002609 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002610 deinit();
2611 exit(status);
2612}
William Lallemand72160322018-11-06 17:37:16 +01002613
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002614/* Handler of the task of mux_stopping_data.
2615 * Called on soft-stop.
2616 */
2617struct task *mux_stopping_process(struct task *t, void *ctx, unsigned int state)
2618{
2619 struct connection *conn, *back;
2620
2621 list_for_each_entry_safe(conn, back, &mux_stopping_data[tid].list, stopping_list) {
2622 if (conn->mux && conn->mux->wake)
2623 conn->mux->wake(conn);
2624 }
2625
2626 return t;
2627}
2628
Willy Tarreau918ff602011-07-25 16:33:49 +02002629/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002630void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002631{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002632 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002633
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002634 /* allocates the thread bound mux_stopping_data task */
2635 mux_stopping_data[tid].task = task_new(tid_bit);
2636 mux_stopping_data[tid].task->process = mux_stopping_process;
2637 LIST_INIT(&mux_stopping_data[tid].list);
2638
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002639 tv_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002640 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002641 wake_expired_tasks();
2642
William Lallemand1aab50b2018-06-07 09:46:01 +02002643 /* check if we caught some signals and process them in the
2644 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002645 if (signal_queue_len && tid == 0) {
2646 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002647 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002648 }
2649
2650 /* Process a few tasks */
2651 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002652
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002653 /* also stop if we failed to cleanly stop all tasks */
2654 if (killed > 1)
2655 break;
2656
Willy Tarreau10146c92015-04-13 20:44:19 +02002657 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002658 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002659 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002660 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002661 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002662 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2663 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002664 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002665 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002666 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002667 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002668 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002669 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002670
Willy Tarreau4f46a352020-03-23 09:27:28 +01002671 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002672 int i;
2673
2674 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002675 /* stop muxes before acknowledging stopping */
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002676 if (!(stopping_thread_mask & tid_bit)) {
2677 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2678 wake = 1;
2679 }
2680
Willy Tarreau1db42732021-04-06 11:44:07 +02002681 if (_HA_ATOMIC_OR_FETCH(&stopping_thread_mask, tid_bit) == tid_bit) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002682 /* notify all threads that stopping was just set */
2683 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002684 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002685 wake_thread(i);
2686 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002687 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002688
2689 /* stop when there's nothing left to do */
2690 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002691 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2692 /* wake all threads waiting on jobs==0 */
2693 for (i = 0; i < global.nbthread; i++)
2694 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2695 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002696 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002697 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002698 }
2699
Willy Tarreauc49ba522019-12-11 08:12:23 +01002700 /* If we have to sleep, measure how long */
2701 next = wake ? TICK_ETERNITY : next_timer_expiry();
2702
Willy Tarreau58b458d2008-06-29 22:40:23 +02002703 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002704 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002705
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002706 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002707 }
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002708
2709 task_destroy(mux_stopping_data[tid].task);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002710}
2711
Christopher Faulet1d17c102017-08-29 15:38:48 +02002712static void *run_thread_poll_loop(void *data)
2713{
Willy Tarreau082b6282019-05-22 14:42:12 +02002714 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002715 struct per_thread_init_fct *ptif;
2716 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002717 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002718 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002719 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2720 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002721
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02002722 ha_set_tid((unsigned long)data);
Willy Tarreaud022e9c2019-09-24 08:25:15 +02002723 sched = &task_per_thread[tid];
Willy Tarreau91e6df02019-05-03 17:21:18 +02002724
Willy Tarreauf6178242019-05-21 19:46:58 +02002725#if (_POSIX_TIMERS > 0) && defined(_POSIX_THREAD_CPUTIME)
Willy Tarreau91e6df02019-05-03 17:21:18 +02002726#ifdef USE_THREAD
Willy Tarreau8323a372019-05-20 18:57:53 +02002727 pthread_getcpuclockid(pthread_self(), &ti->clock_id);
Willy Tarreau624dcbf2019-05-20 20:23:06 +02002728#else
Willy Tarreau8323a372019-05-20 18:57:53 +02002729 ti->clock_id = CLOCK_THREAD_CPUTIME_ID;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002730#endif
Willy Tarreau663fda42019-05-21 15:14:08 +02002731#endif
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002732 /* Now, initialize one thread init at a time. This is better since
2733 * some init code is a bit tricky and may release global resources
2734 * after reallocating them locally. This will also ensure there is
2735 * no race on file descriptors allocation.
2736 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002737#ifdef USE_THREAD
2738 pthread_mutex_lock(&init_mutex);
2739#endif
2740 /* The first thread must set the number of threads left */
2741 if (!init_left)
2742 init_left = global.nbthread;
2743 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002744
Willy Tarreauc4c80fb2021-04-11 15:00:34 +02002745 tv_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002746
Willy Tarreau082b6282019-05-22 14:42:12 +02002747 /* per-thread alloc calls performed here are not allowed to snoop on
2748 * other threads, so they are free to initialize at their own rhythm
2749 * as long as they act as if they were alone. None of them may rely
2750 * on resources initialized by the other ones.
2751 */
2752 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2753 if (!ptaf->fct()) {
2754 ha_alert("failed to allocate resources for thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002755#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002756 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002757#endif
Willy Tarreau082b6282019-05-22 14:42:12 +02002758 exit(1);
2759 }
2760 }
2761
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002762 /* per-thread init calls performed here are not allowed to snoop on
2763 * other threads, so they are free to initialize at their own rhythm
2764 * as long as they act as if they were alone.
2765 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002766 list_for_each_entry(ptif, &per_thread_init_list, list) {
2767 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002768 ha_alert("failed to initialize thread %u.\n", tid);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002769#ifdef USE_THREAD
jenny-cheung048368e2021-07-18 16:40:57 +08002770 pthread_mutex_unlock(&init_mutex);
Willy Tarreaub3c4a8f2021-07-22 14:42:32 +02002771#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002772 exit(1);
2773 }
2774 }
2775
Willy Tarreau71092822019-06-10 09:51:04 +02002776 /* enabling protocols will result in fd_insert() calls to be performed,
2777 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002778 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002779 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002780 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002781 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002782
Willy Tarreau34a150c2019-06-11 09:16:41 +02002783#ifdef USE_THREAD
2784 pthread_cond_broadcast(&init_cond);
2785 pthread_mutex_unlock(&init_mutex);
2786
2787 /* now wait for other threads to finish starting */
2788 pthread_mutex_lock(&init_mutex);
2789 while (init_left)
2790 pthread_cond_wait(&init_cond, &init_mutex);
2791 pthread_mutex_unlock(&init_mutex);
2792#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002793
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002794#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2795 /* Let's refrain from using setuid executables. This way the impact of
2796 * an eventual vulnerability in a library remains limited. It may
2797 * impact external checks but who cares about them anyway ? In the
2798 * worst case it's possible to disable the option. Obviously we do this
2799 * in workers only. We can't hard-fail on this one as it really is
2800 * implementation dependent though we're interested in feedback, hence
2801 * the warning.
2802 */
2803 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2804 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002805 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 +01002806 ha_warning("Failed to disable setuid, please report to developers with detailed "
2807 "information about your operating system. You can silence this warning "
2808 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2809 }
2810 }
2811#endif
2812
Willy Tarreaud96f1122019-12-03 07:07:36 +01002813#if defined(RLIMIT_NPROC)
2814 /* all threads have started, it's now time to prevent any new thread
2815 * or process from starting. Obviously we do this in workers only. We
2816 * can't hard-fail on this one as it really is implementation dependent
2817 * though we're interested in feedback, hence the warning.
2818 */
2819 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2820 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2821 static int warn_fail;
2822
Willy Tarreau18515722021-04-06 11:57:41 +02002823 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002824 ha_warning("Failed to disable forks, please report to developers with detailed "
2825 "information about your operating system. You can silence this warning "
2826 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2827 }
2828 }
2829#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002830 run_poll_loop();
2831
2832 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2833 ptdf->fct();
2834
Willy Tarreau082b6282019-05-22 14:42:12 +02002835 list_for_each_entry(ptff, &per_thread_free_list, list)
2836 ptff->fct();
2837
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002838#ifdef USE_THREAD
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002839 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002840 if (tid > 0)
2841 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002842#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002843 return NULL;
2844}
Christopher Faulet1d17c102017-08-29 15:38:48 +02002845
William Dauchyf9af9d72019-11-17 15:47:16 +01002846/* set uid/gid depending on global settings */
2847static void set_identity(const char *program_name)
2848{
2849 if (global.gid) {
2850 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
2851 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
2852 " without 'uid'/'user' is generally useless.\n", program_name);
2853
2854 if (setgid(global.gid) == -1) {
2855 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
2856 protocol_unbind_all();
2857 exit(1);
2858 }
2859 }
2860
2861 if (global.uid && setuid(global.uid) == -1) {
2862 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
2863 protocol_unbind_all();
2864 exit(1);
2865 }
2866}
2867
Willy Tarreaubaaee002006-06-26 02:48:02 +02002868int main(int argc, char **argv)
2869{
2870 int err, retry;
2871 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02002872 int pidfd = -1;
Willy Tarreau1335da32021-07-14 17:54:01 +02002873 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
2874
2875 /* Catch forced CFLAGS that miss 2-complement integer overflow */
2876 if (intovf + 0x7FFFFFFF >= intovf) {
2877 fprintf(stderr,
2878 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
2879 "The source code was miscompiled by the compiler, which usually indicates that\n"
2880 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
2881 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
2882 "and INSTALL files to decide on the best way to pass your local build options.\n"
2883 "\nBuild options :"
2884#ifdef BUILD_TARGET
2885 "\n TARGET = " BUILD_TARGET
2886#endif
2887#ifdef BUILD_CPU
2888 "\n CPU = " BUILD_CPU
2889#endif
2890#ifdef BUILD_CC
2891 "\n CC = " BUILD_CC
2892#endif
2893#ifdef BUILD_CFLAGS
2894 "\n CFLAGS = " BUILD_CFLAGS
2895#endif
2896#ifdef BUILD_OPTIONS
2897 "\n OPTIONS = " BUILD_OPTIONS
2898#endif
2899#ifdef BUILD_DEBUG
2900 "\n DEBUG = " BUILD_DEBUG
2901#endif
2902 "\n\n");
2903 return 1;
2904 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002905
Olivier Houchard5fa300d2018-02-03 15:15:21 +01002906 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01002907
Willy Tarreaubf696402019-03-01 10:09:28 +01002908 /* take a copy of initial limits before we possibly change them */
2909 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02002910
2911 if (limit.rlim_max == RLIM_INFINITY)
2912 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01002913 rlim_fd_cur_at_boot = limit.rlim_cur;
2914 rlim_fd_max_at_boot = limit.rlim_max;
2915
Willy Tarreau5794fb02018-11-25 18:43:29 +01002916 /* process all initcalls in order of potential dependency */
2917 RUN_INITCALLS(STG_PREPARE);
2918 RUN_INITCALLS(STG_LOCK);
2919 RUN_INITCALLS(STG_ALLOC);
2920 RUN_INITCALLS(STG_POOL);
2921 RUN_INITCALLS(STG_REGISTER);
2922 RUN_INITCALLS(STG_INIT);
2923
Emeric Bruncf20bf12010-10-22 16:06:11 +02002924 init(argc, argv);
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002925 signal_register_fct(SIGQUIT, dump, SIGQUIT);
2926 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
2927 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02002928 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002929
Willy Tarreaue437c442010-03-17 18:02:46 +01002930 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
2931 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
2932 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002933 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002934 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002935
Willy Tarreaudc23a922011-02-16 11:10:36 +01002936 /* ulimits */
2937 if (!global.rlimit_nofile)
2938 global.rlimit_nofile = global.maxsock;
2939
2940 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01002941 limit.rlim_cur = global.rlimit_nofile;
2942 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
2943
Willy Tarreaudc23a922011-02-16 11:10:36 +01002944 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02002945 getrlimit(RLIMIT_NOFILE, &limit);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002946 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2947 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
2948 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002949 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002950 }
2951 else {
2952 /* try to set it to the max possible at least */
2953 limit.rlim_cur = limit.rlim_max;
2954 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
2955 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02002956
William Dauchya5194602020-03-28 19:29:58 +01002957 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002958 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
2959 global.rlimit_nofile = limit.rlim_cur;
2960 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01002961 }
2962 }
2963
2964 if (global.rlimit_memmax) {
2965 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01002966 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01002967#ifdef RLIMIT_AS
2968 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002969 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2970 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2971 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002972 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002973 }
2974 else
William Dauchya5194602020-03-28 19:29:58 +01002975 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002976 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002977 }
2978#else
2979 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002980 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2981 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2982 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002983 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002984 }
2985 else
William Dauchya5194602020-03-28 19:29:58 +01002986 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002987 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002988 }
2989#endif
2990 }
2991
Olivier Houchardf73629d2017-04-05 22:33:04 +02002992 if (old_unixsocket) {
William Lallemand85b0bd92017-06-01 17:38:53 +02002993 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02002994 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002995 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02002996 if (!(global.mode & MODE_MWORKER))
2997 exit(1);
2998 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02002999 }
3000 }
William Lallemand85b0bd92017-06-01 17:38:53 +02003001 get_cur_unixsocket();
3002
Willy Tarreaubaaee002006-06-26 02:48:02 +02003003 /* We will loop at most 100 times with 10 ms delay each time.
3004 * That's at most 1 second. We only send a signal to old pids
3005 * if we cannot grab at least one port.
3006 */
3007 retry = MAX_START_RETRIES;
3008 err = ERR_NONE;
3009 while (retry >= 0) {
3010 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003011 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003012 /* exit the loop on no error or fatal error */
3013 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003015 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003016 break;
3017
3018 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3019 * listening sockets. So on those platforms, it would be wiser to
3020 * simply send SIGUSR1, which will not be undoable.
3021 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003022 if (tell_old_pids(SIGTTOU) == 0) {
3023 /* no need to wait if we can't contact old pids */
3024 retry = 0;
3025 continue;
3026 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003027 /* give some time to old processes to stop listening */
3028 w.tv_sec = 0;
3029 w.tv_usec = 10*1000;
3030 select(0, NULL, NULL, NULL, &w);
3031 retry--;
3032 }
3033
Willy Tarreaue91bff22020-09-02 11:11:43 +02003034 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003035 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003036 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003037 if (retry != MAX_START_RETRIES && nb_oldpids) {
3038 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003039 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003040 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 exit(1);
3042 }
3043
William Lallemand944e6192018-11-21 15:48:31 +01003044 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003045 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 /* Note: we don't have to send anything to the old pids because we
3047 * never stopped them. */
3048 exit(1);
3049 }
3050
Willy Tarreaue91bff22020-09-02 11:11:43 +02003051 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003052 * the previous process gave us, we don't need them anymore
3053 */
3054 while (xfer_sock_list != NULL) {
3055 struct xfer_sock_list *tmpxfer = xfer_sock_list->next;
3056 close(xfer_sock_list->fd);
3057 free(xfer_sock_list->iface);
3058 free(xfer_sock_list->namespace);
3059 free(xfer_sock_list);
3060 xfer_sock_list = tmpxfer;
3061 }
Willy Tarreaudd815982007-10-16 12:25:14 +02003062
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003064 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3065 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066
Willy Tarreaubaaee002006-06-26 02:48:02 +02003067 /* MODE_QUIET can inhibit alerts and warnings below this line */
3068
PiBa-NL149a81a2017-12-25 21:03:31 +01003069 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3070 /* either stdin/out/err are already closed or should stay as they are. */
3071 if ((global.mode & MODE_DAEMON)) {
3072 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3073 global.mode &= ~MODE_VERBOSE;
3074 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3075 }
3076 } else {
3077 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3078 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003079 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003080 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003081 }
3082
3083 /* open log & pid files before the chroot */
William Lallemand80293002017-11-06 11:00:03 +01003084 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003085 unlink(global.pidfile);
3086 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3087 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003088 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089 if (nb_oldpids)
3090 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003091 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003092 exit(1);
3093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 }
3095
Willy Tarreaub38651a2007-03-24 17:24:39 +01003096 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003097 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3098 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003099 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003100 exit(1);
3101 }
3102
Jackie Tapia749f74c2020-07-22 18:59:40 -05003103 /* If the user is not root, we'll still let them try the configuration
3104 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003105 */
3106 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003107 ha_warning("[%s.main()] Some options which require full privileges"
3108 " might not work well.\n"
3109 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003110
William Lallemand095ba4c2017-06-01 17:38:50 +02003111 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3112
3113 /* chroot if needed */
3114 if (global.chroot != NULL) {
3115 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003116 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003117 if (nb_oldpids)
3118 tell_old_pids(SIGTTIN);
3119 protocol_unbind_all();
3120 exit(1);
3121 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003122 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003123 }
3124
William Lallemand944e6192018-11-21 15:48:31 +01003125 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003126 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127
William Lallemand27edc4b2019-05-07 17:49:33 +02003128 /* send a SIGTERM to workers who have a too high reloads number */
3129 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3130 mworker_kill_max_reloads(SIGTERM);
3131
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 /* Note that any error at this stage will be fatal because we will not
3133 * be able to restart the old pids.
3134 */
3135
William Dauchyf9af9d72019-11-17 15:47:16 +01003136 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3137 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003138
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 /* check ulimits */
3140 limit.rlim_cur = limit.rlim_max = 0;
3141 getrlimit(RLIMIT_NOFILE, &limit);
3142 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003143 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3144 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3145 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3146 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3147 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003148 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003149 }
3150 else
3151 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003152 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003153 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3154 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 }
3156
William Lallemand944e6192018-11-21 15:48:31 +01003157 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 int ret = 0;
Willy Tarreaud67ff342021-06-15 07:58:09 +02003159 int in_parent = 0;
William Lallemande1340412017-12-28 16:09:36 +01003160 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003161
William Lallemand095ba4c2017-06-01 17:38:50 +02003162 /*
3163 * if daemon + mworker: must fork here to let a master
3164 * process live in background before forking children
3165 */
William Lallemand73b85e72017-06-01 17:38:51 +02003166
3167 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3168 && (global.mode & MODE_MWORKER)
3169 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003170 ret = fork();
3171 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003172 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003173 protocol_unbind_all();
3174 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003175 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003176 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003177 } else /* change the process group ID in the child (master process) */
3178 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003179 }
William Lallemande20b6a62017-06-01 17:38:55 +02003180
William Lallemande20b6a62017-06-01 17:38:55 +02003181
William Lallemanddeed7802017-11-06 11:00:04 +01003182 /* if in master-worker mode, write the PID of the father */
3183 if (global.mode & MODE_MWORKER) {
3184 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003185 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003186 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003187 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003188 }
3189
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003191 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003192 if (global.mode & MODE_MWORKER)
3193 mworker_ext_launch_all();
Willy Tarreaud67ff342021-06-15 07:58:09 +02003194
3195 ret = fork();
3196 if (ret < 0) {
3197 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3198 protocol_unbind_all();
3199 exit(1); /* there has been an error */
3200 }
3201 else if (ret == 0) { /* child breaks here */
Willy Tarreau3c032f22021-07-21 10:17:02 +02003202 /* This one must not be exported, it's internal! */
3203 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003204 ha_random_jump96(1);
Willy Tarreaud67ff342021-06-15 07:58:09 +02003205 }
3206 else { /* parent here */
3207 in_parent = 1;
3208
William Lallemand944e6192018-11-21 15:48:31 +01003209 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3210 char pidstr[100];
3211 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003212 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003213 }
3214 if (global.mode & MODE_MWORKER) {
3215 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003216
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003217 ha_notice("New worker #%d (%d) forked\n", 1, ret);
William Lallemand944e6192018-11-21 15:48:31 +01003218 /* find the right mworker_proc */
3219 list_for_each_entry(child, &proc_list, list) {
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003220 if (child->reloads == 0 && child->options & PROC_O_TYPE_WORKER) {
William Lallemand944e6192018-11-21 15:48:31 +01003221 child->timestamp = now.tv_sec;
3222 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003223 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003224 break;
3225 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003226 }
3227 }
William Lallemand944e6192018-11-21 15:48:31 +01003228 }
Willy Tarreaud67ff342021-06-15 07:58:09 +02003229
William Lallemand944e6192018-11-21 15:48:31 +01003230 } else {
3231 /* wait mode */
Willy Tarreaud67ff342021-06-15 07:58:09 +02003232 in_parent = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003233 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003234
3235#ifdef USE_CPU_AFFINITY
Willy Tarreau44ea6312021-06-15 08:57:56 +02003236 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 +02003237
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003238#ifdef __FreeBSD__
Willy Tarreau44ea6312021-06-15 08:57:56 +02003239 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003240 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
David Carlier2d0493a2020-12-02 21:14:51 +00003241#elif defined(__linux__) || defined(__DragonFly__)
Willy Tarreau44ea6312021-06-15 08:57:56 +02003242 struct hap_cpuset *set = &cpu_map.proc;
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003243 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003244#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003245 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003246#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003247 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003248 if (pidfd >= 0) {
3249 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3250 close(pidfd);
3251 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003252
3253 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003254 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003255
Willy Tarreaud67ff342021-06-15 07:58:09 +02003256 if (in_parent) {
William Lallemand944e6192018-11-21 15:48:31 +01003257 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003258
3259 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3260 (global.mode & MODE_DAEMON)) {
3261 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003262 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3263 stdio_quiet(-1);
3264
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003265 global.mode &= ~MODE_VERBOSE;
3266 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003267 }
3268
William Lallemandb3f2be32018-09-11 10:06:18 +02003269 mworker_loop();
William Lallemand1499b9b2017-06-07 15:04:47 +02003270 /* should never get there */
3271 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003272 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003273#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003274 ssl_free_dh();
3275#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003276 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003277 }
3278
William Lallemandcb11fd22017-06-01 17:38:52 +02003279 /* child must never use the atexit function */
3280 atexit_flag = 0;
3281
William Lallemandbc193052018-09-11 10:06:26 +02003282 /* close useless master sockets */
3283 if (global.mode & MODE_MWORKER) {
3284 struct mworker_proc *child, *it;
3285 master = 0;
3286
William Lallemand309dc9a2018-10-26 14:47:45 +02003287 mworker_cli_proxy_stop();
3288
William Lallemandbc193052018-09-11 10:06:26 +02003289 /* free proc struct of other processes */
3290 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003291 /* close the FD of the master side for all
3292 * workers, we don't need to close the worker
3293 * side of other workers since it's done with
3294 * the bind_proc */
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003295 if (child->ipc_fd[0] >= 0)
3296 close(child->ipc_fd[0]);
Willy Tarreaue8422bf2021-06-15 09:08:18 +02003297 if (child->options & PROC_O_TYPE_WORKER &&
William Lallemandce83b4a2018-10-26 14:47:30 +02003298 child->reloads == 0) {
3299 /* keep this struct if this is our pid */
3300 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003301 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003302 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003303 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003304 mworker_free_child(child);
3305 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003306 }
3307 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003308
William Lallemande1340412017-12-28 16:09:36 +01003309 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3310 devnullfd = open("/dev/null", O_RDWR, 0);
3311 if (devnullfd < 0) {
3312 ha_alert("Cannot open /dev/null\n");
3313 exit(EXIT_FAILURE);
3314 }
3315 }
3316
William Lallemand095ba4c2017-06-01 17:38:50 +02003317 /* Must chroot and setgid/setuid in the children */
3318 /* chroot if needed */
3319 if (global.chroot != NULL) {
3320 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreaue34cf282021-06-15 08:59:19 +02003321 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003322 if (nb_oldpids)
3323 tell_old_pids(SIGTTIN);
3324 protocol_unbind_all();
3325 exit(1);
3326 }
3327 }
3328
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003329 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003330 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003331
William Lallemand7f80eb22017-05-26 18:19:55 +02003332 /* pass through every cli socket, and check if it's bound to
3333 * the current process and if it exposes listeners sockets.
3334 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3335 * */
3336
Willy Tarreau4975d142021-03-13 11:00:33 +01003337 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003338 struct bind_conf *bind_conf;
3339
Willy Tarreau4975d142021-03-13 11:00:33 +01003340 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003341 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreau72faef32021-06-15 08:36:30 +02003342 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3343 break;
William Lallemand7f80eb22017-05-26 18:19:55 +02003344 }
3345 }
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003346 }
3347
William Lallemand2e8fad92018-11-13 16:18:23 +01003348 /*
3349 * This is only done in daemon mode because we might want the
3350 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3351 * we should now close the 3 first FDs to ensure that we can
3352 * detach from the TTY. We MUST NOT do it in other cases since
3353 * it would have already be done, and 0-2 would have been
3354 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003355 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003356 if ((global.mode & MODE_DAEMON) &&
3357 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003359 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003360 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003361 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3362 }
3363 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003364 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3365 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003366 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003367 }
3368
William Dauchye039f262019-11-17 15:47:15 +01003369 /* try our best to re-enable core dumps depending on system capabilities.
3370 * What is addressed here :
3371 * - remove file size limits
3372 * - remove core size limits
3373 * - mark the process dumpable again if it lost it due to user/group
3374 */
3375 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3376 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3377
3378#if defined(RLIMIT_FSIZE)
3379 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3380 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3381 ha_alert("[%s.main()] Failed to set the raise the maximum "
3382 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003383 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003384 }
3385 else
3386 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003387 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003388 }
3389#endif
3390
3391#if defined(RLIMIT_CORE)
3392 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3393 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3394 ha_alert("[%s.main()] Failed to set the raise the core "
3395 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003396 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003397 }
3398 else
3399 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003400 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003401 }
3402#endif
3403
3404#if defined(USE_PRCTL)
3405 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3406 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3407 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com21185972021-08-21 09:13:10 +01003408#elif defined(USE_PROCCTL)
3409 int traceable = PROC_TRACE_CTL_ENABLE;
3410 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3411 ha_warning("[%s.main()] Failed to set the traceable flag, "
3412 "no core will be dumped.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003413#endif
3414 }
3415
Christopher Faulete3a5e352017-10-24 13:53:54 +02003416 global.mode &= ~MODE_STARTING;
Amaury Denoyelle6af81f82021-05-27 15:45:28 +02003417 reset_usermsgs_ctx();
3418
Willy Tarreau4f60f162007-04-08 16:39:58 +02003419 /*
3420 * That's it : the central polling loop. Run until we stop.
3421 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02003422#ifdef USE_THREAD
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003423 {
William Lallemand1aab50b2018-06-07 09:46:01 +02003424 sigset_t blocked_sig, old_sig;
Willy Tarreauc40efc12019-05-03 09:22:44 +02003425 int i;
3426
William Lallemand1aab50b2018-06-07 09:46:01 +02003427 /* ensure the signals will be blocked in every thread */
3428 sigfillset(&blocked_sig);
3429 sigdelset(&blocked_sig, SIGPROF);
3430 sigdelset(&blocked_sig, SIGBUS);
3431 sigdelset(&blocked_sig, SIGFPE);
3432 sigdelset(&blocked_sig, SIGILL);
3433 sigdelset(&blocked_sig, SIGSEGV);
3434 pthread_sigmask(SIG_SETMASK, &blocked_sig, &old_sig);
3435
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003436 /* Create nbthread-1 thread. The first thread is the current process */
David Carliera92c5ce2019-09-13 05:03:12 +01003437 ha_thread_info[0].pthread = pthread_self();
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003438 for (i = 1; i < global.nbthread; i++)
David Carliera92c5ce2019-09-13 05:03:12 +01003439 pthread_create(&ha_thread_info[i].pthread, NULL, &run_thread_poll_loop, (void *)(long)i);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003440
Christopher Faulet62519022017-10-16 15:49:32 +02003441#ifdef USE_CPU_AFFINITY
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003442 /* Now the CPU affinity for all threads */
Amaury Denoyelleaf02c572021-04-15 16:29:58 +02003443
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003444 for (i = 0; i < global.nbthread; i++) {
Willy Tarreau44ea6312021-06-15 08:57:56 +02003445 if (ha_cpuset_count(&cpu_map.proc))
3446 ha_cpuset_and(&cpu_map.thread[i], &cpu_map.proc);
Christopher Faulet62519022017-10-16 15:49:32 +02003447
Willy Tarreau421f02e2018-01-20 18:19:22 +01003448 if (i < MAX_THREADS && /* only the first 32/64 threads may be pinned */
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003449 ha_cpuset_count(&cpu_map.thread[i])) {/* only do this if the thread has a THREAD map */
David Carlier5e4c8e22019-09-13 05:12:58 +01003450#if defined(__APPLE__)
3451 int j;
Amaury Denoyelle8f685c12021-04-27 16:45:29 +02003452 unsigned long set = cpu_map.thread[i].cpuset;
David Carlier5e4c8e22019-09-13 05:12:58 +01003453
Amaury Denoyelle8f685c12021-04-27 16:45:29 +02003454 while ((j = ffsl(set)) > 0) {
David Carlier5e4c8e22019-09-13 05:12:58 +01003455 thread_affinity_policy_data_t cpu_set = { j - 1 };
3456 thread_port_t mthread = pthread_mach_thread_np(ha_thread_info[i].pthread);
3457 thread_policy_set(mthread, THREAD_AFFINITY_POLICY, (thread_policy_t)&cpu_set, 1);
Amaury Denoyelle8f685c12021-04-27 16:45:29 +02003458 set &= ~(1UL << (j - 1));
David Carlier5e4c8e22019-09-13 05:12:58 +01003459 }
3460#else
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003461 struct hap_cpuset *set = &cpu_map.thread[i];
David Carliera92c5ce2019-09-13 05:03:12 +01003462 pthread_setaffinity_np(ha_thread_info[i].pthread,
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003463 sizeof(set->cpuset), &set->cpuset);
David Carlier5e4c8e22019-09-13 05:12:58 +01003464#endif
Olivier Houchard829aa242017-12-01 18:19:43 +01003465 }
Christopher Faulet1d17c102017-08-29 15:38:48 +02003466 }
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003467#endif /* !USE_CPU_AFFINITY */
3468
William Lallemand1aab50b2018-06-07 09:46:01 +02003469 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003470 haproxy_unblock_signals();
William Lallemand1aab50b2018-06-07 09:46:01 +02003471
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003472 /* Finally, start the poll loop for the first thread */
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02003473 run_thread_poll_loop(0);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003474
3475 /* Wait the end of other threads */
3476 for (i = 1; i < global.nbthread; i++)
David Carliera92c5ce2019-09-13 05:03:12 +01003477 pthread_join(ha_thread_info[i].pthread, NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02003478
Christopher Fauletb79a94c2017-05-30 15:34:30 +02003479#if defined(DEBUG_THREAD) || defined(DEBUG_FULL)
3480 show_lock_stats();
3481#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003482 }
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003483#else /* ! USE_THREAD */
William Lallemandd3801c12018-09-11 10:06:23 +02003484 haproxy_unblock_signals();
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02003485 run_thread_poll_loop(0);
Christopher Faulet62519022017-10-16 15:49:32 +02003486#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003487
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003488 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003489}
3490
Willy Tarreaubaaee002006-06-26 02:48:02 +02003491/*
3492 * Local variables:
3493 * c-indent-level: 8
3494 * c-basic-offset: 8
3495 * End:
3496 */