blob: dd1130de2cfefdbcac2cfb3ff3e4ea59910888dd [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
Christopher Faulet4c20ccb2023-01-27 14:51:36 +01003 * Copyright 2000-2023 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.com078062b2021-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>
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +020094#include <haproxy/cfgdiag.h>
Willy Tarreau6be78492020-06-05 00:00:29 +020095#include <haproxy/cfgparse.h>
Willy Tarreauc13ed532020-06-02 10:22:45 +020096#include <haproxy/chunk.h>
Willy Tarreau83487a82020-06-04 20:19:54 +020097#include <haproxy/cli.h>
Willy Tarreau7ea393d2020-06-04 18:02:10 +020098#include <haproxy/connection.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +020099#ifdef USE_CPU_AFFINITY
Amaury Denoyelle982fb532021-04-21 18:39:58 +0200100#include <haproxy/cpuset.h>
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +0200101#endif
Willy Tarreaueb92deb2020-06-04 10:53:16 +0200102#include <haproxy/dns.h>
Willy Tarreau2741c8c2020-06-02 11:28:02 +0200103#include <haproxy/dynbuf.h>
Willy Tarreau8d366972020-05-27 16:10:29 +0200104#include <haproxy/errors.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200105#include <haproxy/fd.h>
Willy Tarreauc7babd82020-06-04 21:29:29 +0200106#include <haproxy/filters.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200107#include <haproxy/global.h>
Willy Tarreau86416052020-06-04 09:20:54 +0200108#include <haproxy/hlua.h>
Willy Tarreauc761f842020-06-04 11:40:28 +0200109#include <haproxy/http_rules.h>
Willy Tarreau853b2972020-05-27 18:01:47 +0200110#include <haproxy/list.h>
Willy Tarreau213e9902020-06-04 14:58:24 +0200111#include <haproxy/listener.h>
Willy Tarreauaeed4a82020-06-04 22:01:04 +0200112#include <haproxy/log.h>
Willy Tarreaub5abe5b2020-06-04 14:07:37 +0200113#include <haproxy/mworker.h>
Willy Tarreau7a00efb2020-06-02 17:02:59 +0200114#include <haproxy/namespace.h>
Willy Tarreau6131d6a2020-06-02 16:48:09 +0200115#include <haproxy/net_helper.h>
Willy Tarreau6019fab2020-05-27 16:26:00 +0200116#include <haproxy/openssl-compat.h>
Willy Tarreau225a90a2020-06-04 15:06:28 +0200117#include <haproxy/pattern.h>
Willy Tarreau3c2a7c22020-06-04 18:38:21 +0200118#include <haproxy/peers.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200119#include <haproxy/pool.h>
120#include <haproxy/protocol.h>
Willy Tarreaubf3b06b2020-08-26 10:23:40 +0200121#include <haproxy/proto_tcp.h>
Willy Tarreaua264d962020-06-04 22:29:18 +0200122#include <haproxy/proxy.h>
Willy Tarreau7cd8b6e2020-06-02 17:32:26 +0200123#include <haproxy/regex.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200124#include <haproxy/sample.h>
Willy Tarreau1e56f922020-06-04 23:20:13 +0200125#include <haproxy/server.h>
Willy Tarreau48d25b32020-06-04 18:58:52 +0200126#include <haproxy/session.h>
Willy Tarreau3727a8a2020-06-04 17:37:26 +0200127#include <haproxy/signal.h>
Willy Tarreau063d47d2020-08-28 16:29:53 +0200128#include <haproxy/sock.h>
Willy Tarreau25140cc2020-08-28 15:40:33 +0200129#include <haproxy/sock_inet.h>
Willy Tarreau209108d2020-06-04 20:30:20 +0200130#include <haproxy/ssl_sock.h>
Amaury Denoyelleee63d4b2020-10-05 11:49:42 +0200131#include <haproxy/stats-t.h>
Willy Tarreaudfd3de82020-06-04 23:46:14 +0200132#include <haproxy/stream.h>
Willy Tarreaucea0e1b2020-06-04 17:25:40 +0200133#include <haproxy/task.h>
Willy Tarreau3f567e42020-05-28 15:29:19 +0200134#include <haproxy/thread.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200135#include <haproxy/time.h>
136#include <haproxy/tools.h>
137#include <haproxy/uri_auth-t.h>
Willy Tarreaua1718922020-06-04 16:25:31 +0200138#include <haproxy/vars.h>
Willy Tarreaub2551052020-06-09 09:07:15 +0200139#include <haproxy/version.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +0200140
Willy Tarreaubaaee002006-06-26 02:48:02 +0200141
Willy Tarreau7b5654f2019-03-29 21:30:17 +0100142/* array of init calls for older platforms */
143DECLARE_INIT_STAGES;
144
Willy Tarreauf4596402021-04-10 16:53:05 +0200145/* create a read_mostly section to hold variables which are accessed a lot
146 * but which almost never change. The purpose is to isolate them in their
147 * own cache lines where they don't risk to be perturbated by write accesses
148 * to neighbor variables. We need to create an empty aligned variable for
149 * this. The fact that the variable is of size zero means that it will be
150 * eliminated at link time if no other variable uses it, but alignment will
151 * be respected.
152 */
153empty_t __read_mostly_align HA_SECTION("read_mostly") ALIGNED(64);
154
Willy Tarreauf0d3b732021-05-06 16:30:32 +0200155#ifdef BUILD_FEATURES
156const char *build_features = BUILD_FEATURES;
157#else
158const char *build_features = "";
159#endif
160
Willy Tarreau477ecd82010-01-03 21:12:30 +0100161/* list of config files */
162static struct list cfg_cfgfiles = LIST_HEAD_INIT(cfg_cfgfiles);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200163int pid; /* current process id */
Willy Tarreau28156642007-11-26 16:13:36 +0100164int relative_pid = 1; /* process id starting at 1 */
Willy Tarreau387bd4f2017-11-10 19:08:14 +0100165unsigned long pid_bit = 1; /* bit corresponding to the process id */
Willy Tarreaua38a7172019-02-02 17:11:28 +0100166unsigned long all_proc_mask = 1; /* mask of all processes */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200167
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100168volatile unsigned long sleeping_thread_mask = 0; /* Threads that are about to sleep in poll() */
Willy Tarreau4b3f27b2020-03-12 17:28:01 +0100169volatile unsigned long stopping_thread_mask = 0; /* Threads acknowledged stopping */
Willy Tarreauf8ea00e2020-03-12 17:24:53 +0100170
Willy Tarreaubaaee002006-06-26 02:48:02 +0200171/* global options */
172struct global global = {
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100173 .hard_stop_after = TICK_ETERNITY,
Willy Tarreau247a13a2012-11-15 17:38:15 +0100174 .nbproc = 1,
Amaury Denoyelle0f50cb92021-03-26 18:50:33 +0100175 .numa_cpu_mapping = 1,
Willy Tarreau149ab772019-01-26 14:27:06 +0100176 .nbthread = 0,
William Lallemand5f232402012-04-05 18:02:55 +0200177 .req_count = 0,
William Lallemand0f99e342011-10-12 17:50:54 +0200178 .logsrvs = LIST_HEAD_INIT(global.logsrvs),
William Lallemand9d5f5482012-11-07 16:12:57 +0100179 .maxzlibmem = 0,
William Lallemandd85f9172012-11-09 17:05:39 +0100180 .comp_rate_lim = 0,
Emeric Brun850efd52014-01-29 12:24:34 +0100181 .ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED,
Emeric Bruned760922010-10-22 17:59:25 +0200182 .unix_bind = {
183 .ux = {
184 .uid = -1,
185 .gid = -1,
186 .mode = 0,
187 }
188 },
Willy Tarreau27a674e2009-08-17 07:23:33 +0200189 .tune = {
Willy Tarreau7ac908b2019-02-27 12:02:18 +0100190 .options = GTUNE_LISTENER_MQ,
Willy Tarreauc77d3642018-12-12 06:19:42 +0100191 .bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
Christopher Faulet546c4692020-01-22 14:31:21 +0100192 .maxrewrite = MAXREWRITE,
Willy Tarreaua24adf02014-11-27 01:11:56 +0100193 .reserved_bufs = RESERVED_BUFS,
Willy Tarreauf3045d22015-04-29 16:24:50 +0200194 .pattern_cache = DEFAULT_PAT_LRU_SIZE,
Olivier Houchard88698d92019-04-16 19:07:22 +0200195 .pool_low_ratio = 20,
196 .pool_high_ratio = 25,
Christopher Faulet41ba36f2019-07-19 09:36:45 +0200197 .max_http_hdr = MAX_HTTP_HDR,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200198#ifdef USE_OPENSSL
Emeric Brun46635772012-11-14 11:32:56 +0100199 .sslcachesize = SSLCACHESIZE,
Emeric Brunfc32aca2012-09-03 12:10:29 +0200200#endif
William Lallemandf3747832012-11-09 12:33:10 +0100201 .comp_maxlevel = 1,
Willy Tarreau7e312732014-02-12 16:35:14 +0100202#ifdef DEFAULT_IDLE_TIMER
203 .idle_timer = DEFAULT_IDLE_TIMER,
204#else
205 .idle_timer = 1000, /* 1 second */
206#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200207 },
Emeric Brun76d88952012-10-05 15:47:31 +0200208#ifdef USE_OPENSSL
209#ifdef DEFAULT_MAXSSLCONN
Willy Tarreau403edff2012-09-06 11:58:37 +0200210 .maxsslconn = DEFAULT_MAXSSLCONN,
211#endif
Emeric Brun76d88952012-10-05 15:47:31 +0200212#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200213 /* others NULL OK */
214};
215
216/*********************************************************************/
217
218int stopping; /* non zero means stopping in progress */
Cyril Bonté203ec5a2017-03-23 22:44:13 +0100219int killed; /* non zero means a hard-stop is triggered */
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200220int jobs = 0; /* number of active jobs (conns, listeners, active tasks, ...) */
William Lallemanda7199262018-11-16 16:57:20 +0100221int unstoppable_jobs = 0; /* number of active jobs that can't be stopped during a soft stop */
Willy Tarreau199ad242018-11-05 16:31:22 +0100222int active_peers = 0; /* number of active peers (connection attempts and connected) */
Willy Tarreau2d372c22018-11-05 17:12:27 +0100223int connected_peers = 0; /* number of connected peers (verified ones) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224
Ilya Shipitsin46a030c2020-07-05 16:36:08 +0500225/* Here we store information about the pids of the processes we may pause
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 * or kill. We will send them a signal every 10 ms until we can bind to all
227 * our ports. With 200 retries, that's about 2 seconds.
228 */
229#define MAX_START_RETRIES 200
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230static int *oldpids = NULL;
231static int oldpids_sig; /* use USR1 or TERM */
232
Olivier Houchardf73629d2017-04-05 22:33:04 +0200233/* Path to the unix socket we use to retrieve listener sockets from the old process */
234static const char *old_unixsocket;
235
William Lallemand85b0bd92017-06-01 17:38:53 +0200236static char *cur_unixsocket = NULL;
237
William Lallemandcb11fd22017-06-01 17:38:52 +0200238int atexit_flag = 0;
239
Willy Tarreaubb545b42010-08-25 12:58:59 +0200240int nb_oldpids = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241const int zero = 0;
242const int one = 1;
Alexandre Cassen87ea5482007-10-11 20:48:58 +0200243const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Willy Tarreau1d21e0a2010-03-12 21:58:54 +0100245char hostname[MAX_HOSTNAME_LEN];
Dragan Dosen4f014152020-06-18 16:56:47 +0200246char *localpeer = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
William Lallemand00417412020-06-05 14:08:41 +0200248static char **old_argv = NULL; /* previous argv but cleaned up */
William Lallemand73b85e72017-06-01 17:38:51 +0200249
William Lallemandbc193052018-09-11 10:06:26 +0200250struct list proc_list = LIST_HEAD_INIT(proc_list);
251
252int master = 0; /* 1 if in master, 0 if in child */
Willy Tarreaubf696402019-03-01 10:09:28 +0100253unsigned int rlim_fd_cur_at_boot = 0;
254unsigned int rlim_fd_max_at_boot = 0;
William Lallemandbc193052018-09-11 10:06:26 +0200255
Willy Tarreau6c3a6812020-03-06 18:57:15 +0100256/* per-boot randomness */
257unsigned char boot_seed[20]; /* per-boot random seed (160 bits initially) */
258
William Lallemandb3f2be32018-09-11 10:06:18 +0200259static void *run_thread_poll_loop(void *data);
260
Willy Tarreauff055502014-04-28 22:27:06 +0200261/* bitfield of a few warnings to emit just once (WARN_*) */
262unsigned int warned = 0;
263
Amaury Denoyelle484454d2021-05-05 16:18:45 +0200264/* set if experimental features have been used for the current process */
265static unsigned int tainted = 0;
266
Amaury Denoyelled2e53cd2021-05-06 16:21:39 +0200267unsigned int experimental_directives_allowed = 0;
268
269int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
270 char **errmsg)
271{
272 if (kw->flags & KWF_EXPERIMENTAL) {
273 if (!experimental_directives_allowed) {
Amaury Denoyelle86c1d0f2021-05-07 15:07:21 +0200274 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 +0200275 file, linenum, kw->kw);
276 return 1;
277 }
278 mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
279 }
280
281 return 0;
282}
283
William Lallemande7361152018-10-26 14:47:36 +0200284/* master CLI configuration (-S flag) */
285struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100286
287/* These are strings to be reported in the output of "haproxy -vv". They may
288 * either be constants (in which case must_free must be zero) or dynamically
289 * allocated strings to pass to free() on exit, and in this case must_free
290 * must be non-zero.
291 */
292struct list build_opts_list = LIST_HEAD_INIT(build_opts_list);
293struct build_opts_str {
294 struct list list;
295 const char *str;
296 int must_free;
297};
298
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299/*********************************************************************/
300/* general purpose functions ***************************************/
301/*********************************************************************/
302
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100303/* used to register some build option strings at boot. Set must_free to
304 * non-zero if the string must be freed upon exit.
305 */
306void hap_register_build_opts(const char *str, int must_free)
307{
308 struct build_opts_str *b;
309
310 b = calloc(1, sizeof(*b));
311 if (!b) {
312 fprintf(stderr, "out of memory\n");
313 exit(1);
314 }
315 b->str = str;
316 b->must_free = must_free;
Willy Tarreau2b718102021-04-21 07:32:39 +0200317 LIST_APPEND(&build_opts_list, &b->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100318}
319
Willy Tarreaua43dfda2021-05-06 07:43:35 +0200320#define VERSION_MAX_ELTS 7
321
322/* This function splits an haproxy version string into an array of integers.
323 * The syntax of the supported version string is the following:
324 *
325 * <a>[.<b>[.<c>[.<d>]]][-{dev,pre,rc}<f>][-*][-<g>]
326 *
327 * This validates for example:
328 * 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
329 * 2.4-dev18-f6818d-20
330 *
331 * The result is set in a array of <VERSION_MAX_ELTS> elements. Each letter has
332 * one fixed place in the array. The tags take a numeric value called <e> which
333 * defaults to 3. "dev" is 1, "rc" and "pre" are 2. Numbers not encountered are
334 * considered as zero (henxe 1.5 and 1.5.0 are the same).
335 *
336 * The resulting values are:
337 * 1.2.1-pre2 1, 2, 1, 0, 2, 2, 0
338 * 1.2.1 1, 2, 1, 0, 3, 0, 0
339 * 1.2.10.1 1, 2, 10, 1, 3, 0, 0
340 * 1.3.16-rc1 1, 3, 16, 0, 2, 1, 0
341 * 1.4-dev3 1, 4, 0, 0, 1, 3, 0
342 * 1.5-dev18 1, 5, 0, 0, 1, 18, 0
343 * 1.5-dev18-43 1, 5, 0, 0, 1, 18, 43
344 * 2.4-dev18-f6818d-20 2, 4, 0, 0, 1, 18, 20
345 *
346 * The function returns non-zero if the conversion succeeded, or zero if it
347 * failed.
348 */
349int split_version(const char *version, unsigned int *value)
350{
351 const char *p, *s;
352 char *error;
353 int nelts;
354
355 /* Initialize array with zeroes */
356 for (nelts = 0; nelts < VERSION_MAX_ELTS; nelts++)
357 value[nelts] = 0;
358 value[4] = 3;
359
360 p = version;
361
362 /* If the version number is empty, return false */
363 if (*p == '\0')
364 return 0;
365
366 /* Convert first number <a> */
367 value[0] = strtol(p, &error, 10);
368 p = error + 1;
369 if (*error == '\0')
370 return 1;
371 if (*error == '-')
372 goto split_version_tag;
373 if (*error != '.')
374 return 0;
375
376 /* Convert first number <b> */
377 value[1] = strtol(p, &error, 10);
378 p = error + 1;
379 if (*error == '\0')
380 return 1;
381 if (*error == '-')
382 goto split_version_tag;
383 if (*error != '.')
384 return 0;
385
386 /* Convert first number <c> */
387 value[2] = strtol(p, &error, 10);
388 p = error + 1;
389 if (*error == '\0')
390 return 1;
391 if (*error == '-')
392 goto split_version_tag;
393 if (*error != '.')
394 return 0;
395
396 /* Convert first number <d> */
397 value[3] = strtol(p, &error, 10);
398 p = error + 1;
399 if (*error == '\0')
400 return 1;
401 if (*error != '-')
402 return 0;
403
404 split_version_tag:
405 /* Check for commit number */
406 if (*p >= '0' && *p <= '9')
407 goto split_version_commit;
408
409 /* Read tag */
410 if (strncmp(p, "dev", 3) == 0) { value[4] = 1; p += 3; }
411 else if (strncmp(p, "rc", 2) == 0) { value[4] = 2; p += 2; }
412 else if (strncmp(p, "pre", 3) == 0) { value[4] = 2; p += 3; }
413 else
414 goto split_version_commit;
415
416 /* Convert tag number */
417 value[5] = strtol(p, &error, 10);
418 p = error + 1;
419 if (*error == '\0')
420 return 1;
421 if (*error != '-')
422 return 0;
423
424 split_version_commit:
425 /* Search the last "-" */
426 s = strrchr(p, '-');
427 if (s) {
428 s++;
429 if (*s == '\0')
430 return 0;
431 value[6] = strtol(s, &error, 10);
432 if (*error != '\0')
433 value[6] = 0;
434 return 1;
435 }
436
437 /* convert the version */
438 value[6] = strtol(p, &error, 10);
439 if (*error != '\0')
440 value[6] = 0;
441
442 return 1;
443}
444
445/* This function compares the current haproxy version with an arbitrary version
446 * string. It returns:
447 * -1 : the version in argument is older than the current haproxy version
448 * 0 : the version in argument is the same as the current haproxy version
449 * 1 : the version in argument is newer than the current haproxy version
450 *
451 * Or some errors:
452 * -2 : the current haproxy version is not parsable
453 * -3 : the version in argument is not parsable
454 */
455int compare_current_version(const char *version)
456{
457 unsigned int loc[VERSION_MAX_ELTS];
458 unsigned int mod[VERSION_MAX_ELTS];
459 int i;
460
461 /* split versions */
462 if (!split_version(haproxy_version, loc))
463 return -2;
464 if (!split_version(version, mod))
465 return -3;
466
467 /* compare versions */
468 for (i = 0; i < VERSION_MAX_ELTS; i++) {
469 if (mod[i] < loc[i])
470 return -1;
471 else if (mod[i] > loc[i])
472 return 1;
473 }
474 return 0;
475}
476
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100477static void display_version()
Willy Tarreaubaaee002006-06-26 02:48:02 +0200478{
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200479 struct utsname utsname;
480
Willy Tarreaua5357cd2021-05-09 06:14:25 +0200481 printf("HAProxy version %s %s - https://haproxy.org/\n"
Willy Tarreau08dd2022019-11-21 18:07:30 +0100482 PRODUCT_STATUS "\n", haproxy_version, haproxy_date);
Willy Tarreau47479eb2019-11-21 18:48:20 +0100483
484 if (strlen(PRODUCT_URL_BUGS) > 0) {
485 char base_version[20];
486 int dots = 0;
487 char *del;
488
489 /* only retrieve the base version without distro-specific extensions */
490 for (del = haproxy_version; *del; del++) {
491 if (*del == '.')
492 dots++;
493 else if (*del < '0' || *del > '9')
494 break;
495 }
496
497 strlcpy2(base_version, haproxy_version, del - haproxy_version + 1);
498 if (dots < 2)
499 printf("Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open\n");
500 else
501 printf("Known bugs: " PRODUCT_URL_BUGS "\n", base_version);
502 }
Tim Duesterhusdfad6a42020-04-18 16:02:47 +0200503
504 if (uname(&utsname) == 0) {
505 printf("Running on: %s %s %s %s\n", utsname.sysname, utsname.release, utsname.version, utsname.machine);
506 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200507}
508
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100509static void display_build_opts()
Willy Tarreau7b066db2007-12-02 11:28:59 +0100510{
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100511 struct build_opts_str *item;
512
Willy Tarreau7b066db2007-12-02 11:28:59 +0100513 printf("Build options :"
514#ifdef BUILD_TARGET
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100515 "\n TARGET = " BUILD_TARGET
Willy Tarreau7b066db2007-12-02 11:28:59 +0100516#endif
517#ifdef BUILD_CPU
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100518 "\n CPU = " BUILD_CPU
Willy Tarreau7b066db2007-12-02 11:28:59 +0100519#endif
520#ifdef BUILD_CC
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100521 "\n CC = " BUILD_CC
522#endif
523#ifdef BUILD_CFLAGS
524 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100525#endif
Willy Tarreau9f2b7302008-01-02 20:48:34 +0100526#ifdef BUILD_OPTIONS
527 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau7b066db2007-12-02 11:28:59 +0100528#endif
Tim Duesterhusc8d19702020-11-21 18:07:59 +0100529#ifdef BUILD_DEBUG
530 "\n DEBUG = " BUILD_DEBUG
531#endif
Willy Tarreau7728ed32019-03-27 13:20:08 +0100532#ifdef BUILD_FEATURES
533 "\n\nFeature list : " BUILD_FEATURES
534#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200535 "\n\nDefault settings :"
Willy Tarreauca783d42019-03-13 10:03:07 +0100536 "\n bufsize = %d, maxrewrite = %d, maxpollevents = %d"
Willy Tarreau27a674e2009-08-17 07:23:33 +0200537 "\n\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100538 BUFSIZE, MAXREWRITE, MAX_POLL_EVENTS);
Willy Tarreaube5b6852009-10-03 18:57:08 +0200539
Willy Tarreaucdb737e2016-12-21 18:43:10 +0100540 list_for_each_entry(item, &build_opts_list, list) {
541 puts(item->str);
542 }
543
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100544 putchar('\n');
545
Willy Tarreaube5b6852009-10-03 18:57:08 +0200546 list_pollers(stdout);
547 putchar('\n');
Christopher Faulet98d9fe22018-04-10 14:37:32 +0200548 list_mux_proto(stdout);
549 putchar('\n');
Willy Tarreau679bba12019-03-19 08:08:10 +0100550 list_services(stdout);
551 putchar('\n');
Christopher Fauletb3f4e142016-03-07 12:46:38 +0100552 list_filters(stdout);
553 putchar('\n');
Willy Tarreau7b066db2007-12-02 11:28:59 +0100554}
555
Willy Tarreaubaaee002006-06-26 02:48:02 +0200556/*
557 * This function prints the command line usage and exits
558 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100559static void usage(char *name)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200560{
561 display_version();
562 fprintf(stderr,
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200563 "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200564 "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n"
Willy Tarreaua088d312015-10-08 11:58:48 +0200565 " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] [-- <cfgfile>*]\n"
Willy Tarreau7b066db2007-12-02 11:28:59 +0100566 " -v displays version ; -vv shows known build options.\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567 " -d enters debug mode ; -db only disables background mode.\n"
Willy Tarreau6e064432012-05-08 15:40:42 +0200568 " -dM[<byte>] poisons memory with <byte> (defaults to 0x50)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200569 " -V enters verbose mode (disables quiet mode)\n"
Willy Tarreau576132e2011-09-10 19:26:56 +0200570 " -D goes daemon ; -C changes to <dir> before loading files.\n"
William Lallemand095ba4c2017-06-01 17:38:50 +0200571 " -W master-worker mode.\n"
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100572#if defined(USE_SYSTEMD)
573 " -Ws master-worker mode with systemd notify support.\n"
574#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575 " -q quiet mode : don't display messages\n"
Willy Tarreau5d01a632009-06-22 16:02:30 +0200576 " -c check mode : only check config files and exit\n"
Willy Tarreauca783d42019-03-13 10:03:07 +0100577 " -n sets the maximum total # of connections (uses ulimit -n)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200578 " -m limits the usable amount of memory (in MB)\n"
579 " -N sets the default, per-proxy maximum # of connections (%d)\n"
Emeric Brun2b920a12010-09-23 18:30:22 +0200580 " -L set local peer name (default to hostname)\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581 " -p writes pids of all children to this file\n"
Willy Tarreaue5733232019-05-22 19:24:06 +0200582#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200583 " -de disables epoll() usage even when available\n"
584#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200585#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +0200586 " -dk disables kqueue() usage even when available\n"
587#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200588#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +0000589 " -dv disables event ports usage even when available\n"
590#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200591#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200592 " -dp disables poll() usage even when available\n"
593#endif
Willy Tarreaue5733232019-05-22 19:24:06 +0200594#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100595 " -dS disables splice usage (broken on old kernels)\n"
596#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200597#if defined(USE_GETADDRINFO)
598 " -dG disables getaddrinfo() usage\n"
599#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000600#if defined(SO_REUSEPORT)
601 " -dR disables SO_REUSEPORT usage\n"
602#endif
Willy Tarreau0aa9dbe2021-12-28 15:43:11 +0100603#if defined(HA_HAVE_DUMP_LIBS)
604 " -dL dumps loaded object files after config checks\n"
605#endif
Willy Tarreau3eed10e2016-11-07 21:03:16 +0100606 " -dr ignores server address resolution failures\n"
Emeric Brun850efd52014-01-29 12:24:34 +0100607 " -dV disables SSL verify on servers side\n"
Willy Tarreau3eb10b82020-04-15 16:42:39 +0200608 " -dW fails if any warning is emitted\n"
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +0200609 " -dD diagnostic mode : warn about suspicious configuration statements\n"
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +0200610 " -sf/-st [pid ]* finishes/terminates old pids.\n"
Olivier Houchardf73629d2017-04-05 22:33:04 +0200611 " -x <unix_socket> get listening sockets from a unix socket\n"
William Lallemand63329e32019-06-13 17:03:37 +0200612 " -S <bind>[,<bind options>...] new master CLI\n"
Willy Tarreaubaaee002006-06-26 02:48:02 +0200613 "\n",
Willy Tarreauca783d42019-03-13 10:03:07 +0100614 name, cfg_maxpconn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615 exit(1);
616}
617
618
619
620/*********************************************************************/
621/* more specific functions ***************************************/
622/*********************************************************************/
623
William Lallemand73b85e72017-06-01 17:38:51 +0200624/* sends the signal <sig> to all pids found in <oldpids>. Returns the number of
625 * pids the signal was correctly delivered to.
626 */
William Lallemande25473c2019-04-01 11:29:56 +0200627int tell_old_pids(int sig)
William Lallemand73b85e72017-06-01 17:38:51 +0200628{
629 int p;
630 int ret = 0;
631 for (p = 0; p < nb_oldpids; p++)
632 if (kill(oldpids[p], sig) == 0)
633 ret++;
634 return ret;
635}
636
William Lallemand75ea0a02017-11-15 19:02:58 +0100637/*
William Lallemand73b85e72017-06-01 17:38:51 +0200638 * remove a pid forom the olpid array and decrease nb_oldpids
639 * return 1 pid was found otherwise return 0
640 */
641
642int delete_oldpid(int pid)
643{
644 int i;
645
646 for (i = 0; i < nb_oldpids; i++) {
647 if (oldpids[i] == pid) {
648 oldpids[i] = oldpids[nb_oldpids - 1];
649 oldpids[nb_oldpids - 1] = 0;
650 nb_oldpids--;
651 return 1;
652 }
653 }
654 return 0;
655}
656
William Lallemand85b0bd92017-06-01 17:38:53 +0200657
658static void get_cur_unixsocket()
659{
Willy Tarreau7b11b7e2022-02-01 08:47:41 +0100660 /* get rid of the one found on the command line for now */
661 ha_free(&cur_unixsocket);
662
William Lallemand85b0bd92017-06-01 17:38:53 +0200663 /* if -x was used, try to update the stat socket if not available anymore */
Willy Tarreau4975d142021-03-13 11:00:33 +0100664 if (global.cli_fe) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200665 struct bind_conf *bind_conf;
666
667 /* pass through all stats socket */
Willy Tarreau4975d142021-03-13 11:00:33 +0100668 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200669 struct listener *l;
670
671 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
672
Willy Tarreau37159062020-08-27 07:48:42 +0200673 if (l->rx.addr.ss_family == AF_UNIX &&
William Lallemand85b0bd92017-06-01 17:38:53 +0200674 (bind_conf->level & ACCESS_FD_LISTENERS)) {
675 const struct sockaddr_un *un;
676
Willy Tarreau37159062020-08-27 07:48:42 +0200677 un = (struct sockaddr_un *)&l->rx.addr;
William Lallemand85b0bd92017-06-01 17:38:53 +0200678 /* priority to old_unixsocket */
679 if (!cur_unixsocket) {
680 cur_unixsocket = strdup(un->sun_path);
681 } else {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100682 if (old_unixsocket && strcmp(un->sun_path, old_unixsocket) == 0) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200683 free(cur_unixsocket);
684 cur_unixsocket = strdup(old_unixsocket);
685 return;
686 }
687 }
688 }
689 }
690 }
691 }
692 if (!cur_unixsocket && old_unixsocket)
693 cur_unixsocket = strdup(old_unixsocket);
694}
695
William Lallemand73b85e72017-06-01 17:38:51 +0200696/*
697 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800698 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200699 */
William Lallemanda57b7e32018-12-14 21:11:31 +0100700void mworker_reload()
William Lallemand73b85e72017-06-01 17:38:51 +0200701{
William Lallemand00417412020-06-05 14:08:41 +0200702 char **next_argv = NULL;
703 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200704 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200705 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200706 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100707 struct rlimit limit;
William Lallemand7c756a82018-11-26 11:53:40 +0100708 struct per_thread_deinit_fct *ptdf;
William Lallemand73b85e72017-06-01 17:38:51 +0200709
710 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100711#if defined(USE_SYSTEMD)
712 if (global.tune.options & GTUNE_USE_SYSTEMD)
713 sd_notify(0, "RELOADING=1");
714#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200715 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
716
William Lallemand030571a2022-01-28 21:17:30 +0100717 mworker_cleanup_proc();
William Lallemandbc193052018-09-11 10:06:26 +0200718 mworker_proc_list_to_env(); /* put the children description in the env */
719
William Lallemand7c756a82018-11-26 11:53:40 +0100720 /* during the reload we must ensure that every FDs that can't be
721 * reuse (ie those that are not referenced in the proc_list)
722 * are closed or they will leak. */
723
724 /* close the listeners FD */
725 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200726
727 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
728 /* close the poller FD and the thread waker pipe FD */
729 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
730 ptdf->fct();
731 if (fdtab)
732 deinit_pollers();
733 }
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500734#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200735 /* close random device FDs */
736 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100737#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100738
Willy Tarreau8dca1952019-03-01 10:21:55 +0100739 /* restore the initial FD limits */
740 limit.rlim_cur = rlim_fd_cur_at_boot;
741 limit.rlim_max = rlim_fd_max_at_boot;
742 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
743 getrlimit(RLIMIT_NOFILE, &limit);
744 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
745 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
746 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
747 }
748
William Lallemand73b85e72017-06-01 17:38:51 +0200749 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200750 while (old_argv[old_argc])
751 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200752
William Lallemand85b0bd92017-06-01 17:38:53 +0200753 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200754 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200755 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200756 if (next_argv == NULL)
757 goto alloc_error;
758
William Lallemand00417412020-06-05 14:08:41 +0200759 /* copy the program name */
760 next_argv[next_argc++] = old_argv[0];
761
762 /* insert the new options just after argv[0] in case we have a -- */
763
William Lallemand73b85e72017-06-01 17:38:51 +0200764 /* add -sf <PID>* to argv */
William Lallemand3f128872019-04-01 11:29:59 +0200765 if (mworker_child_nb() > 0) {
766 struct mworker_proc *child;
767
William Lallemand73b85e72017-06-01 17:38:51 +0200768 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200769
770 list_for_each_entry(child, &proc_list, list) {
William Lallemand677e2f22019-11-19 17:04:18 +0100771 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1 )
William Lallemand3f128872019-04-01 11:29:59 +0200772 continue;
William Lallemand00417412020-06-05 14:08:41 +0200773 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
William Lallemand73b85e72017-06-01 17:38:51 +0200774 goto alloc_error;
775 msg = NULL;
776 }
777 }
William Lallemand2bf6d622017-06-20 11:20:23 +0200778 /* add the -x option with the stat socket */
William Lallemand85b0bd92017-06-01 17:38:53 +0200779 if (cur_unixsocket) {
William Lallemand2bf6d622017-06-20 11:20:23 +0200780 next_argv[next_argc++] = "-x";
781 next_argv[next_argc++] = (char *)cur_unixsocket;
William Lallemand85b0bd92017-06-01 17:38:53 +0200782 }
783
William Lallemand00417412020-06-05 14:08:41 +0200784 /* copy the previous options */
785 for (i = 1; i < old_argc; i++)
786 next_argv[next_argc++] = old_argv[i];
787
Christopher Faulet767a84b2017-11-24 16:50:31 +0100788 ha_warning("Reexecuting Master process\n");
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200789 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100790 execvp(next_argv[0], next_argv);
William Lallemand73b85e72017-06-01 17:38:51 +0200791
Christopher Faulet767a84b2017-11-24 16:50:31 +0100792 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100793 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100794 return;
795
William Lallemand73b85e72017-06-01 17:38:51 +0200796alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100797 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800798 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200799 return;
800}
801
William Lallemandb3f2be32018-09-11 10:06:18 +0200802static void mworker_loop()
803{
804
805#if defined(USE_SYSTEMD)
806 if (global.tune.options & GTUNE_USE_SYSTEMD)
807 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
808#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200809 /* Busy polling makes no sense in the master :-) */
810 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200811
William Lallemandbc193052018-09-11 10:06:26 +0200812 master = 1;
813
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100814 signal_unregister(SIGTTIN);
815 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100816 signal_unregister(SIGUSR1);
817 signal_unregister(SIGHUP);
818 signal_unregister(SIGQUIT);
819
William Lallemandb3f2be32018-09-11 10:06:18 +0200820 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
821 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100822 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
823 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200824 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
825 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
826 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
827 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
828
829 mworker_unblock_signals();
830 mworker_cleanlisteners();
William Lallemand27f3fa52018-12-06 14:05:20 +0100831 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200832
William Lallemandbc193052018-09-11 10:06:26 +0200833 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
834 some SIGCHLD were lost */
835
William Lallemandb3f2be32018-09-11 10:06:18 +0200836 global.nbthread = 1;
837 relative_pid = 1;
838 pid_bit = 1;
Willy Tarreaua38a7172019-02-02 17:11:28 +0100839 all_proc_mask = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200840
William Lallemand2672eb92018-12-14 15:52:39 +0100841#ifdef USE_THREAD
842 tid_bit = 1;
843 all_threads_mask = 1;
844#endif
845
William Lallemandb3f2be32018-09-11 10:06:18 +0200846 jobs++; /* this is the "master" job, we want to take care of the
847 signals even if there is no listener so the poll loop don't
848 leave */
849
850 fork_poller();
Willy Tarreaub4f7cc32019-05-03 09:27:30 +0200851 run_thread_poll_loop(0);
William Lallemandb3f2be32018-09-11 10:06:18 +0200852}
William Lallemandcb11fd22017-06-01 17:38:52 +0200853
854/*
855 * Reexec the process in failure mode, instead of exiting
856 */
857void reexec_on_failure()
858{
859 if (!atexit_flag)
860 return;
861
862 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
863
Willy Tarreau96d9a7f2022-01-28 18:40:06 +0100864 /* do not keep unused FDs retrieved from the previous process */
865 sock_drop_unused_old_sockets();
866
Christopher Faulet767a84b2017-11-24 16:50:31 +0100867 ha_warning("Reexecuting Master process in waitpid mode\n");
William Lallemandcb11fd22017-06-01 17:38:52 +0200868 mworker_reload();
William Lallemandcb11fd22017-06-01 17:38:52 +0200869}
William Lallemand73b85e72017-06-01 17:38:51 +0200870
871
872/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200873 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
874 * a signal zero to all subscribers. This means that it's as easy as
875 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200876 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100877static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200878{
879 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200880 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100881 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882}
883
884/*
885 * upon SIGTTOU, we pause everything
886 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100887static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200888{
Willy Tarreau775e0012020-09-24 16:36:26 +0200889 if (protocol_pause_all() & ERR_FATAL) {
890 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200891 ha_warning("%s", msg);
892 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200893 soft_stop();
894 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100895 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200896}
897
898/*
899 * upon SIGTTIN, let's have a soft stop.
900 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100901static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902{
Willy Tarreau775e0012020-09-24 16:36:26 +0200903 if (protocol_resume_all() & ERR_FATAL) {
904 const char *msg = "Some proxies refused to resume, probably due to a conflict on a listening port. You may want to try again after the conflicting application is stopped, otherwise a restart might be needed to resume safe operations.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200905 ha_warning("%s", msg);
906 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200907 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908}
909
910/*
911 * this function dumps every server's state when the process receives SIGHUP.
912 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100913static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100915 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200916
Christopher Faulet767a84b2017-11-24 16:50:31 +0100917 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 while (p) {
919 struct server *s = p->srv;
920
921 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
922 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100923 chunk_printf(&trash,
924 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
925 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200926 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100927 s->cur_sess, s->nbpend, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200928 ha_warning("%s\n", trash.area);
929 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200930 s = s->next;
931 }
932
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200933 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
934 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100935 chunk_printf(&trash,
936 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
937 p->id,
938 p->feconn, p->beconn, p->totpend, p->nbpend, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200939 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100940 chunk_printf(&trash,
941 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
942 p->id,
943 (p->srv_bck) ? "is running on backup servers" : "has no server available",
944 p->feconn, p->beconn, p->totpend, p->nbpend, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100946 chunk_printf(&trash,
947 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
948 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
949 p->id, p->srv_act, p->srv_bck,
950 p->feconn, p->beconn, p->totpend, p->nbpend, p->fe_counters.cum_conn, p->be_counters.cum_conn);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200951 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200952 ha_warning("%s\n", trash.area);
953 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954
955 p = p->next;
956 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957}
958
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100959static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200960{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200961 /* dump memory usage then free everything possible */
962 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100963 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200964}
965
William Lallemande1340412017-12-28 16:09:36 +0100966/*
967 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
968 * If <fd> < 0, it opens /dev/null and use it to dup
969 *
970 * In the case of chrooting, you have to open /dev/null before the chroot, and
971 * pass the <fd> to this function
972 */
973static void stdio_quiet(int fd)
974{
975 if (fd < 0)
976 fd = open("/dev/null", O_RDWR, 0);
977
978 if (fd > -1) {
979 fclose(stdin);
980 fclose(stdout);
981 fclose(stderr);
982
983 dup2(fd, 0);
984 dup2(fd, 1);
985 dup2(fd, 2);
986 if (fd > 2)
987 close(fd);
988 return;
989 }
990
991 ha_alert("Cannot open /dev/null\n");
992 exit(EXIT_FAILURE);
993}
994
995
Joseph Herlant03420902018-11-15 10:41:50 -0800996/* This function checks if cfg_cfgfiles contains directories.
997 * If it finds one, it adds all the files (and only files) it contains
998 * in cfg_cfgfiles in place of the directory (and removes the directory).
999 * It adds the files in lexical order.
1000 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001001 * It doesn't add files with name starting with '.'
1002 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001003static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001004{
1005 struct wordlist *wl, *wlb;
1006 char *err = NULL;
1007
1008 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1009 struct stat file_stat;
1010 struct dirent **dir_entries = NULL;
1011 int dir_entries_nb;
1012 int dir_entries_it;
1013
1014 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001015 ha_alert("Cannot open configuration file/directory %s : %s\n",
1016 wl->s,
1017 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001018 exit(1);
1019 }
1020
1021 if (!S_ISDIR(file_stat.st_mode))
1022 continue;
1023
1024 /* from this point wl->s is a directory */
1025
1026 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1027 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001028 ha_alert("Cannot open configuration directory %s : %s\n",
1029 wl->s,
1030 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001031 exit(1);
1032 }
1033
1034 /* for each element in the directory wl->s */
1035 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1036 struct dirent *dir_entry = dir_entries[dir_entries_it];
1037 char *filename = NULL;
1038 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1039
1040 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001041 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001042 */
1043 if (dir_entry->d_name[0] == '.' ||
1044 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1045 goto next_dir_entry;
1046
1047 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001048 ha_alert("Cannot load configuration files %s : out of memory.\n",
1049 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001050 exit(1);
1051 }
1052
1053 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001054 ha_alert("Cannot open configuration file %s : %s\n",
1055 wl->s,
1056 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001057 exit(1);
1058 }
1059
1060 /* don't add anything else than regular file in cfg_cfgfiles
1061 * this way we avoid loops
1062 */
1063 if (!S_ISREG(file_stat.st_mode))
1064 goto next_dir_entry;
1065
1066 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001067 ha_alert("Cannot load configuration files %s : %s\n",
1068 filename,
1069 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001070 exit(1);
1071 }
1072
1073next_dir_entry:
1074 free(filename);
1075 free(dir_entry);
1076 }
1077
1078 free(dir_entries);
1079
1080 /* remove the current directory (wl) from cfg_cfgfiles */
1081 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001082 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001083 free(wl);
1084 }
1085
1086 free(err);
1087}
1088
Willy Tarreaubaaee002006-06-26 02:48:02 +02001089/*
William Lallemand73b85e72017-06-01 17:38:51 +02001090 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001091 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001092 * Return an allocated copy of argv
1093 */
1094
1095static char **copy_argv(int argc, char **argv)
1096{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001097 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001098
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001099 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001100 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001101 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001102 return NULL;
1103 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001104 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001105
William Lallemanddf6c5a82020-06-04 17:40:23 +02001106 /* first copy argv[0] */
1107 *newargv++ = *argv++;
1108 argc--;
1109
1110 while (argc > 0) {
1111 if (**argv != '-') {
1112 /* non options are copied but will fail in the argument parser */
1113 *newargv++ = *argv++;
1114 argc--;
1115
1116 } else {
1117 char *flag;
1118
1119 flag = *argv + 1;
1120
1121 if (flag[0] == '-' && flag[1] == 0) {
1122 /* "--\0" copy every arguments till the end of argv */
1123 *newargv++ = *argv++;
1124 argc--;
1125
1126 while (argc > 0) {
1127 *newargv++ = *argv++;
1128 argc--;
1129 }
1130 } else {
1131 switch (*flag) {
1132 case 's':
1133 /* -sf / -st and their parameters are ignored */
1134 if (flag[1] == 'f' || flag[1] == 't') {
1135 argc--;
1136 argv++;
1137 /* The list can't contain a negative value since the only
1138 way to know the end of this list is by looking for the
1139 next option or the end of the options */
1140 while (argc > 0 && argv[0][0] != '-') {
1141 argc--;
1142 argv++;
1143 }
William Lallemand398da622020-09-02 16:12:23 +02001144 } else {
1145 argc--;
1146 argv++;
1147
William Lallemanddf6c5a82020-06-04 17:40:23 +02001148 }
1149 break;
1150
1151 case 'x':
1152 /* this option and its parameter are ignored */
1153 argc--;
1154 argv++;
1155 if (argc > 0) {
1156 argc--;
1157 argv++;
1158 }
1159 break;
1160
1161 case 'C':
1162 case 'n':
1163 case 'm':
1164 case 'N':
1165 case 'L':
1166 case 'f':
1167 case 'p':
1168 case 'S':
1169 /* these options have only 1 parameter which must be copied and can start with a '-' */
1170 *newargv++ = *argv++;
1171 argc--;
1172 if (argc == 0)
1173 goto error;
1174 *newargv++ = *argv++;
1175 argc--;
1176 break;
1177 default:
1178 /* for other options just copy them without parameters, this is also done
1179 * for options like "--foo", but this will fail in the argument parser.
1180 * */
1181 *newargv++ = *argv++;
1182 argc--;
1183 break;
1184 }
William Lallemand73b85e72017-06-01 17:38:51 +02001185 }
1186 }
William Lallemand73b85e72017-06-01 17:38:51 +02001187 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001188
William Lallemanddf6c5a82020-06-04 17:40:23 +02001189 return retargv;
1190
1191error:
1192 free(retargv);
1193 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001194}
1195
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001196
1197/* Performs basic random seed initialization. The main issue with this is that
1198 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1199 * which means that there will only be 4 billion possible random sequences once
1200 * srandom() is called, regardless of the internal state. Not calling it is
1201 * even worse as we'll always produce the same randoms sequences. What we do
1202 * here is to create an initial sequence from various entropy sources, hash it
1203 * using SHA1 and keep the resulting 160 bits available globally.
1204 *
1205 * We initialize the current process with the first 32 bits before starting the
1206 * polling loop, where all this will be changed to have process specific and
1207 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001208 *
1209 * Before starting threads, it's still possible to call random() as srandom()
1210 * is initialized from this, but after threads and/or processes are started,
1211 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001212 */
1213static void ha_random_boot(char *const *argv)
1214{
1215 unsigned char message[256];
1216 unsigned char *m = message;
1217 struct timeval tv;
1218 blk_SHA_CTX ctx;
1219 unsigned long l;
1220 int fd;
1221 int i;
1222
1223 /* start with current time as pseudo-random seed */
1224 gettimeofday(&tv, NULL);
1225 write_u32(m, tv.tv_sec); m += 4;
1226 write_u32(m, tv.tv_usec); m += 4;
1227
1228 /* PID and PPID add some OS-based randomness */
1229 write_u16(m, getpid()); m += 2;
1230 write_u16(m, getppid()); m += 2;
1231
1232 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1233 fd = open("/dev/urandom", O_RDONLY);
1234 if (fd >= 0) {
1235 i = read(fd, m, 20);
1236 if (i > 0)
1237 m += i;
1238 close(fd);
1239 }
1240
1241 /* take up to 160 bits bytes from openssl (non-blocking) */
1242#ifdef USE_OPENSSL
1243 if (RAND_bytes(m, 20) == 1)
1244 m += 20;
1245#endif
1246
1247 /* take 160 bits from existing random in case it was already initialized */
1248 for (i = 0; i < 5; i++) {
1249 write_u32(m, random());
1250 m += 4;
1251 }
1252
1253 /* stack address (benefit form operating system's ASLR) */
1254 l = (unsigned long)&m;
1255 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1256
1257 /* argv address (benefit form operating system's ASLR) */
1258 l = (unsigned long)&argv;
1259 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1260
1261 /* use tv_usec again after all the operations above */
1262 gettimeofday(&tv, NULL);
1263 write_u32(m, tv.tv_usec); m += 4;
1264
1265 /*
1266 * At this point, ~84-92 bytes have been used
1267 */
1268
1269 /* finish with the hostname */
1270 strncpy((char *)m, hostname, message + sizeof(message) - m);
1271 m += strlen(hostname);
1272
1273 /* total message length */
1274 l = m - message;
1275
1276 memset(&ctx, 0, sizeof(ctx));
1277 blk_SHA1_Init(&ctx);
1278 blk_SHA1_Update(&ctx, message, l);
1279 blk_SHA1_Final(boot_seed, &ctx);
1280
1281 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001282 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001283}
1284
Willy Tarreau5a023f02019-03-01 14:19:31 +01001285/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1286 * setting, and returns it. It may return -1 meaning "unlimited" if some
1287 * unlimited proxies have been found and the global.maxconn value is not yet
1288 * set. It may also return a value greater than maxconn if it's not yet set.
1289 * Note that a value of zero means there is no need for pipes. -1 is never
1290 * returned if global.maxconn is valid.
1291 */
1292static int compute_ideal_maxpipes()
1293{
1294 struct proxy *cur;
1295 int nbfe = 0, nbbe = 0;
1296 int unlimited = 0;
1297 int pipes;
1298 int max;
1299
1300 for (cur = proxies_list; cur; cur = cur->next) {
1301 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1302 if (cur->cap & PR_CAP_FE) {
1303 max = cur->maxconn;
1304 nbfe += max;
1305 if (!max) {
1306 unlimited = 1;
1307 break;
1308 }
1309 }
1310 if (cur->cap & PR_CAP_BE) {
1311 max = cur->fullconn ? cur->fullconn : global.maxconn;
1312 nbbe += max;
1313 if (!max) {
1314 unlimited = 1;
1315 break;
1316 }
1317 }
1318 }
1319 }
1320
1321 pipes = MAX(nbfe, nbbe);
1322 if (global.maxconn) {
1323 if (pipes > global.maxconn || unlimited)
1324 pipes = global.maxconn;
1325 } else if (unlimited) {
1326 pipes = -1;
1327 }
1328
1329 return pipes >= 4 ? pipes / 4 : pipes;
1330}
1331
Willy Tarreauac350932019-03-01 15:43:14 +01001332/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1333 * rlimits and computes an ideal maxconn. It's meant to be called only when
1334 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001335 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1336 * default 100) is returned as it is expected that it will even run on tight
1337 * environments, and will maintain compatibility with previous packages that
1338 * used to rely on this value as the default one. The system will emit a
1339 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001340 */
1341static int compute_ideal_maxconn()
1342{
1343 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1344 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1345 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001346 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001347 int maxconn;
1348
1349 /* we have to take into account these elements :
1350 * - number of engine_fds, which inflates the number of FD needed per
1351 * connection by this number.
1352 * - number of pipes per connection on average : for the unlimited
1353 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1354 * fixed value of 2*pipes.
1355 * - two FDs per connection
1356 */
1357
1358 /* subtract listeners and checks */
1359 remain -= global.maxsock;
1360
Willy Tarreau3f200852019-03-14 19:13:17 +01001361 /* one epoll_fd/kqueue_fd per thread */
1362 remain -= global.nbthread;
1363
1364 /* one wake-up pipe (2 fd) per thread */
1365 remain -= 2 * global.nbthread;
1366
Willy Tarreauac350932019-03-01 15:43:14 +01001367 /* Fixed pipes values : we only subtract them if they're not larger
1368 * than the remaining FDs because pipes are optional.
1369 */
1370 if (pipes >= 0 && pipes * 2 < remain)
1371 remain -= pipes * 2;
1372
1373 if (pipes < 0) {
1374 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1375 * = maxconn * (2 + 0.5 + engine_fds)
1376 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1377 */
1378 maxconn = 2 * remain / (5 + 2 * engine_fds);
1379 } else {
1380 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1381 * = maxconn * (2 + engine_fds)
1382 */
1383 maxconn = remain / (2 + engine_fds);
1384 }
1385
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001386 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001387}
1388
Willy Tarreaua409f302020-03-10 17:08:53 +01001389/* computes the estimated maxsock value for the given maxconn based on the
1390 * possibly set global.maxpipes and existing partial global.maxsock. It may
1391 * temporarily change global.maxconn for the time needed to propagate the
1392 * computations, and will reset it.
1393 */
1394static int compute_ideal_maxsock(int maxconn)
1395{
1396 int maxpipes = global.maxpipes;
1397 int maxsock = global.maxsock;
1398
1399
1400 if (!maxpipes) {
1401 int old_maxconn = global.maxconn;
1402
1403 global.maxconn = maxconn;
1404 maxpipes = compute_ideal_maxpipes();
1405 global.maxconn = old_maxconn;
1406 }
1407
1408 maxsock += maxconn * 2; /* each connection needs two sockets */
1409 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1410 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1411 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1412
1413 /* compute fd used by async engines */
1414 if (global.ssl_used_async_engines) {
1415 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1416
1417 maxsock += maxconn * sides * global.ssl_used_async_engines;
1418 }
1419 return maxsock;
1420}
1421
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001422/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001423 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1424 * value is accepted, non-zero otherwise. This is used to determine if an
1425 * automatic limit may be applied or not. When it is not, the caller knows that
1426 * the highest we can do is the rlim_max at boot. In case of error, we return
1427 * that the setting is possible, so that we defer the error processing to the
1428 * final stage in charge of enforcing this.
1429 */
1430static int check_if_maxsock_permitted(int maxsock)
1431{
1432 struct rlimit orig_limit, test_limit;
1433 int ret;
1434
1435 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1436 return 1;
1437
1438 /* don't go further if we can't even set to what we have */
1439 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1440 return 1;
1441
1442 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1443 test_limit.rlim_cur = test_limit.rlim_max;
1444 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1445
1446 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1447 return 1;
1448
1449 return ret == 0;
1450}
1451
Amaury Denoyelle484454d2021-05-05 16:18:45 +02001452void mark_tainted(const enum tainted_flags flag)
1453{
1454 HA_ATOMIC_OR(&tainted, flag);
1455}
1456
1457unsigned int get_tainted()
1458{
1459 int tainted_state;
1460 HA_ATOMIC_STORE(&tainted_state, tainted);
1461 return tainted_state;
1462}
Willy Tarreau304e17e2020-03-10 17:54:54 +01001463
William Lallemand73b85e72017-06-01 17:38:51 +02001464/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02001465 * This function initializes all the necessary variables. It only returns
1466 * if everything is OK. If something fails, it exits.
1467 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001468static void init(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001469{
Willy Tarreaubaaee002006-06-26 02:48:02 +02001470 int arg_mode = 0; /* MODE_DEBUG, ... */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001471 char *tmp;
1472 char *cfg_pidfile = NULL;
Willy Tarreau058e9072009-07-20 09:30:05 +02001473 int err_code = 0;
Maxime de Roucy0f503922016-05-13 23:52:55 +02001474 char *err_msg = NULL;
Willy Tarreau477ecd82010-01-03 21:12:30 +01001475 struct wordlist *wl;
Kevinm48936af2010-12-22 16:08:21 +00001476 char *progname;
Willy Tarreau576132e2011-09-10 19:26:56 +02001477 char *change_dir = NULL;
Christopher Fauletd7c91962015-04-30 11:48:27 +02001478 struct proxy *px;
Willy Tarreaue6945732016-12-21 19:57:00 +01001479 struct post_check_fct *pcf;
Willy Tarreauac350932019-03-01 15:43:14 +01001480 int ideal_maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481
William Lallemanda48f51b2023-02-21 14:07:05 +01001482 setenv("HAPROXY_STARTUP_VERSION", HAPROXY_VERSION, 0);
Christopher Faulete3a5e352017-10-24 13:53:54 +02001483 global.mode = MODE_STARTING;
William Lallemand00417412020-06-05 14:08:41 +02001484 old_argv = copy_argv(argc, argv);
1485 if (!old_argv) {
William Lallemanddf6c5a82020-06-04 17:40:23 +02001486 ha_alert("failed to copy argv.\n");
1487 exit(1);
1488 }
William Lallemand73b85e72017-06-01 17:38:51 +02001489
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001490 if (!init_trash_buffers(1)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001491 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet748919a2017-07-26 14:59:46 +02001492 exit(1);
1493 }
David du Colombier7af46052012-05-16 14:16:48 +02001494
Emeric Brun2b920a12010-09-23 18:30:22 +02001495 /* NB: POSIX does not make it mandatory for gethostname() to NULL-terminate
1496 * the string in case of truncation, and at least FreeBSD appears not to do
1497 * it.
1498 */
1499 memset(hostname, 0, sizeof(hostname));
1500 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001501
1502 if ((localpeer = strdup(hostname)) == NULL) {
1503 ha_alert("Cannot allocate memory for local peer.\n");
1504 exit(EXIT_FAILURE);
1505 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001506 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Emeric Brun2b920a12010-09-23 18:30:22 +02001507
William Lallemand24c928c2020-01-14 17:58:18 +01001508 /* we were in mworker mode, we should restart in mworker mode */
1509 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1510 global.mode |= MODE_MWORKER;
1511
Willy Tarreaubaaee002006-06-26 02:48:02 +02001512 /*
1513 * Initialize the previously static variables.
1514 */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001515
Willy Tarreau173d9952018-01-26 21:48:23 +01001516 totalconn = actconn = listeners = stopping = 0;
Cyril Bonté203ec5a2017-03-23 22:44:13 +01001517 killed = 0;
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001518
Willy Tarreaubaaee002006-06-26 02:48:02 +02001519
1520#ifdef HAPROXY_MEMMAX
Willy Tarreau70060452015-12-14 12:46:07 +01001521 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001522#endif
1523
Benoit GARNIERb413c2a2016-03-27 11:08:03 +02001524 tzset();
Willy Tarreauc4c80fb2021-04-11 15:00:34 +02001525 tv_init_process_date();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001526 start_date = now;
1527
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001528 ha_random_boot(argv);
Willy Tarreau84310e22014-02-14 11:59:04 +01001529
Willy Tarreau8ed669b2013-01-11 15:49:37 +01001530 if (init_acl() != 0)
1531 exit(1);
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001532
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001533 /* Initialise lua. */
1534 hlua_init();
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001535
Christopher Fauletff2613e2016-11-09 11:36:17 +01001536 /* Initialize process vars */
Willy Tarreaucfc4f242021-05-08 11:41:28 +02001537 vars_init(&proc_vars, SCOPE_PROC);
Christopher Fauletff2613e2016-11-09 11:36:17 +01001538
Willy Tarreau43b78992009-01-25 15:42:27 +01001539 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001540#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001541 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001542#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001543#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001544 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001545#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001546#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001547 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001548#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001549#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001550 global.tune.options |= GTUNE_USE_EVPORTS;
1551#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001552#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001553 global.tune.options |= GTUNE_USE_SPLICE;
1554#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001555#if defined(USE_GETADDRINFO)
1556 global.tune.options |= GTUNE_USE_GAI;
1557#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001558#if defined(SO_REUSEPORT)
1559 global.tune.options |= GTUNE_USE_REUSEPORT;
1560#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001561#ifdef USE_THREAD
1562 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1563#endif
William Dauchya5194602020-03-28 19:29:58 +01001564 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565
1566 pid = getpid();
1567 progname = *argv;
1568 while ((tmp = strchr(progname, '/')) != NULL)
1569 progname = tmp + 1;
1570
Kevinm48936af2010-12-22 16:08:21 +00001571 /* the process name is used for the logs only */
Eric Salama7cea6062020-10-02 11:58:19 +02001572 chunk_initlen(&global.log_tag, strdup(progname), strlen(progname), strlen(progname));
1573 if (b_orig(&global.log_tag) == NULL) {
1574 chunk_destroy(&global.log_tag);
1575 ha_alert("Cannot allocate memory for log_tag.\n");
1576 exit(EXIT_FAILURE);
1577 }
Kevinm48936af2010-12-22 16:08:21 +00001578
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579 argc--; argv++;
1580 while (argc > 0) {
1581 char *flag;
1582
1583 if (**argv == '-') {
1584 flag = *argv+1;
1585
1586 /* 1 arg */
1587 if (*flag == 'v') {
1588 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001589 if (flag[1] == 'v') /* -vv */
1590 display_build_opts();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591 exit(0);
1592 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001593#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001595 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001597#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001598 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001599 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001600#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001601#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001602 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001603 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001604#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001605#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001606 else if (*flag == 'd' && flag[1] == 'v')
1607 global.tune.options &= ~GTUNE_USE_EVPORTS;
1608#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001609#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001610 else if (*flag == 'd' && flag[1] == 'S')
1611 global.tune.options &= ~GTUNE_USE_SPLICE;
1612#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001613#if defined(USE_GETADDRINFO)
1614 else if (*flag == 'd' && flag[1] == 'G')
1615 global.tune.options &= ~GTUNE_USE_GAI;
1616#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001617#if defined(SO_REUSEPORT)
1618 else if (*flag == 'd' && flag[1] == 'R')
1619 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1620#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001621 else if (*flag == 'd' && flag[1] == 'V')
1622 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623 else if (*flag == 'V')
1624 arg_mode |= MODE_VERBOSE;
1625 else if (*flag == 'd' && flag[1] == 'b')
1626 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001627 else if (*flag == 'd' && flag[1] == 'D')
1628 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001629 else if (*flag == 'd' && flag[1] == 'W')
1630 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreau6e064432012-05-08 15:40:42 +02001631 else if (*flag == 'd' && flag[1] == 'M')
1632 mem_poison_byte = flag[2] ? strtol(flag + 2, NULL, 0) : 'P';
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001633 else if (*flag == 'd' && flag[1] == 'r')
1634 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreau0aa9dbe2021-12-28 15:43:11 +01001635#if defined(HA_HAVE_DUMP_LIBS)
1636 else if (*flag == 'd' && flag[1] == 'L')
1637 arg_mode |= MODE_DUMP_LIBS;
1638#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001639 else if (*flag == 'd')
1640 arg_mode |= MODE_DEBUG;
1641 else if (*flag == 'c')
1642 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001643 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001644 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001645 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001646 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001647#if defined(USE_SYSTEMD)
1648 global.tune.options |= GTUNE_USE_SYSTEMD;
1649#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001650 ha_alert("master-worker mode with systemd support (-Ws) requested, but not compiled. Use master-worker mode (-W) if you are not using Type=notify in your unit file or recompile with USE_SYSTEMD=1.\n\n");
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001651 usage(progname);
1652#endif
1653 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001654 else if (*flag == 'W')
1655 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 else if (*flag == 'q')
1657 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001658 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001659 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001660 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001661 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001662 }
William Lallemand4fc09692017-06-19 16:37:19 +02001663 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001664 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001665 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001666
Willy Tarreau7b11b7e2022-02-01 08:47:41 +01001667 /* preset it now for early aborts */
1668 free(cur_unixsocket);
1669 cur_unixsocket = strdup(old_unixsocket);
1670
Olivier Houchardf73629d2017-04-05 22:33:04 +02001671 argv++;
1672 argc--;
1673 }
William Lallemande7361152018-10-26 14:47:36 +02001674 else if (*flag == 'S') {
1675 struct wordlist *c;
1676
William Lallemanda6b32492020-06-04 23:49:20 +02001677 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001678 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1679 usage(progname);
1680 }
1681 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1682 ha_alert("Cannot allocate memory\n");
1683 exit(EXIT_FAILURE);
1684 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001685 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001686
1687 argv++;
1688 argc--;
1689 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001690 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1691 /* list of pids to finish ('f') or terminate ('t') */
1692
1693 if (flag[1] == 'f')
1694 oldpids_sig = SIGUSR1; /* finish then exit */
1695 else
1696 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001697 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001698 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001699 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1700 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001701 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001702 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001703 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001704 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001705 errno = 0;
1706 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1707 if (errno) {
1708 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1709 flag,
1710 *argv, strerror(errno));
1711 exit(1);
1712 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001713 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001714 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001715 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1716 flag, endptr);
1717 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001718 }
Chris Lane236062f2018-02-05 23:15:44 +00001719 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001720 if (oldpids[nb_oldpids] <= 0)
1721 usage(progname);
1722 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001723 }
1724 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001725 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1726 /* now that's a cfgfile list */
1727 argv++; argc--;
1728 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001729 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001730 ha_alert("Cannot load configuration file/directory %s : %s\n",
1731 *argv,
1732 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001733 exit(1);
1734 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001735 argv++; argc--;
1736 }
1737 break;
1738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001739 else { /* >=2 args */
1740 argv++; argc--;
1741 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001742 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001743
1744 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001745 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001746 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001747 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001748 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001749 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001750 free(localpeer);
1751 if ((localpeer = strdup(*argv)) == NULL) {
1752 ha_alert("Cannot allocate memory for local peer.\n");
1753 exit(EXIT_FAILURE);
1754 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001755 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001756 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001757 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001758 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001759 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001760 ha_alert("Cannot load configuration file/directory %s : %s\n",
1761 *argv,
1762 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001763 exit(1);
1764 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001765 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001766 case 'p' : cfg_pidfile = *argv; break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001767 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001768 }
1769 }
1770 }
1771 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001772 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001773 argv++; argc--;
1774 }
1775
Christopher Faulete3a5e352017-10-24 13:53:54 +02001776 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001777 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Willy Tarreau0aa9dbe2021-12-28 15:43:11 +01001778 | MODE_DIAG | MODE_DUMP_LIBS));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001779
William Lallemand944e6192018-11-21 15:48:31 +01001780 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001781 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001782 global.mode |= MODE_MWORKER_WAIT;
1783 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001784 }
1785
Willy Tarreau7a534eb2021-07-21 10:01:36 +02001786 if ((global.mode & (MODE_MWORKER | MODE_CHECK)) == MODE_MWORKER &&
1787 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001788 atexit_flag = 1;
1789 atexit(reexec_on_failure);
1790 }
1791
Willy Tarreau576132e2011-09-10 19:26:56 +02001792 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001793 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001794 exit(1);
1795 }
1796
Willy Tarreaubaaee002006-06-26 02:48:02 +02001797 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001798
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001799#ifdef USE_CPU_AFFINITY
1800 {
1801 int i;
1802 for (i = 0; i < MAX_PROCS; ++i) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02001803 ha_cpuset_zero(&cpu_map.proc[i]);
1804 ha_cpuset_zero(&cpu_map.proc_t1[i]);
Willy Tarreau26f42a02021-05-14 08:26:38 +02001805 }
1806 for (i = 0; i < MAX_THREADS; ++i) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02001807 ha_cpuset_zero(&cpu_map.thread[i]);
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001808 }
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001809 }
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001810#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001811
William Lallemand944e6192018-11-21 15:48:31 +01001812 /* in wait mode, we don't try to read the configuration files */
1813 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001814 char *env_cfgfiles = NULL;
1815 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001816
William Lallemand944e6192018-11-21 15:48:31 +01001817 /* handle cfgfiles that are actually directories */
1818 cfgfiles_expand_directories();
1819
1820 if (LIST_ISEMPTY(&cfg_cfgfiles))
1821 usage(progname);
1822
1823
1824 list_for_each_entry(wl, &cfg_cfgfiles, list) {
1825 int ret;
1826
Christopher Faulet4e366822021-01-12 18:57:38 +01001827 if (env_err == 0) {
1828 if (!memprintf(&env_cfgfiles, "%s%s%s",
1829 (env_cfgfiles ? env_cfgfiles : ""),
1830 (env_cfgfiles ? ";" : ""), wl->s))
1831 env_err = 1;
1832 }
William Lallemand7b302d82019-05-20 11:15:37 +02001833
William Lallemand944e6192018-11-21 15:48:31 +01001834 ret = readcfgfile(wl->s);
1835 if (ret == -1) {
1836 ha_alert("Could not open configuration file %s : %s\n",
1837 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01001838 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001839 exit(1);
1840 }
1841 if (ret & (ERR_ABORT|ERR_FATAL))
1842 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
1843 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01001844 if (err_code & ERR_ABORT) {
1845 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001846 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01001847 }
Willy Tarreauc4382422009-12-06 13:10:44 +01001848 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001849
William Lallemand944e6192018-11-21 15:48:31 +01001850 /* do not try to resolve arguments nor to spot inconsistencies when
1851 * the configuration contains fatal errors caused by files not found
1852 * or failed memory allocations.
1853 */
1854 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1855 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01001856 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001857 exit(1);
1858 }
Christopher Faulet4e366822021-01-12 18:57:38 +01001859 if (env_err) {
1860 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
1861 exit(1);
1862 }
1863 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
1864 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02001865
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02001866 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001867 if (global.mode & MODE_MWORKER) {
1868 int proc;
William Lallemand16dd1b32018-11-19 18:46:18 +01001869 struct mworker_proc *tmproc;
1870
William Lallemand482f9a92019-04-12 16:15:00 +02001871 setenv("HAPROXY_MWORKER", "1", 1);
1872
William Lallemand16dd1b32018-11-19 18:46:18 +01001873 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
1874
William Lallemandf3a86832019-04-01 11:29:58 +02001875 tmproc = calloc(1, sizeof(*tmproc));
William Lallemand16dd1b32018-11-19 18:46:18 +01001876 if (!tmproc) {
1877 ha_alert("Cannot allocate process structures.\n");
1878 exit(EXIT_FAILURE);
1879 }
William Lallemand8f7069a2019-04-12 16:09:23 +02001880 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01001881 tmproc->reloads = 0;
1882 tmproc->relative_pid = 0;
1883 tmproc->pid = pid;
1884 tmproc->timestamp = start_date.tv_sec;
1885 tmproc->ipc_fd[0] = -1;
1886 tmproc->ipc_fd[1] = -1;
1887
1888 proc_self = tmproc;
1889
Willy Tarreau2b718102021-04-21 07:32:39 +02001890 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01001891 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001892
1893 for (proc = 0; proc < global.nbproc; proc++) {
William Lallemandce83b4a2018-10-26 14:47:30 +02001894
William Lallemandf3a86832019-04-01 11:29:58 +02001895 tmproc = calloc(1, sizeof(*tmproc));
William Lallemandce83b4a2018-10-26 14:47:30 +02001896 if (!tmproc) {
1897 ha_alert("Cannot allocate process structures.\n");
1898 exit(EXIT_FAILURE);
1899 }
1900
William Lallemand8f7069a2019-04-12 16:09:23 +02001901 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
William Lallemandce83b4a2018-10-26 14:47:30 +02001902 tmproc->pid = -1;
1903 tmproc->reloads = 0;
William Lallemande3683302018-11-19 18:46:17 +01001904 tmproc->timestamp = -1;
William Lallemandce83b4a2018-10-26 14:47:30 +02001905 tmproc->relative_pid = 1 + proc;
William Lallemand550db6d2018-11-06 17:37:12 +01001906 tmproc->ipc_fd[0] = -1;
1907 tmproc->ipc_fd[1] = -1;
William Lallemandce83b4a2018-10-26 14:47:30 +02001908
1909 if (mworker_cli_sockpair_new(tmproc, proc) < 0) {
1910 exit(EXIT_FAILURE);
1911 }
1912
Willy Tarreau2b718102021-04-21 07:32:39 +02001913 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemandce83b4a2018-10-26 14:47:30 +02001914 }
William Lallemand944e6192018-11-21 15:48:31 +01001915 }
1916 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
1917 struct wordlist *it, *c;
1918
Remi Tricot-Le Bretond90aa342021-05-19 10:45:12 +02001919 /* get the info of the children in the env */
1920 if (mworker_env_to_proc_list() < 0) {
1921 exit(EXIT_FAILURE);
1922 }
William Lallemande7361152018-10-26 14:47:36 +02001923
William Lallemand550db6d2018-11-06 17:37:12 +01001924 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02001925
William Lallemand550db6d2018-11-06 17:37:12 +01001926 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02001927 ha_alert("Can't create the master's CLI.\n");
1928 exit(EXIT_FAILURE);
1929 }
William Lallemande7361152018-10-26 14:47:36 +02001930
William Lallemand550db6d2018-11-06 17:37:12 +01001931 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
1932
1933 if (mworker_cli_proxy_new_listener(c->s) < 0) {
1934 ha_alert("Can't create the master's CLI.\n");
1935 exit(EXIT_FAILURE);
1936 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001937 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01001938 free(c->s);
1939 free(c);
1940 }
1941 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001942 }
1943
Eric Salama5ba83352021-03-16 15:11:17 +01001944 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
1945 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
1946 }
1947
Willy Tarreauf42d7942020-10-20 11:54:49 +02001948 if (global.nbproc > 1 && !global.nbthread) {
1949 ha_warning("nbproc is deprecated!\n"
1950 " | For suffering many limitations, the 'nbproc' directive is now deprecated\n"
1951 " | and scheduled for removal in 2.5. Just comment it out: haproxy will use\n"
1952 " | threads and will run on all allocated processors. You may also switch to\n"
1953 " | 'nbthread %d' to keep the same number of processors. If you absolutely\n"
1954 " | want to run in multi-process mode, you can silence this warning by adding\n"
1955 " | 'nbthread 1', but then please report your use case to developers.\n",
1956 global.nbproc);
1957 }
1958
Willy Tarreaue90904d2021-02-12 14:08:31 +01001959 /* defaults sections are not needed anymore */
1960 proxy_destroy_all_defaults();
1961
Willy Tarreauc690ca42023-05-17 09:02:21 +02001962 /* update the ready date that will be used to count the startup time
1963 * during config checks (e.g. to schedule certain tasks if needed)
1964 */
Willy Tarreauef0d92d2023-05-17 15:15:26 +02001965 gettimeofday(&date, NULL);
Willy Tarreauc690ca42023-05-17 09:02:21 +02001966 ready_date = date;
1967
1968 /* Note: global.nbthread will be initialized as part of this call */
Willy Tarreaubb925012009-07-23 13:36:36 +02001969 err_code |= check_config_validity();
Willy Tarreauc690ca42023-05-17 09:02:21 +02001970
1971 /* update the ready date to also account for the check time */
Willy Tarreauef0d92d2023-05-17 15:15:26 +02001972 gettimeofday(&date, NULL);
Willy Tarreauc690ca42023-05-17 09:02:21 +02001973 ready_date = date;
1974
Christopher Fauletc1692962019-08-12 09:51:07 +02001975 for (px = proxies_list; px; px = px->next) {
1976 struct server *srv;
1977 struct post_proxy_check_fct *ppcf;
1978 struct post_server_check_fct *pscf;
1979
Christopher Fauletd5bd8242020-11-02 16:20:13 +01001980 if (px->disabled)
1981 continue;
1982
Christopher Fauletc1692962019-08-12 09:51:07 +02001983 list_for_each_entry(pscf, &post_server_check_list, list) {
1984 for (srv = px->srv; srv; srv = srv->next)
1985 err_code |= pscf->fct(srv);
1986 }
1987 list_for_each_entry(ppcf, &post_proxy_check_list, list)
1988 err_code |= ppcf->fct(px);
1989 }
Willy Tarreaubb925012009-07-23 13:36:36 +02001990 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001991 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001992 exit(1);
1993 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001994
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01001995 err_code |= pattern_finalize_config();
1996 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1997 ha_alert("Failed to finalize pattern config.\n");
1998 exit(1);
1999 }
Willy Tarreau0f936722019-04-11 14:47:08 +02002000
Willy Tarreau70060452015-12-14 12:46:07 +01002001 /* recompute the amount of per-process memory depending on nbproc and
2002 * the shared SSL cache size (allowed to exist in all processes).
2003 */
2004 if (global.rlimit_memmax_all) {
2005#if defined (USE_OPENSSL) && !defined(USE_PRIVATE_CACHE)
2006 int64_t ssl_cache_bytes = global.tune.sslcachesize * 200LL;
2007
2008 global.rlimit_memmax =
2009 ((((int64_t)global.rlimit_memmax_all * 1048576LL) -
2010 ssl_cache_bytes) / global.nbproc +
2011 ssl_cache_bytes + 1048575LL) / 1048576LL;
2012#else
2013 global.rlimit_memmax = global.rlimit_memmax_all / global.nbproc;
2014#endif
2015 }
2016
Willy Tarreaue5733232019-05-22 19:24:06 +02002017#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002018 err_code |= netns_init();
2019 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002020 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01002021 exit(1);
2022 }
2023#endif
2024
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002025 /* Apply server states */
2026 apply_server_state();
2027
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002028 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002029 srv_compute_all_admin_states(px);
2030
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002031 /* Apply servers' configured address */
2032 err_code |= srv_init_addr();
2033 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002034 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002035 exit(1);
2036 }
2037
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002038 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2039 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2040 exit(1);
2041 }
2042
Willy Tarreau0aa9dbe2021-12-28 15:43:11 +01002043#if defined(HA_HAVE_DUMP_LIBS)
2044 if (global.mode & MODE_DUMP_LIBS) {
2045 qfprintf(stdout, "List of loaded object files:\n");
2046 chunk_reset(&trash);
2047 if (dump_libs(&trash, 0))
2048 printf("%s", trash.area);
2049 }
2050#endif
2051
Willy Tarreaubaaee002006-06-26 02:48:02 +02002052 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002053 struct peers *pr;
2054 struct proxy *px;
2055
Willy Tarreaubebd2122020-04-15 16:06:11 +02002056 if (warned & WARN_ANY)
2057 qfprintf(stdout, "Warnings were found.\n");
2058
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002059 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002060 if (pr->peers_fe)
2061 break;
2062
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002063 for (px = proxies_list; px; px = px->next)
Willy Tarreauc3914d42020-09-24 08:39:22 +02002064 if (!px->disabled && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002065 break;
2066
Emeric Brun3a9c0002021-08-13 09:32:50 +02002067 if (!px) {
2068 /* We may only have log-forward section */
2069 for (px = cfg_log_forward; px; px = px->next)
2070 if (!px->disabled && px->li_all)
2071 break;
2072 }
2073
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002074 if (pr || px) {
2075 /* At least one peer or one listener has been found */
2076 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002077 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002078 }
2079 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2080 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002081 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002082
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002083 if (global.mode & MODE_DIAG) {
2084 cfg_run_diagnostics();
2085 }
2086
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002087 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002088 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002089
Willy Tarreaue6945732016-12-21 19:57:00 +01002090 list_for_each_entry(pcf, &post_check_list, list) {
2091 err_code |= pcf->fct();
2092 if (err_code & (ERR_ABORT|ERR_FATAL))
2093 exit(1);
2094 }
2095
William Lallemande9eb2492022-06-21 11:11:50 +02002096 /* set the default maxconn in the master, but let it be rewritable with -n */
2097 if (global.mode & MODE_MWORKER_WAIT)
2098 global.maxconn = DEFAULT_MAXCONN;
2099
Willy Tarreaubaaee002006-06-26 02:48:02 +02002100 if (cfg_maxconn > 0)
2101 global.maxconn = cfg_maxconn;
2102
Willy Tarreau4975d142021-03-13 11:00:33 +01002103 if (global.cli_fe)
2104 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002105
2106 if (cfg_peers) {
2107 /* peers also need to bypass global maxconn */
2108 struct peers *p = cfg_peers;
2109
2110 for (p = cfg_peers; p; p = p->next)
2111 if (p->peers_fe)
2112 global.maxsock += p->peers_fe->maxconn;
2113 }
2114
Willy Tarreaubaaee002006-06-26 02:48:02 +02002115 if (cfg_pidfile) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002116 free(global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002117 global.pidfile = strdup(cfg_pidfile);
2118 }
2119
Willy Tarreaud0256482015-01-15 21:45:22 +01002120 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002121 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2122 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2123 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2124 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002125 *
2126 * If memmax is set, then it depends on which values are set. If
2127 * maxsslconn is set, we use memmax to determine how many cleartext
2128 * connections may be added, and set maxconn to the sum of the two.
2129 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2130 * the remaining amount of memory between memmax and the cleartext
2131 * connections. If neither are set, then it is considered that all
2132 * connections are SSL-capable, and maxconn is computed based on this,
2133 * then maxsslconn accordingly. We need to know if SSL is used on the
2134 * frontends, backends, or both, because when it's used on both sides,
2135 * we need twice the value for maxsslconn, but we only count the
2136 * handshake once since it is not performed on the two sides at the
2137 * same time (frontend-side is terminated before backend-side begins).
2138 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002139 * ssl_handshake_cost during its initialization. In any case, if
2140 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2141 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002142 */
Willy Tarreauac350932019-03-01 15:43:14 +01002143 ideal_maxconn = compute_ideal_maxconn();
2144
Willy Tarreaud0256482015-01-15 21:45:22 +01002145 if (!global.rlimit_memmax) {
2146 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002147 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002148 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2149 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2150 }
2151 }
2152#ifdef USE_OPENSSL
2153 else if (!global.maxconn && !global.maxsslconn &&
2154 (global.ssl_used_frontend || global.ssl_used_backend)) {
2155 /* memmax is set, compute everything automatically. Here we want
2156 * to ensure that all SSL connections will be served. We take
2157 * care of the number of sides where SSL is used, and consider
2158 * the worst case : SSL used on both sides and doing a handshake
2159 * simultaneously. Note that we can't have more than maxconn
2160 * handshakes at a time by definition, so for the worst case of
2161 * two SSL conns per connection, we count a single handshake.
2162 */
2163 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2164 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002165 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002166
2167 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2168 mem -= global.maxzlibmem;
2169 mem = mem * MEM_USABLE_RATIO;
2170
Willy Tarreau304e17e2020-03-10 17:54:54 +01002171 /* Principle: we test once to set maxconn according to the free
2172 * memory. If it results in values the system rejects, we try a
2173 * second time by respecting rlim_fd_max. If it fails again, we
2174 * go back to the initial value and will let the final code
2175 * dealing with rlimit report the error. That's up to 3 attempts.
2176 */
2177 do {
2178 global.maxconn = mem /
2179 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2180 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2181 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002182
Willy Tarreau304e17e2020-03-10 17:54:54 +01002183 if (retried == 1)
2184 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2185 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002186#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002187 if (global.maxconn > SYSTEM_MAXCONN)
2188 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002189#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002190 global.maxsslconn = sides * global.maxconn;
2191
2192 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2193 break;
2194 } while (retried++ < 2);
2195
Willy Tarreaud0256482015-01-15 21:45:22 +01002196 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2197 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2198 global.maxconn, global.maxsslconn);
2199 }
2200 else if (!global.maxsslconn &&
2201 (global.ssl_used_frontend || global.ssl_used_backend)) {
2202 /* memmax and maxconn are known, compute maxsslconn automatically.
2203 * maxsslconn being forced, we don't know how many of it will be
2204 * on each side if both sides are being used. The worst case is
2205 * when all connections use only one SSL instance because
2206 * handshakes may be on two sides at the same time.
2207 */
2208 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2209 int64_t mem = global.rlimit_memmax * 1048576ULL;
2210 int64_t sslmem;
2211
2212 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2213 mem -= global.maxzlibmem;
2214 mem = mem * MEM_USABLE_RATIO;
2215
Willy Tarreau87b09662015-04-03 00:22:06 +02002216 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002217 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2218 global.maxsslconn = round_2dig(global.maxsslconn);
2219
2220 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002221 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2222 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2223 "without SSL is %d, but %d was found and SSL is in use.\n",
2224 global.rlimit_memmax,
2225 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2226 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002227 exit(1);
2228 }
2229
2230 if (global.maxsslconn > sides * global.maxconn)
2231 global.maxsslconn = sides * global.maxconn;
2232
2233 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2234 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2235 }
2236#endif
2237 else if (!global.maxconn) {
2238 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2239 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2240 int64_t mem = global.rlimit_memmax * 1048576ULL;
2241 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002242 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002243
2244 if (global.ssl_used_frontend || global.ssl_used_backend)
2245 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2246
2247 mem -= global.maxzlibmem;
2248 mem = mem * MEM_USABLE_RATIO;
2249
2250 clearmem = mem;
2251 if (sides)
2252 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2253
Willy Tarreau304e17e2020-03-10 17:54:54 +01002254 /* Principle: we test once to set maxconn according to the free
2255 * memory. If it results in values the system rejects, we try a
2256 * second time by respecting rlim_fd_max. If it fails again, we
2257 * go back to the initial value and will let the final code
2258 * dealing with rlimit report the error. That's up to 3 attempts.
2259 */
2260 do {
2261 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2262 if (retried == 1)
2263 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2264 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002265#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002266 if (global.maxconn > SYSTEM_MAXCONN)
2267 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002268#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002269
Willy Tarreau304e17e2020-03-10 17:54:54 +01002270 if (clearmem <= 0 || !global.maxconn) {
2271 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2272 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2273 "is %d, but %d was found.\n",
2274 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002275 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002276 global.maxsslconn);
2277 exit(1);
2278 }
2279
2280 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2281 break;
2282 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002283
2284 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2285 if (sides && global.maxsslconn > sides * global.maxconn) {
2286 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2287 "to be limited to %d. Better reduce global.maxsslconn to get more "
2288 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2289 }
2290 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2291 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002292 }
2293
Willy Tarreaua409f302020-03-10 17:08:53 +01002294 global.maxsock = compute_ideal_maxsock(global.maxconn);
2295 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002296 if (!global.maxpipes)
2297 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298
Olivier Houchard88698d92019-04-16 19:07:22 +02002299 /* update connection pool thresholds */
2300 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2301 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2302
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002303 proxy_adjust_all_maxconn();
2304
Willy Tarreau1db37712007-06-03 17:16:49 +02002305 if (global.tune.maxpollevents <= 0)
2306 global.tune.maxpollevents = MAX_POLL_EVENTS;
2307
Willy Tarreau060a7612021-03-10 11:06:26 +01002308 if (global.tune.runqueue_depth <= 0) {
2309 /* tests on various thread counts from 1 to 64 have shown an
2310 * optimal queue depth following roughly 1/sqrt(threads).
2311 */
2312 int s = my_flsl(global.nbthread);
2313 s += (global.nbthread / s); // roughly twice the sqrt.
2314 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2315 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002316
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002317 if (global.tune.recv_enough == 0)
2318 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2319
Willy Tarreau27a674e2009-08-17 07:23:33 +02002320 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2321 global.tune.maxrewrite = global.tune.bufsize / 2;
2322
Willy Tarreaubaaee002006-06-26 02:48:02 +02002323 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2324 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002325 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002326 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2327 }
2328
William Lallemand095ba4c2017-06-01 17:38:50 +02002329 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002330 /* command line daemon mode inhibits foreground and debug modes mode */
2331 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002332 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002333 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002334
2335 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002336
William Lallemand095ba4c2017-06-01 17:38:50 +02002337 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002338 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002339 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002340 }
2341
William Lallemand095ba4c2017-06-01 17:38:50 +02002342 if ((global.nbproc > 1) && !(global.mode & (MODE_DAEMON | MODE_MWORKER))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002343 if (!(global.mode & (MODE_FOREGROUND | MODE_DEBUG)))
Christopher Faulet767a84b2017-11-24 16:50:31 +01002344 ha_warning("<nbproc> is only meaningful in daemon mode or master-worker mode. Setting limit to 1 process.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02002345 global.nbproc = 1;
2346 }
2347
2348 if (global.nbproc < 1)
2349 global.nbproc = 1;
2350
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002351 if (global.nbthread < 1)
2352 global.nbthread = 1;
2353
Christopher Faulet3ef26392017-08-29 16:46:57 +02002354 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002355 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002356 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002357 exit(1);
2358 }
2359
Christopher Faulet96d44832017-11-14 22:02:30 +01002360 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002361 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002362 exit(1);
2363 }
2364
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002365 /*
2366 * Note: we could register external pollers here.
2367 * Built-in pollers have been registered before main().
2368 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002369
Willy Tarreau43b78992009-01-25 15:42:27 +01002370 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002371 disable_poller("kqueue");
2372
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002373 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2374 disable_poller("evports");
2375
Willy Tarreau43b78992009-01-25 15:42:27 +01002376 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002377 disable_poller("epoll");
2378
Willy Tarreau43b78992009-01-25 15:42:27 +01002379 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002380 disable_poller("poll");
2381
Willy Tarreau43b78992009-01-25 15:42:27 +01002382 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002383 disable_poller("select");
2384
2385 /* Note: we could disable any poller by name here */
2386
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002387 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002388 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002389 fprintf(stderr, "\n");
2390 list_filters(stderr);
2391 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002392
Willy Tarreau4f60f162007-04-08 16:39:58 +02002393 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002394 ha_alert("No polling mechanism available.\n"
2395 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2396 " is too low on this platform to support maxconn and the number of listeners\n"
2397 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2398 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2399 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2400 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2401 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2402 " check build settings using 'haproxy -vv'.\n\n",
2403 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002404 exit(1);
2405 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002406 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2407 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002408 }
2409
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002410 if (!global.node)
2411 global.node = strdup(hostname);
2412
Willy Tarreau02b092f2020-10-07 18:36:54 +02002413 /* stop disabled proxies */
2414 for (px = proxies_list; px; px = px->next) {
Willy Tarreauc3914d42020-09-24 08:39:22 +02002415 if (px->disabled)
Willy Tarreau02b092f2020-10-07 18:36:54 +02002416 stop_proxy(px);
2417 }
2418
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002419 if (!hlua_post_init())
2420 exit(1);
Thomas Holmes6abded42015-05-12 16:23:58 +01002421
Maxime de Roucy0f503922016-05-13 23:52:55 +02002422 free(err_msg);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002423}
2424
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002425void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002426{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002427 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002428 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002429 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002430 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002431 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002432 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002433 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002434 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002435 struct per_thread_init_fct *tif, *tifb;
2436 struct per_thread_deinit_fct *tdf, *tdfb;
2437 struct per_thread_alloc_fct *taf, *tafb;
2438 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002439 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002440 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002441 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002442 int cur_fd;
2443
2444 /* At this point the listeners state is weird:
2445 * - most listeners are still bound and referenced in their protocol
2446 * - some might be zombies that are not in their proto anymore, but
2447 * still appear in their proxy's listeners with a valid FD.
2448 * - some might be stopped and still appear in their proxy as FD #-1
2449 * - among all of them, some might be inherited hence shared and we're
2450 * not allowed to pause them or whatever, we must just close them.
2451 * - finally some are not listeners (pipes, logs, stdout, etc) and
2452 * must be left intact.
2453 *
2454 * The safe way to proceed is to unbind (and close) whatever is not yet
2455 * unbound so that no more receiver/listener remains alive. Then close
2456 * remaining listener FDs, which correspond to zombie listeners (those
2457 * belonging to disabled proxies that were in another process).
2458 * objt_listener() would be cleaner here but not converted yet.
2459 */
2460 protocol_unbind_all();
2461
2462 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002463 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002464 continue;
2465
Willy Tarreaua74cb382020-10-15 21:29:49 +02002466 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002467 struct listener *l = fdtab[cur_fd].owner;
2468
2469 BUG_ON(l->state != LI_INIT);
2470 unbind_listener(l);
2471 }
2472 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002473
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002474 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002475 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002476 /* build a list of unique uri_auths */
2477 if (!ua)
2478 ua = p->uri_auth;
2479 else {
2480 /* check if p->uri_auth is unique */
2481 for (uap = ua; uap; uap=uap->next)
2482 if (uap == p->uri_auth)
2483 break;
2484
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002485 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002486 /* add it, if it is */
2487 p->uri_auth->next = ua;
2488 ua = p->uri_auth;
2489 }
William Lallemand0f99e342011-10-12 17:50:54 +02002490 }
2491
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002492 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002493 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002494 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002495 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002496
Aurelien DARRAGONf8796032023-03-09 12:07:09 +01002497
2498 /* we don't need to free sink_proxies_list proxies since it is
2499 * already handled in sink_deinit()
2500 */
Aurelien DARRAGON5526ddc2023-03-09 12:21:12 +01002501 p = cfg_log_forward;
2502 /* we need to manually clean cfg_log_forward proxy list */
2503 while (p) {
2504 p0 = p;
2505 p = p->next;
2506 free_proxy(p0);
2507 }
Aurelien DARRAGONf8796032023-03-09 12:07:09 +01002508
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002509 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002510 struct stat_scope *scope, *scopep;
2511
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002512 uap = ua;
2513 ua = ua->next;
2514
Willy Tarreaua534fea2008-08-03 12:19:50 +02002515 free(uap->uri_prefix);
2516 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002517 free(uap->node);
2518 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002519
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002520 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002521 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002522
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002523 scope = uap->scope;
2524 while (scope) {
2525 scopep = scope;
2526 scope = scope->next;
2527
2528 free(scopep->px_id);
2529 free(scopep);
2530 }
2531
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002532 free(uap);
2533 }
2534
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002535 userlist_free(userlist);
2536
David Carlier834cb2e2015-09-25 12:02:25 +01002537 cfg_unregister_sections();
2538
Christopher Faulet0132d062017-07-26 15:33:35 +02002539 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002540
Willy Tarreau05554e62016-12-21 20:46:26 +01002541 list_for_each_entry(pdf, &post_deinit_list, list)
2542 pdf->fct();
2543
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002544 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002545 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002546 ha_free(&global.chroot);
2547 ha_free(&global.pidfile);
2548 ha_free(&global.node);
2549 ha_free(&global.desc);
2550 ha_free(&oldpids);
2551 ha_free(&old_argv);
2552 ha_free(&localpeer);
2553 ha_free(&global.server_state_base);
2554 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002555 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002556 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002557
William Lallemand0f99e342011-10-12 17:50:54 +02002558 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002559 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002560 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002561 free(log);
2562 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002563 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002564 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002565 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002566 free(wl);
2567 }
2568
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002569 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2570 if (bol->must_free)
2571 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002572 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002573 free(bol);
2574 }
2575
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002576 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002577 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002578 free(pxdf);
2579 }
2580
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002581 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002582 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002583 free(pdf);
2584 }
2585
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002586 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002587 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002588 free(srvdf);
2589 }
2590
Tim Duesterhusfc854942020-09-10 19:46:42 +02002591 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002592 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002593 free(pcf);
2594 }
2595
Tim Duesterhus34bef072020-07-04 11:49:50 +02002596 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002597 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002598 free(pscf);
2599 }
2600
Tim Duesterhus53508d62020-09-10 19:46:40 +02002601 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002602 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002603 free(ppcf);
2604 }
2605
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002606 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002607 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002608 free(tif);
2609 }
2610
2611 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002612 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002613 free(tdf);
2614 }
2615
2616 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002617 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002618 free(taf);
2619 }
2620
2621 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002622 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002623 free(tff);
2624 }
2625
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002626 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002627 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002628 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629} /* end deinit() */
2630
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002631__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002632{
Amaury Denoyelle890f4be2021-08-09 15:02:56 +02002633 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002634 deinit();
2635 exit(status);
2636}
William Lallemand72160322018-11-06 17:37:16 +01002637
Willy Tarreau918ff602011-07-25 16:33:49 +02002638/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002639void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002640{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002641 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002642
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002643 tv_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002644 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002645 wake_expired_tasks();
2646
William Lallemand1aab50b2018-06-07 09:46:01 +02002647 /* check if we caught some signals and process them in the
2648 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002649 if (signal_queue_len && tid == 0) {
2650 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002651 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002652 }
2653
2654 /* Process a few tasks */
2655 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002656
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002657 /* also stop if we failed to cleanly stop all tasks */
2658 if (killed > 1)
2659 break;
2660
Matthias Wirth6b933fc2022-09-09 10:21:00 +02002661 /* expire immediately if events or signals are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002662 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002663 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002664 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002665 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002666 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2667 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002668 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002669 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002670 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Matthias Wirth6b933fc2022-09-09 10:21:00 +02002671 } else if (signal_queue_len) {
2672 /* this check is required to avoid
2673 * a race with wakeup on signals using wake_threads() */
2674 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002675 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002676 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002677 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002678
Willy Tarreau4f46a352020-03-23 09:27:28 +01002679 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002680 int i;
2681
2682 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002683 /* stop muxes before acknowledging stopping */
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002684 if (!(stopping_thread_mask & tid_bit)) {
2685 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2686 wake = 1;
2687 }
2688
Willy Tarreau1db42732021-04-06 11:44:07 +02002689 if (_HA_ATOMIC_OR_FETCH(&stopping_thread_mask, tid_bit) == tid_bit) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002690 /* notify all threads that stopping was just set */
2691 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002692 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002693 wake_thread(i);
2694 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002695 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002696
2697 /* stop when there's nothing left to do */
2698 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002699 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2700 /* wake all threads waiting on jobs==0 */
2701 for (i = 0; i < global.nbthread; i++)
2702 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2703 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002704 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002705 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002706 }
2707
Willy Tarreauc49ba522019-12-11 08:12:23 +01002708 /* If we have to sleep, measure how long */
2709 next = wake ? TICK_ETERNITY : next_timer_expiry();
2710
Willy Tarreau58b458d2008-06-29 22:40:23 +02002711 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002712 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002713
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002714 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002715 }
2716}
2717
Christopher Faulet1d17c102017-08-29 15:38:48 +02002718static void *run_thread_poll_loop(void *data)
2719{
Willy Tarreau082b6282019-05-22 14:42:12 +02002720 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002721 struct per_thread_init_fct *ptif;
2722 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002723 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002724 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002725 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2726 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002727
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02002728 ha_set_tid((unsigned long)data);
Willy Tarreaud022e9c2019-09-24 08:25:15 +02002729 sched = &task_per_thread[tid];
Willy Tarreau91e6df02019-05-03 17:21:18 +02002730
Willy Tarreauf6178242019-05-21 19:46:58 +02002731#if (_POSIX_TIMERS > 0) && defined(_POSIX_THREAD_CPUTIME)
Willy Tarreau91e6df02019-05-03 17:21:18 +02002732#ifdef USE_THREAD
Willy Tarreau8323a372019-05-20 18:57:53 +02002733 pthread_getcpuclockid(pthread_self(), &ti->clock_id);
Willy Tarreau624dcbf2019-05-20 20:23:06 +02002734#else
Willy Tarreau8323a372019-05-20 18:57:53 +02002735 ti->clock_id = CLOCK_THREAD_CPUTIME_ID;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002736#endif
Willy Tarreau663fda42019-05-21 15:14:08 +02002737#endif
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002738 /* Now, initialize one thread init at a time. This is better since
2739 * some init code is a bit tricky and may release global resources
2740 * after reallocating them locally. This will also ensure there is
2741 * no race on file descriptors allocation.
2742 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002743#ifdef USE_THREAD
2744 pthread_mutex_lock(&init_mutex);
2745#endif
2746 /* The first thread must set the number of threads left */
2747 if (!init_left)
2748 init_left = global.nbthread;
2749 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002750
Willy Tarreauc4c80fb2021-04-11 15:00:34 +02002751 tv_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002752
Willy Tarreau082b6282019-05-22 14:42:12 +02002753 /* per-thread alloc calls performed here are not allowed to snoop on
2754 * other threads, so they are free to initialize at their own rhythm
2755 * as long as they act as if they were alone. None of them may rely
2756 * on resources initialized by the other ones.
2757 */
2758 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2759 if (!ptaf->fct()) {
2760 ha_alert("failed to allocate resources for thread %u.\n", tid);
2761 exit(1);
2762 }
2763 }
2764
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002765 /* per-thread init calls performed here are not allowed to snoop on
2766 * other threads, so they are free to initialize at their own rhythm
2767 * as long as they act as if they were alone.
2768 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002769 list_for_each_entry(ptif, &per_thread_init_list, list) {
2770 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002771 ha_alert("failed to initialize thread %u.\n", tid);
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 Tarreau08293ed2021-07-14 17:54:01 +02002873 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
2874
Willy Tarreaufa32d202022-07-21 09:55:22 +02002875 /* Catch broken toolchains */
2876 if (sizeof(long) != sizeof(void *) || (intovf + 0x7FFFFFFF >= intovf)) {
2877 const char *msg;
2878
2879 if (sizeof(long) != sizeof(void *))
2880 /* Apparently MingW64 was not made for us and can also break openssl */
2881 msg = "The compiler this program was built with uses unsupported integral type sizes.\n"
2882 "Most likely it follows the unsupported LLP64 model. Never try to link HAProxy\n"
2883 "against libraries built with that compiler either! Please only use a compiler\n"
2884 "producing ILP32 or LP64 programs for both programs and libraries.\n";
2885 else if (intovf + 0x7FFFFFFF >= intovf)
2886 /* Catch forced CFLAGS that miss 2-complement integer overflow */
2887 msg = "The source code was miscompiled by the compiler, which usually indicates that\n"
2888 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
2889 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
2890 "and INSTALL files to decide on the best way to pass your local build options.\n";
2891 else
2892 msg = "Bug in the compiler bug detection code, please report it to developers!\n";
2893
Willy Tarreau08293ed2021-07-14 17:54:01 +02002894 fprintf(stderr,
2895 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
Willy Tarreaufa32d202022-07-21 09:55:22 +02002896 "%s"
2897 "\nBuild options :"
Willy Tarreau08293ed2021-07-14 17:54:01 +02002898#ifdef BUILD_TARGET
Willy Tarreaufa32d202022-07-21 09:55:22 +02002899 "\n TARGET = " BUILD_TARGET
Willy Tarreau08293ed2021-07-14 17:54:01 +02002900#endif
2901#ifdef BUILD_CPU
Willy Tarreaufa32d202022-07-21 09:55:22 +02002902 "\n CPU = " BUILD_CPU
Willy Tarreau08293ed2021-07-14 17:54:01 +02002903#endif
2904#ifdef BUILD_CC
Willy Tarreaufa32d202022-07-21 09:55:22 +02002905 "\n CC = " BUILD_CC
Willy Tarreau08293ed2021-07-14 17:54:01 +02002906#endif
2907#ifdef BUILD_CFLAGS
Willy Tarreaufa32d202022-07-21 09:55:22 +02002908 "\n CFLAGS = " BUILD_CFLAGS
Willy Tarreau08293ed2021-07-14 17:54:01 +02002909#endif
2910#ifdef BUILD_OPTIONS
Willy Tarreaufa32d202022-07-21 09:55:22 +02002911 "\n OPTIONS = " BUILD_OPTIONS
Willy Tarreau08293ed2021-07-14 17:54:01 +02002912#endif
2913#ifdef BUILD_DEBUG
Willy Tarreaufa32d202022-07-21 09:55:22 +02002914 "\n DEBUG = " BUILD_DEBUG
Willy Tarreau08293ed2021-07-14 17:54:01 +02002915#endif
Willy Tarreaufa32d202022-07-21 09:55:22 +02002916 "\n\n", msg);
2917
Willy Tarreau08293ed2021-07-14 17:54:01 +02002918 return 1;
2919 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002920
Olivier Houchard5fa300d2018-02-03 15:15:21 +01002921 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01002922
Willy Tarreauff9c9142019-02-07 10:39:36 +01002923 /* this can only safely be done here, though it's optimized away by
2924 * the compiler.
2925 */
2926 if (MAX_PROCS < 1 || MAX_PROCS > LONGBITS) {
2927 ha_alert("MAX_PROCS value must be between 1 and %d inclusive; "
2928 "HAProxy was built with value %d, please fix it and rebuild.\n",
2929 LONGBITS, MAX_PROCS);
2930 exit(1);
2931 }
2932
Willy Tarreaubf696402019-03-01 10:09:28 +01002933 /* take a copy of initial limits before we possibly change them */
2934 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02002935
2936 if (limit.rlim_max == RLIM_INFINITY)
2937 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01002938 rlim_fd_cur_at_boot = limit.rlim_cur;
2939 rlim_fd_max_at_boot = limit.rlim_max;
2940
Willy Tarreau5794fb02018-11-25 18:43:29 +01002941 /* process all initcalls in order of potential dependency */
2942 RUN_INITCALLS(STG_PREPARE);
2943 RUN_INITCALLS(STG_LOCK);
2944 RUN_INITCALLS(STG_ALLOC);
2945 RUN_INITCALLS(STG_POOL);
2946 RUN_INITCALLS(STG_REGISTER);
2947 RUN_INITCALLS(STG_INIT);
2948
Emeric Bruncf20bf12010-10-22 16:06:11 +02002949 init(argc, argv);
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002950 signal_register_fct(SIGQUIT, dump, SIGQUIT);
2951 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
2952 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02002953 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002954
Willy Tarreaue437c442010-03-17 18:02:46 +01002955 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
2956 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
2957 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002958 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002959 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002960
Willy Tarreaudc23a922011-02-16 11:10:36 +01002961 /* ulimits */
2962 if (!global.rlimit_nofile)
2963 global.rlimit_nofile = global.maxsock;
2964
2965 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01002966 limit.rlim_cur = global.rlimit_nofile;
2967 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
2968
Willy Tarreaudc23a922011-02-16 11:10:36 +01002969 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02002970 getrlimit(RLIMIT_NOFILE, &limit);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002971 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2972 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
2973 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002974 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002975 }
2976 else {
2977 /* try to set it to the max possible at least */
2978 limit.rlim_cur = limit.rlim_max;
2979 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
2980 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02002981
William Dauchya5194602020-03-28 19:29:58 +01002982 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002983 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
2984 global.rlimit_nofile = limit.rlim_cur;
2985 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01002986 }
2987 }
2988
2989 if (global.rlimit_memmax) {
2990 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01002991 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01002992#ifdef RLIMIT_AS
2993 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002994 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2995 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2996 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002997 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002998 }
2999 else
William Dauchya5194602020-03-28 19:29:58 +01003000 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003001 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003002 }
3003#else
3004 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003005 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3006 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
3007 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003008 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003009 }
3010 else
William Dauchya5194602020-03-28 19:29:58 +01003011 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003012 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01003013 }
3014#endif
3015 }
3016
William Lallemand9993c172022-01-07 18:19:42 +01003017 /* Try to get the listeners FD from the previous process using
3018 * _getsocks on the stat socket, it must never been done in wait mode
3019 * and check mode
3020 */
3021 if (old_unixsocket &&
3022 !(global.mode & (MODE_MWORKER_WAIT|MODE_CHECK))) {
William Lallemand85b0bd92017-06-01 17:38:53 +02003023 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02003024 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003025 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02003026 if (!(global.mode & MODE_MWORKER))
3027 exit(1);
3028 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02003029 }
3030 }
William Lallemand85b0bd92017-06-01 17:38:53 +02003031 get_cur_unixsocket();
3032
Willy Tarreaubaaee002006-06-26 02:48:02 +02003033 /* We will loop at most 100 times with 10 ms delay each time.
3034 * That's at most 1 second. We only send a signal to old pids
3035 * if we cannot grab at least one port.
3036 */
3037 retry = MAX_START_RETRIES;
3038 err = ERR_NONE;
3039 while (retry >= 0) {
3040 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02003041 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01003042 /* exit the loop on no error or fatal error */
3043 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003044 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02003045 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 break;
3047
3048 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
3049 * listening sockets. So on those platforms, it would be wiser to
3050 * simply send SIGUSR1, which will not be undoable.
3051 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02003052 if (tell_old_pids(SIGTTOU) == 0) {
3053 /* no need to wait if we can't contact old pids */
3054 retry = 0;
3055 continue;
3056 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003057 /* give some time to old processes to stop listening */
3058 w.tv_sec = 0;
3059 w.tv_usec = 10*1000;
3060 select(0, NULL, NULL, NULL, &w);
3061 retry--;
3062 }
3063
Willy Tarreaue91bff22020-09-02 11:11:43 +02003064 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003065 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003066 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003067 if (retry != MAX_START_RETRIES && nb_oldpids) {
3068 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003069 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003070 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003071 exit(1);
3072 }
3073
William Lallemand944e6192018-11-21 15:48:31 +01003074 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003075 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003076 /* Note: we don't have to send anything to the old pids because we
3077 * never stopped them. */
3078 exit(1);
3079 }
3080
Willy Tarreaue91bff22020-09-02 11:11:43 +02003081 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003082 * the previous process gave us, we don't need them anymore
3083 */
Willy Tarreau9f775762022-01-28 18:28:18 +01003084 sock_drop_unused_old_sockets();
Willy Tarreaudd815982007-10-16 12:25:14 +02003085
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003087 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3088 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003089
Willy Tarreaubaaee002006-06-26 02:48:02 +02003090 /* MODE_QUIET can inhibit alerts and warnings below this line */
3091
PiBa-NL149a81a2017-12-25 21:03:31 +01003092 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3093 /* either stdin/out/err are already closed or should stay as they are. */
3094 if ((global.mode & MODE_DAEMON)) {
3095 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3096 global.mode &= ~MODE_VERBOSE;
3097 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3098 }
3099 } else {
3100 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3101 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003102 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003103 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003104 }
3105
3106 /* open log & pid files before the chroot */
William Lallemand7af8e1d2022-02-14 09:02:14 +01003107 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) &&
3108 !(global.mode & MODE_MWORKER_WAIT) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 unlink(global.pidfile);
3110 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3111 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003112 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113 if (nb_oldpids)
3114 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003115 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 exit(1);
3117 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 }
3119
Willy Tarreaub38651a2007-03-24 17:24:39 +01003120 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003121 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3122 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003123 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003124 exit(1);
3125 }
3126
Jackie Tapia749f74c2020-07-22 18:59:40 -05003127 /* If the user is not root, we'll still let them try the configuration
3128 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003129 */
3130 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003131 ha_warning("[%s.main()] Some options which require full privileges"
3132 " might not work well.\n"
3133 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003134
William Lallemand095ba4c2017-06-01 17:38:50 +02003135 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3136
3137 /* chroot if needed */
3138 if (global.chroot != NULL) {
3139 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003140 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003141 if (nb_oldpids)
3142 tell_old_pids(SIGTTIN);
3143 protocol_unbind_all();
3144 exit(1);
3145 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003146 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003147 }
3148
William Lallemand944e6192018-11-21 15:48:31 +01003149 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003150 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151
William Lallemand27edc4b2019-05-07 17:49:33 +02003152 /* send a SIGTERM to workers who have a too high reloads number */
3153 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3154 mworker_kill_max_reloads(SIGTERM);
3155
Willy Tarreaubaaee002006-06-26 02:48:02 +02003156 /* Note that any error at this stage will be fatal because we will not
3157 * be able to restart the old pids.
3158 */
3159
William Dauchyf9af9d72019-11-17 15:47:16 +01003160 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3161 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003162
Willy Tarreaubaaee002006-06-26 02:48:02 +02003163 /* check ulimits */
3164 limit.rlim_cur = limit.rlim_max = 0;
3165 getrlimit(RLIMIT_NOFILE, &limit);
3166 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003167 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3168 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3169 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3170 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3171 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003172 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003173 }
3174 else
3175 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003176 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003177 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3178 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003179 }
3180
Willy Tarreauc690ca42023-05-17 09:02:21 +02003181 /* update the ready date a last time to also account for final setup time */
Willy Tarreauef0d92d2023-05-17 15:15:26 +02003182 gettimeofday(&date, NULL);
Willy Tarreauc690ca42023-05-17 09:02:21 +02003183 ready_date = date;
3184
William Lallemand944e6192018-11-21 15:48:31 +01003185 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003186 struct proxy *px;
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003187 struct peers *curpeers;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 int ret = 0;
3189 int proc;
William Lallemande1340412017-12-28 16:09:36 +01003190 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191
William Lallemand095ba4c2017-06-01 17:38:50 +02003192 /*
3193 * if daemon + mworker: must fork here to let a master
3194 * process live in background before forking children
3195 */
William Lallemand73b85e72017-06-01 17:38:51 +02003196
3197 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3198 && (global.mode & MODE_MWORKER)
3199 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003200 ret = fork();
3201 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003202 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003203 protocol_unbind_all();
3204 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003205 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003206 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003207 } else /* change the process group ID in the child (master process) */
3208 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003209 }
William Lallemande20b6a62017-06-01 17:38:55 +02003210
William Lallemande20b6a62017-06-01 17:38:55 +02003211
William Lallemanddeed7802017-11-06 11:00:04 +01003212 /* if in master-worker mode, write the PID of the father */
3213 if (global.mode & MODE_MWORKER) {
3214 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003215 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003216 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003217 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003218 }
3219
Willy Tarreaubaaee002006-06-26 02:48:02 +02003220 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003221 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003222 if (global.mode & MODE_MWORKER)
3223 mworker_ext_launch_all();
William Lallemand944e6192018-11-21 15:48:31 +01003224 for (proc = 0; proc < global.nbproc; proc++) {
3225 ret = fork();
3226 if (ret < 0) {
3227 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3228 protocol_unbind_all();
3229 exit(1); /* there has been an error */
3230 }
Willy Tarreau52bf8392020-03-08 00:42:37 +01003231 else if (ret == 0) { /* child breaks here */
Willy Tarreaua9274a12021-07-21 10:17:02 +02003232 /* This one must not be exported, it's internal! */
3233 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreau52bf8392020-03-08 00:42:37 +01003234 ha_random_jump96(relative_pid);
William Lallemand944e6192018-11-21 15:48:31 +01003235 break;
Willy Tarreau52bf8392020-03-08 00:42:37 +01003236 }
William Lallemand944e6192018-11-21 15:48:31 +01003237 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3238 char pidstr[100];
3239 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003240 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003241 }
3242 if (global.mode & MODE_MWORKER) {
3243 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003244
William Lallemand220567e2018-11-21 18:04:53 +01003245 ha_notice("New worker #%d (%d) forked\n", relative_pid, ret);
William Lallemand944e6192018-11-21 15:48:31 +01003246 /* find the right mworker_proc */
3247 list_for_each_entry(child, &proc_list, list) {
3248 if (child->relative_pid == relative_pid &&
William Lallemand7768c2d2022-07-21 00:52:43 +02003249 child->reloads == 0 && child->options & PROC_O_TYPE_WORKER &&
3250 child->pid == -1) {
William Lallemand512df052023-02-17 16:23:52 +01003251 child->timestamp = date.tv_sec;
William Lallemand944e6192018-11-21 15:48:31 +01003252 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003253 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003254 break;
3255 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003256 }
3257 }
William Lallemandbc193052018-09-11 10:06:26 +02003258
William Lallemand944e6192018-11-21 15:48:31 +01003259 relative_pid++; /* each child will get a different one */
3260 pid_bit <<= 1;
3261 }
3262 } else {
3263 /* wait mode */
3264 global.nbproc = 1;
3265 proc = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003267
3268#ifdef USE_CPU_AFFINITY
3269 if (proc < global.nbproc && /* child */
Willy Tarreauff9c9142019-02-07 10:39:36 +01003270 proc < MAX_PROCS && /* only the first 32/64 processes may be pinned */
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003271 ha_cpuset_count(&cpu_map.proc[proc])) { /* only do this if the process has a CPU map */
Olivier Houchard97148f62017-08-16 17:29:11 +02003272
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003273#ifdef __FreeBSD__
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003274 struct hap_cpuset *set = &cpu_map.proc[proc];
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003275 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
David Carlier2d0493a2020-12-02 21:14:51 +00003276#elif defined(__linux__) || defined(__DragonFly__)
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003277 struct hap_cpuset *set = &cpu_map.proc[proc];
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003278 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003279#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003280 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003281#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003282 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003283 if (pidfd >= 0) {
3284 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3285 close(pidfd);
3286 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003287
3288 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003289 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003291 if (proc == global.nbproc) {
William Lallemand944e6192018-11-21 15:48:31 +01003292 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003293
3294 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3295 (global.mode & MODE_DAEMON)) {
3296 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003297 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3298 stdio_quiet(-1);
3299
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003300 global.mode &= ~MODE_VERBOSE;
3301 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003302 }
3303
William Lallemandb3f2be32018-09-11 10:06:18 +02003304 mworker_loop();
William Lallemand1499b9b2017-06-07 15:04:47 +02003305 /* should never get there */
3306 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003307 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003308#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003309 ssl_free_dh();
3310#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003311 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003312 }
3313
William Lallemandcb11fd22017-06-01 17:38:52 +02003314 /* child must never use the atexit function */
3315 atexit_flag = 0;
3316
William Lallemandbc193052018-09-11 10:06:26 +02003317 /* close useless master sockets */
3318 if (global.mode & MODE_MWORKER) {
3319 struct mworker_proc *child, *it;
3320 master = 0;
3321
William Lallemand309dc9a2018-10-26 14:47:45 +02003322 mworker_cli_proxy_stop();
3323
William Lallemandbc193052018-09-11 10:06:26 +02003324 /* free proc struct of other processes */
3325 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003326 /* close the FD of the master side for all
3327 * workers, we don't need to close the worker
3328 * side of other workers since it's done with
3329 * the bind_proc */
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003330 if (child->ipc_fd[0] >= 0)
3331 close(child->ipc_fd[0]);
William Lallemandce83b4a2018-10-26 14:47:30 +02003332 if (child->relative_pid == relative_pid &&
William Lallemand7768c2d2022-07-21 00:52:43 +02003333 child->reloads == 0 &&
3334 child->pid == -1) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003335 /* keep this struct if this is our pid */
3336 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003337 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003338 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003339 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003340 mworker_free_child(child);
3341 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003342 }
3343 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003344
William Lallemande1340412017-12-28 16:09:36 +01003345 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3346 devnullfd = open("/dev/null", O_RDWR, 0);
3347 if (devnullfd < 0) {
3348 ha_alert("Cannot open /dev/null\n");
3349 exit(EXIT_FAILURE);
3350 }
3351 }
3352
William Lallemand095ba4c2017-06-01 17:38:50 +02003353 /* Must chroot and setgid/setuid in the children */
3354 /* chroot if needed */
3355 if (global.chroot != NULL) {
3356 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreau46317372021-06-15 08:59:19 +02003357 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003358 if (nb_oldpids)
3359 tell_old_pids(SIGTTIN);
3360 protocol_unbind_all();
3361 exit(1);
3362 }
3363 }
3364
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003365 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003366 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003367
William Lallemand7f80eb22017-05-26 18:19:55 +02003368 /* pass through every cli socket, and check if it's bound to
3369 * the current process and if it exposes listeners sockets.
3370 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3371 * */
3372
Willy Tarreau4975d142021-03-13 11:00:33 +01003373 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003374 struct bind_conf *bind_conf;
3375
Willy Tarreau4975d142021-03-13 11:00:33 +01003376 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003377 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreaue26993c2020-09-03 07:18:55 +02003378 if (!bind_conf->settings.bind_proc || bind_conf->settings.bind_proc & (1UL << proc)) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003379 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3380 break;
3381 }
3382 }
3383 }
3384 }
3385
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003386 /* we might have to unbind some proxies from some processes */
Olivier Houchardfbc74e82017-11-24 16:54:05 +01003387 px = proxies_list;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003388 while (px != NULL) {
Willy Tarreauc3914d42020-09-24 08:39:22 +02003389 if (px->bind_proc && !px->disabled) {
Willy Tarreau337c8352020-09-24 10:51:29 +02003390 if (!(px->bind_proc & (1UL << proc)))
3391 stop_proxy(px);
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003392 }
3393 px = px->next;
3394 }
3395
Emeric Brunc47ba592020-10-07 10:13:10 +02003396 /* we might have to unbind some log forward proxies from some processes */
3397 px = cfg_log_forward;
3398 while (px != NULL) {
Willy Tarreauc3914d42020-09-24 08:39:22 +02003399 if (px->bind_proc && !px->disabled) {
Willy Tarreau337c8352020-09-24 10:51:29 +02003400 if (!(px->bind_proc & (1UL << proc)))
3401 stop_proxy(px);
Emeric Brunc47ba592020-10-07 10:13:10 +02003402 }
3403 px = px->next;
3404 }
3405
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003406 /* we might have to unbind some peers sections from some processes */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02003407 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003408 if (!curpeers->peers_fe)
3409 continue;
3410
3411 if (curpeers->peers_fe->bind_proc & (1UL << proc))
3412 continue;
3413
3414 stop_proxy(curpeers->peers_fe);
3415 /* disable this peer section so that it kills itself */
Willy Tarreau47c8c022015-09-28 16:39:25 +02003416 signal_unregister_handler(curpeers->sighandler);
Olivier Houchard3f795f72019-04-17 22:51:06 +02003417 task_destroy(curpeers->sync_task);
Willy Tarreau47c8c022015-09-28 16:39:25 +02003418 curpeers->sync_task = NULL;
Olivier Houchard3f795f72019-04-17 22:51:06 +02003419 task_destroy(curpeers->peers_fe->task);
Willy Tarreau47c8c022015-09-28 16:39:25 +02003420 curpeers->peers_fe->task = NULL;
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003421 curpeers->peers_fe = NULL;
3422 }
3423
William Lallemand2e8fad92018-11-13 16:18:23 +01003424 /*
3425 * This is only done in daemon mode because we might want the
3426 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3427 * we should now close the 3 first FDs to ensure that we can
3428 * detach from the TTY. We MUST NOT do it in other cases since
3429 * it would have already be done, and 0-2 would have been
3430 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003432 if ((global.mode & MODE_DAEMON) &&
3433 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003435 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003436 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003437 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3438 }
3439 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003440 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3441 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003442 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003443 }
3444
William Dauchye039f262019-11-17 15:47:15 +01003445 /* try our best to re-enable core dumps depending on system capabilities.
3446 * What is addressed here :
3447 * - remove file size limits
3448 * - remove core size limits
3449 * - mark the process dumpable again if it lost it due to user/group
3450 */
3451 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3452 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3453
3454#if defined(RLIMIT_FSIZE)
3455 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3456 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3457 ha_alert("[%s.main()] Failed to set the raise the maximum "
3458 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003459 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003460 }
3461 else
3462 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003463 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003464 }
3465#endif
3466
3467#if defined(RLIMIT_CORE)
3468 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3469 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3470 ha_alert("[%s.main()] Failed to set the raise the core "
3471 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003472 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003473 }
3474 else
3475 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003476 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003477 }
3478#endif
3479
3480#if defined(USE_PRCTL)
3481 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3482 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3483 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com078062b2021-08-21 09:13:10 +01003484#elif defined(USE_PROCCTL)
3485 int traceable = PROC_TRACE_CTL_ENABLE;
3486 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3487 ha_warning("[%s.main()] Failed to set the traceable flag, "
3488 "no core will be dumped.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003489#endif
3490 }
3491
Christopher Faulete3a5e352017-10-24 13:53:54 +02003492 global.mode &= ~MODE_STARTING;
Willy Tarreau4f60f162007-04-08 16:39:58 +02003493 /*
3494 * That's it : the central polling loop. Run until we stop.
3495 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02003496#ifdef USE_THREAD
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003497 {
William Lallemand1aab50b2018-06-07 09:46:01 +02003498 sigset_t blocked_sig, old_sig;
Willy Tarreauc40efc12019-05-03 09:22:44 +02003499 int i;
3500
William Lallemand1aab50b2018-06-07 09:46:01 +02003501 /* ensure the signals will be blocked in every thread */
3502 sigfillset(&blocked_sig);
3503 sigdelset(&blocked_sig, SIGPROF);
3504 sigdelset(&blocked_sig, SIGBUS);
3505 sigdelset(&blocked_sig, SIGFPE);
3506 sigdelset(&blocked_sig, SIGILL);
3507 sigdelset(&blocked_sig, SIGSEGV);
3508 pthread_sigmask(SIG_SETMASK, &blocked_sig, &old_sig);
3509
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003510 /* Create nbthread-1 thread. The first thread is the current process */
David Carliera92c5ce2019-09-13 05:03:12 +01003511 ha_thread_info[0].pthread = pthread_self();
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003512 for (i = 1; i < global.nbthread; i++)
David Carliera92c5ce2019-09-13 05:03:12 +01003513 pthread_create(&ha_thread_info[i].pthread, NULL, &run_thread_poll_loop, (void *)(long)i);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003514
Christopher Faulet62519022017-10-16 15:49:32 +02003515#ifdef USE_CPU_AFFINITY
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003516 /* Now the CPU affinity for all threads */
Amaury Denoyelleaf02c572021-04-15 16:29:58 +02003517
3518 /* If on multiprocess, use proc_t1 except for the first process.
3519 */
3520 if ((relative_pid - 1) > 0)
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003521 cpu_map.thread[0] = cpu_map.proc_t1[relative_pid-1];
Willy Tarreau7764a572019-07-16 15:10:34 +02003522
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003523 for (i = 0; i < global.nbthread; i++) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003524 if (ha_cpuset_count(&cpu_map.proc[relative_pid-1]))
3525 ha_cpuset_and(&cpu_map.thread[i], &cpu_map.proc[relative_pid-1]);
Christopher Faulet62519022017-10-16 15:49:32 +02003526
Willy Tarreau421f02e2018-01-20 18:19:22 +01003527 if (i < MAX_THREADS && /* only the first 32/64 threads may be pinned */
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003528 ha_cpuset_count(&cpu_map.thread[i])) {/* only do this if the thread has a THREAD map */
David Carlier5e4c8e22019-09-13 05:12:58 +01003529#if defined(__APPLE__)
3530 int j;
Amaury Denoyelle8f685c12021-04-27 16:45:29 +02003531 unsigned long set = cpu_map.thread[i].cpuset;
David Carlier5e4c8e22019-09-13 05:12:58 +01003532
Amaury Denoyelle8f685c12021-04-27 16:45:29 +02003533 while ((j = ffsl(set)) > 0) {
David Carlier5e4c8e22019-09-13 05:12:58 +01003534 thread_affinity_policy_data_t cpu_set = { j - 1 };
3535 thread_port_t mthread = pthread_mach_thread_np(ha_thread_info[i].pthread);
3536 thread_policy_set(mthread, THREAD_AFFINITY_POLICY, (thread_policy_t)&cpu_set, 1);
Amaury Denoyelle8f685c12021-04-27 16:45:29 +02003537 set &= ~(1UL << (j - 1));
David Carlier5e4c8e22019-09-13 05:12:58 +01003538 }
3539#else
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003540 struct hap_cpuset *set = &cpu_map.thread[i];
David Carliera92c5ce2019-09-13 05:03:12 +01003541 pthread_setaffinity_np(ha_thread_info[i].pthread,
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003542 sizeof(set->cpuset), &set->cpuset);
David Carlier5e4c8e22019-09-13 05:12:58 +01003543#endif
Olivier Houchard829aa242017-12-01 18:19:43 +01003544 }
Christopher Faulet1d17c102017-08-29 15:38:48 +02003545 }
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003546#endif /* !USE_CPU_AFFINITY */
3547
William Lallemand1aab50b2018-06-07 09:46:01 +02003548 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003549 haproxy_unblock_signals();
William Lallemand1aab50b2018-06-07 09:46:01 +02003550
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003551 /* Finally, start the poll loop for the first thread */
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02003552 run_thread_poll_loop(0);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003553
3554 /* Wait the end of other threads */
3555 for (i = 1; i < global.nbthread; i++)
David Carliera92c5ce2019-09-13 05:03:12 +01003556 pthread_join(ha_thread_info[i].pthread, NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02003557
Christopher Fauletb79a94c2017-05-30 15:34:30 +02003558#if defined(DEBUG_THREAD) || defined(DEBUG_FULL)
3559 show_lock_stats();
3560#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003561 }
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003562#else /* ! USE_THREAD */
William Lallemandd3801c12018-09-11 10:06:23 +02003563 haproxy_unblock_signals();
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02003564 run_thread_poll_loop(0);
Christopher Faulet62519022017-10-16 15:49:32 +02003565#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003566
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003567 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003568}
3569
Willy Tarreaubaaee002006-06-26 02:48:02 +02003570/*
3571 * Local variables:
3572 * c-indent-level: 8
3573 * c-basic-offset: 8
3574 * End:
3575 */