blob: f5d4579d59fe8bf1010133f2577a586b76188057 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
Willy Tarreaua5357cd2021-05-09 06:14:25 +02002 * HAProxy : High Availability-enabled HTTP/TCP proxy
Willy Tarreau1e183b82022-01-07 16:40:23 +01003 * Copyright 2000-2022 Willy Tarreau <willy@haproxy.org>.
Willy Tarreaubaaee002006-06-26 02:48:02 +02004 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
Ilya Shipitsin46a030c2020-07-05 16:36:08 +050010 * Please refer to RFC7230 - RFC7235 information about HTTP protocol, and
11 * RFC6265 for information about cookies usage. More generally, the IETF HTTP
Willy Tarreaubaaee002006-06-26 02:48:02 +020012 * Working Group's web site should be consulted for protocol related changes :
13 *
14 * http://ftp.ics.uci.edu/pub/ietf/http/
15 *
16 * Pending bugs (may be not fixed because never reproduced) :
17 * - solaris only : sometimes, an HTTP proxy with only a dispatch address causes
18 * the proxy to terminate (no core) if the client breaks the connection during
19 * the response. Seen on 1.1.8pre4, but never reproduced. May not be related to
20 * the snprintf() bug since requests were simple (GET / HTTP/1.0), but may be
21 * related to missing setsid() (fixed in 1.1.15)
22 * - a proxy with an invalid config will prevent the startup even if disabled.
23 *
24 * ChangeLog has moved to the CHANGELOG file.
25 *
Willy Tarreaubaaee002006-06-26 02:48:02 +020026 */
27
David Carlier7ece0962015-12-08 21:43:09 +000028#define _GNU_SOURCE
Willy Tarreaubaaee002006-06-26 02:48:02 +020029#include <stdio.h>
30#include <stdlib.h>
31#include <unistd.h>
32#include <string.h>
33#include <ctype.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020034#include <dirent.h>
Maxime de Roucy379d9c72016-05-13 23:52:56 +020035#include <sys/stat.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036#include <sys/time.h>
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <netinet/tcp.h>
40#include <netinet/in.h>
41#include <arpa/inet.h>
42#include <netdb.h>
43#include <fcntl.h>
44#include <errno.h>
45#include <signal.h>
46#include <stdarg.h>
47#include <sys/resource.h>
Tim Duesterhusdfad6a42020-04-18 16:02:47 +020048#include <sys/utsname.h>
Marc-Antoine Perennou992709b2013-02-12 10:53:52 +010049#include <sys/wait.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050#include <time.h>
51#include <syslog.h>
Michael Schererab012dd2013-01-12 18:35:19 +010052#include <grp.h>
Willy 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{
660 /* if -x was used, try to update the stat socket if not available anymore */
Willy Tarreau4975d142021-03-13 11:00:33 +0100661 if (global.cli_fe) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200662 struct bind_conf *bind_conf;
663
664 /* pass through all stats socket */
Willy Tarreau4975d142021-03-13 11:00:33 +0100665 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200666 struct listener *l;
667
668 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
669
Willy Tarreau37159062020-08-27 07:48:42 +0200670 if (l->rx.addr.ss_family == AF_UNIX &&
William Lallemand85b0bd92017-06-01 17:38:53 +0200671 (bind_conf->level & ACCESS_FD_LISTENERS)) {
672 const struct sockaddr_un *un;
673
Willy Tarreau37159062020-08-27 07:48:42 +0200674 un = (struct sockaddr_un *)&l->rx.addr;
William Lallemand85b0bd92017-06-01 17:38:53 +0200675 /* priority to old_unixsocket */
676 if (!cur_unixsocket) {
677 cur_unixsocket = strdup(un->sun_path);
678 } else {
Tim Duesterhuse5ff1412021-01-02 22:31:53 +0100679 if (old_unixsocket && strcmp(un->sun_path, old_unixsocket) == 0) {
William Lallemand85b0bd92017-06-01 17:38:53 +0200680 free(cur_unixsocket);
681 cur_unixsocket = strdup(old_unixsocket);
682 return;
683 }
684 }
685 }
686 }
687 }
688 }
689 if (!cur_unixsocket && old_unixsocket)
690 cur_unixsocket = strdup(old_unixsocket);
691}
692
William Lallemand73b85e72017-06-01 17:38:51 +0200693/*
694 * When called, this function reexec haproxy with -sf followed by current
Joseph Herlant03420902018-11-15 10:41:50 -0800695 * children PIDs and possibly old children PIDs if they didn't leave yet.
William Lallemand73b85e72017-06-01 17:38:51 +0200696 */
William Lallemanda57b7e32018-12-14 21:11:31 +0100697void mworker_reload()
William Lallemand73b85e72017-06-01 17:38:51 +0200698{
William Lallemand00417412020-06-05 14:08:41 +0200699 char **next_argv = NULL;
700 int old_argc = 0; /* previous number of argument */
William Lallemand73b85e72017-06-01 17:38:51 +0200701 int next_argc = 0;
William Lallemand00417412020-06-05 14:08:41 +0200702 int i = 0;
William Lallemand73b85e72017-06-01 17:38:51 +0200703 char *msg = NULL;
Willy Tarreau8dca1952019-03-01 10:21:55 +0100704 struct rlimit limit;
William Lallemand7c756a82018-11-26 11:53:40 +0100705 struct per_thread_deinit_fct *ptdf;
William Lallemand73b85e72017-06-01 17:38:51 +0200706
707 mworker_block_signals();
Tim Duesterhusd6942c82017-11-20 15:58:35 +0100708#if defined(USE_SYSTEMD)
709 if (global.tune.options & GTUNE_USE_SYSTEMD)
710 sd_notify(0, "RELOADING=1");
711#endif
William Lallemand73b85e72017-06-01 17:38:51 +0200712 setenv("HAPROXY_MWORKER_REEXEC", "1", 1);
713
William Lallemandbc193052018-09-11 10:06:26 +0200714 mworker_proc_list_to_env(); /* put the children description in the env */
715
William Lallemand7c756a82018-11-26 11:53:40 +0100716 /* during the reload we must ensure that every FDs that can't be
717 * reuse (ie those that are not referenced in the proc_list)
718 * are closed or they will leak. */
719
720 /* close the listeners FD */
721 mworker_cli_proxy_stop();
William Lallemand16866672019-06-24 17:40:48 +0200722
723 if (getenv("HAPROXY_MWORKER_WAIT_ONLY") == NULL) {
724 /* close the poller FD and the thread waker pipe FD */
725 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
726 ptdf->fct();
727 if (fdtab)
728 deinit_pollers();
729 }
Ilya Shipitsin98a9e1b2021-02-19 23:42:53 +0500730#ifdef HAVE_SSL_RAND_KEEP_RANDOM_DEVICES_OPEN
William Lallemand5fdb5b32019-10-15 14:04:08 +0200731 /* close random device FDs */
732 RAND_keep_random_devices_open(0);
Rob Allen56996da2019-05-03 09:11:32 +0100733#endif
William Lallemand7c756a82018-11-26 11:53:40 +0100734
Willy Tarreau8dca1952019-03-01 10:21:55 +0100735 /* restore the initial FD limits */
736 limit.rlim_cur = rlim_fd_cur_at_boot;
737 limit.rlim_max = rlim_fd_max_at_boot;
738 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
739 getrlimit(RLIMIT_NOFILE, &limit);
740 ha_warning("Failed to restore initial FD limits (cur=%u max=%u), using cur=%u max=%u\n",
741 rlim_fd_cur_at_boot, rlim_fd_max_at_boot,
742 (unsigned int)limit.rlim_cur, (unsigned int)limit.rlim_max);
743 }
744
William Lallemand73b85e72017-06-01 17:38:51 +0200745 /* compute length */
William Lallemand00417412020-06-05 14:08:41 +0200746 while (old_argv[old_argc])
747 old_argc++;
William Lallemand73b85e72017-06-01 17:38:51 +0200748
William Lallemand85b0bd92017-06-01 17:38:53 +0200749 /* 1 for haproxy -sf, 2 for -x /socket */
William Lallemandaba7f8b2021-04-21 16:55:34 +0200750 next_argv = calloc(old_argc + 1 + 2 + mworker_child_nb() + 1,
Tim Duesterhuse52b6e52020-09-12 20:26:43 +0200751 sizeof(*next_argv));
William Lallemand73b85e72017-06-01 17:38:51 +0200752 if (next_argv == NULL)
753 goto alloc_error;
754
William Lallemand00417412020-06-05 14:08:41 +0200755 /* copy the program name */
756 next_argv[next_argc++] = old_argv[0];
757
758 /* insert the new options just after argv[0] in case we have a -- */
759
William Lallemand73b85e72017-06-01 17:38:51 +0200760 /* add -sf <PID>* to argv */
William Lallemand3f128872019-04-01 11:29:59 +0200761 if (mworker_child_nb() > 0) {
762 struct mworker_proc *child;
763
William Lallemand73b85e72017-06-01 17:38:51 +0200764 next_argv[next_argc++] = "-sf";
William Lallemand3f128872019-04-01 11:29:59 +0200765
766 list_for_each_entry(child, &proc_list, list) {
William Lallemand677e2f22019-11-19 17:04:18 +0100767 if (!(child->options & (PROC_O_TYPE_WORKER|PROC_O_TYPE_PROG)) || child->pid <= -1 )
William Lallemand3f128872019-04-01 11:29:59 +0200768 continue;
William Lallemand00417412020-06-05 14:08:41 +0200769 if ((next_argv[next_argc++] = memprintf(&msg, "%d", child->pid)) == NULL)
William Lallemand73b85e72017-06-01 17:38:51 +0200770 goto alloc_error;
771 msg = NULL;
772 }
773 }
William Lallemand2bf6d622017-06-20 11:20:23 +0200774 /* add the -x option with the stat socket */
William Lallemand85b0bd92017-06-01 17:38:53 +0200775 if (cur_unixsocket) {
William Lallemand2bf6d622017-06-20 11:20:23 +0200776 next_argv[next_argc++] = "-x";
777 next_argv[next_argc++] = (char *)cur_unixsocket;
William Lallemand85b0bd92017-06-01 17:38:53 +0200778 }
779
William Lallemand00417412020-06-05 14:08:41 +0200780 /* copy the previous options */
781 for (i = 1; i < old_argc; i++)
782 next_argv[next_argc++] = old_argv[i];
783
Christopher Faulet767a84b2017-11-24 16:50:31 +0100784 ha_warning("Reexecuting Master process\n");
Willy Tarreaue0d86e22019-08-26 10:37:39 +0200785 signal(SIGPROF, SIG_IGN);
Tim Duesterhus0436ab72017-11-12 17:39:18 +0100786 execvp(next_argv[0], next_argv);
William Lallemand73b85e72017-06-01 17:38:51 +0200787
Christopher Faulet767a84b2017-11-24 16:50:31 +0100788 ha_warning("Failed to reexecute the master process [%d]: %s\n", pid, strerror(errno));
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100789 ha_free(&next_argv);
William Lallemand722d4ca2017-11-15 19:02:55 +0100790 return;
791
William Lallemand73b85e72017-06-01 17:38:51 +0200792alloc_error:
Willy Tarreau61cfdf42021-02-20 10:46:51 +0100793 ha_free(&next_argv);
Joseph Herlant07a08342018-11-15 10:43:05 -0800794 ha_warning("Failed to reexecute the master process [%d]: Cannot allocate memory\n", pid);
William Lallemand73b85e72017-06-01 17:38:51 +0200795 return;
796}
797
William Lallemandb3f2be32018-09-11 10:06:18 +0200798static void mworker_loop()
799{
800
801#if defined(USE_SYSTEMD)
802 if (global.tune.options & GTUNE_USE_SYSTEMD)
803 sd_notifyf(0, "READY=1\nMAINPID=%lu", (unsigned long)getpid());
804#endif
Willy Tarreaud83b6c12019-04-18 11:31:36 +0200805 /* Busy polling makes no sense in the master :-) */
806 global.tune.options &= ~GTUNE_BUSY_POLLING;
William Lallemandb3f2be32018-09-11 10:06:18 +0200807
William Lallemandbc193052018-09-11 10:06:26 +0200808 master = 1;
809
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100810 signal_unregister(SIGTTIN);
811 signal_unregister(SIGTTOU);
William Lallemand0564d412018-11-20 17:36:53 +0100812 signal_unregister(SIGUSR1);
813 signal_unregister(SIGHUP);
814 signal_unregister(SIGQUIT);
815
William Lallemandb3f2be32018-09-11 10:06:18 +0200816 signal_register_fct(SIGTERM, mworker_catch_sigterm, SIGTERM);
817 signal_register_fct(SIGUSR1, mworker_catch_sigterm, SIGUSR1);
Willy Tarreaud26c9f92019-12-11 14:24:07 +0100818 signal_register_fct(SIGTTIN, mworker_broadcast_signal, SIGTTIN);
819 signal_register_fct(SIGTTOU, mworker_broadcast_signal, SIGTTOU);
William Lallemandb3f2be32018-09-11 10:06:18 +0200820 signal_register_fct(SIGINT, mworker_catch_sigterm, SIGINT);
821 signal_register_fct(SIGHUP, mworker_catch_sighup, SIGHUP);
822 signal_register_fct(SIGUSR2, mworker_catch_sighup, SIGUSR2);
823 signal_register_fct(SIGCHLD, mworker_catch_sigchld, SIGCHLD);
824
825 mworker_unblock_signals();
826 mworker_cleanlisteners();
William Lallemand27f3fa52018-12-06 14:05:20 +0100827 mworker_cleantasks();
William Lallemandb3f2be32018-09-11 10:06:18 +0200828
William Lallemandbc193052018-09-11 10:06:26 +0200829 mworker_catch_sigchld(NULL); /* ensure we clean the children in case
830 some SIGCHLD were lost */
831
William Lallemandb3f2be32018-09-11 10:06:18 +0200832 global.nbthread = 1;
833 relative_pid = 1;
834 pid_bit = 1;
Willy Tarreaua38a7172019-02-02 17:11:28 +0100835 all_proc_mask = 1;
William Lallemandb3f2be32018-09-11 10:06:18 +0200836
William Lallemand2672eb92018-12-14 15:52:39 +0100837#ifdef USE_THREAD
838 tid_bit = 1;
839 all_threads_mask = 1;
840#endif
841
William Lallemandb3f2be32018-09-11 10:06:18 +0200842 jobs++; /* this is the "master" job, we want to take care of the
843 signals even if there is no listener so the poll loop don't
844 leave */
845
846 fork_poller();
Willy Tarreaub4f7cc32019-05-03 09:27:30 +0200847 run_thread_poll_loop(0);
William Lallemandb3f2be32018-09-11 10:06:18 +0200848}
William Lallemandcb11fd22017-06-01 17:38:52 +0200849
850/*
851 * Reexec the process in failure mode, instead of exiting
852 */
853void reexec_on_failure()
854{
855 if (!atexit_flag)
856 return;
857
858 setenv("HAPROXY_MWORKER_WAIT_ONLY", "1", 1);
859
Christopher Faulet767a84b2017-11-24 16:50:31 +0100860 ha_warning("Reexecuting Master process in waitpid mode\n");
William Lallemandcb11fd22017-06-01 17:38:52 +0200861 mworker_reload();
William Lallemandcb11fd22017-06-01 17:38:52 +0200862}
William Lallemand73b85e72017-06-01 17:38:51 +0200863
864
865/*
Willy Tarreaud0807c32010-08-27 18:26:11 +0200866 * upon SIGUSR1, let's have a soft stop. Note that soft_stop() broadcasts
867 * a signal zero to all subscribers. This means that it's as easy as
868 * subscribing to signal 0 to get informed about an imminent shutdown.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200869 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100870static void sig_soft_stop(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200871{
872 soft_stop();
Willy Tarreau24f4efa2010-08-27 17:56:48 +0200873 signal_unregister_handler(sh);
Willy Tarreaubafbe012017-11-24 17:34:44 +0100874 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200875}
876
877/*
878 * upon SIGTTOU, we pause everything
879 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100880static void sig_pause(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200881{
Willy Tarreau775e0012020-09-24 16:36:26 +0200882 if (protocol_pause_all() & ERR_FATAL) {
883 const char *msg = "Some proxies refused to pause, performing soft stop now.\n";
Willy Tarreau0a002df2020-10-09 19:26:27 +0200884 ha_warning("%s", msg);
885 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200886 soft_stop();
887 }
Willy Tarreaubafbe012017-11-24 17:34:44 +0100888 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200889}
890
891/*
892 * upon SIGTTIN, let's have a soft stop.
893 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100894static void sig_listen(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200895{
Willy Tarreau775e0012020-09-24 16:36:26 +0200896 if (protocol_resume_all() & ERR_FATAL) {
897 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 +0200898 ha_warning("%s", msg);
899 send_log(NULL, LOG_WARNING, "%s", msg);
Willy Tarreau775e0012020-09-24 16:36:26 +0200900 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200901}
902
903/*
904 * this function dumps every server's state when the process receives SIGHUP.
905 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100906static void sig_dump_state(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200907{
Olivier Houchardfbc74e82017-11-24 16:54:05 +0100908 struct proxy *p = proxies_list;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200909
Christopher Faulet767a84b2017-11-24 16:50:31 +0100910 ha_warning("SIGHUP received, dumping servers states.\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +0200911 while (p) {
912 struct server *s = p->srv;
913
914 send_log(p, LOG_NOTICE, "SIGHUP received, dumping servers states for proxy %s.\n", p->id);
915 while (s) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100916 chunk_printf(&trash,
917 "SIGHUP: Server %s/%s is %s. Conn: %d act, %d pend, %lld tot.",
918 p->id, s->id,
Emeric Brun52a91d32017-08-31 14:41:55 +0200919 (s->cur_state != SRV_ST_STOPPED) ? "UP" : "DOWN",
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100920 s->cur_sess, s->nbpend, s->counters.cum_sess);
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200921 ha_warning("%s\n", trash.area);
922 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200923 s = s->next;
924 }
925
Willy Tarreau5fcc8f12007-09-17 11:27:09 +0200926 /* FIXME: those info are a bit outdated. We should be able to distinguish between FE and BE. */
927 if (!p->srv) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100928 chunk_printf(&trash,
929 "SIGHUP: Proxy %s has no servers. Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
930 p->id,
931 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 +0200932 } else if (p->srv_act == 0) {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100933 chunk_printf(&trash,
934 "SIGHUP: Proxy %s %s ! Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
935 p->id,
936 (p->srv_bck) ? "is running on backup servers" : "has no server available",
937 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 +0200938 } else {
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100939 chunk_printf(&trash,
940 "SIGHUP: Proxy %s has %d active servers and %d backup servers available."
941 " Conn: act(FE+BE): %d+%d, %d pend (%d unass), tot(FE+BE): %lld+%lld.",
942 p->id, p->srv_act, p->srv_bck,
943 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 +0200944 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +0200945 ha_warning("%s\n", trash.area);
946 send_log(p, LOG_NOTICE, "%s\n", trash.area);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200947
948 p = p->next;
949 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200950}
951
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100952static void dump(struct sig_handler *sh)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200953{
Willy Tarreauc6ca1a02007-05-13 19:43:47 +0200954 /* dump memory usage then free everything possible */
955 dump_pools();
Willy Tarreaubafbe012017-11-24 17:34:44 +0100956 pool_gc(NULL);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957}
958
William Lallemande1340412017-12-28 16:09:36 +0100959/*
960 * This function dup2 the stdio FDs (0,1,2) with <fd>, then closes <fd>
961 * If <fd> < 0, it opens /dev/null and use it to dup
962 *
963 * In the case of chrooting, you have to open /dev/null before the chroot, and
964 * pass the <fd> to this function
965 */
966static void stdio_quiet(int fd)
967{
968 if (fd < 0)
969 fd = open("/dev/null", O_RDWR, 0);
970
971 if (fd > -1) {
972 fclose(stdin);
973 fclose(stdout);
974 fclose(stderr);
975
976 dup2(fd, 0);
977 dup2(fd, 1);
978 dup2(fd, 2);
979 if (fd > 2)
980 close(fd);
981 return;
982 }
983
984 ha_alert("Cannot open /dev/null\n");
985 exit(EXIT_FAILURE);
986}
987
988
Joseph Herlant03420902018-11-15 10:41:50 -0800989/* This function checks if cfg_cfgfiles contains directories.
990 * If it finds one, it adds all the files (and only files) it contains
991 * in cfg_cfgfiles in place of the directory (and removes the directory).
992 * It adds the files in lexical order.
993 * It adds only files with .cfg extension.
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200994 * It doesn't add files with name starting with '.'
995 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +0100996static void cfgfiles_expand_directories(void)
Maxime de Roucy379d9c72016-05-13 23:52:56 +0200997{
998 struct wordlist *wl, *wlb;
999 char *err = NULL;
1000
1001 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
1002 struct stat file_stat;
1003 struct dirent **dir_entries = NULL;
1004 int dir_entries_nb;
1005 int dir_entries_it;
1006
1007 if (stat(wl->s, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001008 ha_alert("Cannot open configuration file/directory %s : %s\n",
1009 wl->s,
1010 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001011 exit(1);
1012 }
1013
1014 if (!S_ISDIR(file_stat.st_mode))
1015 continue;
1016
1017 /* from this point wl->s is a directory */
1018
1019 dir_entries_nb = scandir(wl->s, &dir_entries, NULL, alphasort);
1020 if (dir_entries_nb < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001021 ha_alert("Cannot open configuration directory %s : %s\n",
1022 wl->s,
1023 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001024 exit(1);
1025 }
1026
1027 /* for each element in the directory wl->s */
1028 for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; dir_entries_it++) {
1029 struct dirent *dir_entry = dir_entries[dir_entries_it];
1030 char *filename = NULL;
1031 char *d_name_cfgext = strstr(dir_entry->d_name, ".cfg");
1032
1033 /* don't add filename that begin with .
Joseph Herlant03420902018-11-15 10:41:50 -08001034 * only add filename with .cfg extension
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001035 */
1036 if (dir_entry->d_name[0] == '.' ||
1037 !(d_name_cfgext && d_name_cfgext[4] == '\0'))
1038 goto next_dir_entry;
1039
1040 if (!memprintf(&filename, "%s/%s", wl->s, dir_entry->d_name)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001041 ha_alert("Cannot load configuration files %s : out of memory.\n",
1042 filename);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001043 exit(1);
1044 }
1045
1046 if (stat(filename, &file_stat)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001047 ha_alert("Cannot open configuration file %s : %s\n",
1048 wl->s,
1049 strerror(errno));
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001050 exit(1);
1051 }
1052
1053 /* don't add anything else than regular file in cfg_cfgfiles
1054 * this way we avoid loops
1055 */
1056 if (!S_ISREG(file_stat.st_mode))
1057 goto next_dir_entry;
1058
1059 if (!list_append_word(&wl->list, filename, &err)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001060 ha_alert("Cannot load configuration files %s : %s\n",
1061 filename,
1062 err);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001063 exit(1);
1064 }
1065
1066next_dir_entry:
1067 free(filename);
1068 free(dir_entry);
1069 }
1070
1071 free(dir_entries);
1072
1073 /* remove the current directory (wl) from cfg_cfgfiles */
1074 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02001075 LIST_DELETE(&wl->list);
Maxime de Roucy379d9c72016-05-13 23:52:56 +02001076 free(wl);
1077 }
1078
1079 free(err);
1080}
1081
Willy Tarreaubaaee002006-06-26 02:48:02 +02001082/*
William Lallemand73b85e72017-06-01 17:38:51 +02001083 * copy and cleanup the current argv
William Lallemanddf6c5a82020-06-04 17:40:23 +02001084 * Remove the -sf /-st / -x parameters
William Lallemand73b85e72017-06-01 17:38:51 +02001085 * Return an allocated copy of argv
1086 */
1087
1088static char **copy_argv(int argc, char **argv)
1089{
William Lallemanddf6c5a82020-06-04 17:40:23 +02001090 char **newargv, **retargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001091
Tim Duesterhuse52b6e52020-09-12 20:26:43 +02001092 newargv = calloc(argc + 2, sizeof(*newargv));
William Lallemand73b85e72017-06-01 17:38:51 +02001093 if (newargv == NULL) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001094 ha_warning("Cannot allocate memory\n");
William Lallemand73b85e72017-06-01 17:38:51 +02001095 return NULL;
1096 }
William Lallemanddf6c5a82020-06-04 17:40:23 +02001097 retargv = newargv;
William Lallemand73b85e72017-06-01 17:38:51 +02001098
William Lallemanddf6c5a82020-06-04 17:40:23 +02001099 /* first copy argv[0] */
1100 *newargv++ = *argv++;
1101 argc--;
1102
1103 while (argc > 0) {
1104 if (**argv != '-') {
1105 /* non options are copied but will fail in the argument parser */
1106 *newargv++ = *argv++;
1107 argc--;
1108
1109 } else {
1110 char *flag;
1111
1112 flag = *argv + 1;
1113
1114 if (flag[0] == '-' && flag[1] == 0) {
1115 /* "--\0" copy every arguments till the end of argv */
1116 *newargv++ = *argv++;
1117 argc--;
1118
1119 while (argc > 0) {
1120 *newargv++ = *argv++;
1121 argc--;
1122 }
1123 } else {
1124 switch (*flag) {
1125 case 's':
1126 /* -sf / -st and their parameters are ignored */
1127 if (flag[1] == 'f' || flag[1] == 't') {
1128 argc--;
1129 argv++;
1130 /* The list can't contain a negative value since the only
1131 way to know the end of this list is by looking for the
1132 next option or the end of the options */
1133 while (argc > 0 && argv[0][0] != '-') {
1134 argc--;
1135 argv++;
1136 }
William Lallemand398da622020-09-02 16:12:23 +02001137 } else {
1138 argc--;
1139 argv++;
1140
William Lallemanddf6c5a82020-06-04 17:40:23 +02001141 }
1142 break;
1143
1144 case 'x':
1145 /* this option and its parameter are ignored */
1146 argc--;
1147 argv++;
1148 if (argc > 0) {
1149 argc--;
1150 argv++;
1151 }
1152 break;
1153
1154 case 'C':
1155 case 'n':
1156 case 'm':
1157 case 'N':
1158 case 'L':
1159 case 'f':
1160 case 'p':
1161 case 'S':
1162 /* these options have only 1 parameter which must be copied and can start with a '-' */
1163 *newargv++ = *argv++;
1164 argc--;
1165 if (argc == 0)
1166 goto error;
1167 *newargv++ = *argv++;
1168 argc--;
1169 break;
1170 default:
1171 /* for other options just copy them without parameters, this is also done
1172 * for options like "--foo", but this will fail in the argument parser.
1173 * */
1174 *newargv++ = *argv++;
1175 argc--;
1176 break;
1177 }
William Lallemand73b85e72017-06-01 17:38:51 +02001178 }
1179 }
William Lallemand73b85e72017-06-01 17:38:51 +02001180 }
William Lallemand2bf6d622017-06-20 11:20:23 +02001181
William Lallemanddf6c5a82020-06-04 17:40:23 +02001182 return retargv;
1183
1184error:
1185 free(retargv);
1186 return NULL;
William Lallemand73b85e72017-06-01 17:38:51 +02001187}
1188
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001189
1190/* Performs basic random seed initialization. The main issue with this is that
1191 * srandom_r() only takes 32 bits and purposely provides a reproducible sequence,
1192 * which means that there will only be 4 billion possible random sequences once
1193 * srandom() is called, regardless of the internal state. Not calling it is
1194 * even worse as we'll always produce the same randoms sequences. What we do
1195 * here is to create an initial sequence from various entropy sources, hash it
1196 * using SHA1 and keep the resulting 160 bits available globally.
1197 *
1198 * We initialize the current process with the first 32 bits before starting the
1199 * polling loop, where all this will be changed to have process specific and
1200 * thread specific sequences.
Willy Tarreau52bf8392020-03-08 00:42:37 +01001201 *
1202 * Before starting threads, it's still possible to call random() as srandom()
1203 * is initialized from this, but after threads and/or processes are started,
1204 * only ha_random() is expected to be used to guarantee distinct sequences.
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001205 */
1206static void ha_random_boot(char *const *argv)
1207{
1208 unsigned char message[256];
1209 unsigned char *m = message;
1210 struct timeval tv;
1211 blk_SHA_CTX ctx;
1212 unsigned long l;
1213 int fd;
1214 int i;
1215
1216 /* start with current time as pseudo-random seed */
1217 gettimeofday(&tv, NULL);
1218 write_u32(m, tv.tv_sec); m += 4;
1219 write_u32(m, tv.tv_usec); m += 4;
1220
1221 /* PID and PPID add some OS-based randomness */
1222 write_u16(m, getpid()); m += 2;
1223 write_u16(m, getppid()); m += 2;
1224
1225 /* take up to 160 bits bytes from /dev/urandom if available (non-blocking) */
1226 fd = open("/dev/urandom", O_RDONLY);
1227 if (fd >= 0) {
1228 i = read(fd, m, 20);
1229 if (i > 0)
1230 m += i;
1231 close(fd);
1232 }
1233
1234 /* take up to 160 bits bytes from openssl (non-blocking) */
1235#ifdef USE_OPENSSL
1236 if (RAND_bytes(m, 20) == 1)
1237 m += 20;
1238#endif
1239
1240 /* take 160 bits from existing random in case it was already initialized */
1241 for (i = 0; i < 5; i++) {
1242 write_u32(m, random());
1243 m += 4;
1244 }
1245
1246 /* stack address (benefit form operating system's ASLR) */
1247 l = (unsigned long)&m;
1248 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1249
1250 /* argv address (benefit form operating system's ASLR) */
1251 l = (unsigned long)&argv;
1252 memcpy(m, &l, sizeof(l)); m += sizeof(l);
1253
1254 /* use tv_usec again after all the operations above */
1255 gettimeofday(&tv, NULL);
1256 write_u32(m, tv.tv_usec); m += 4;
1257
1258 /*
1259 * At this point, ~84-92 bytes have been used
1260 */
1261
1262 /* finish with the hostname */
1263 strncpy((char *)m, hostname, message + sizeof(message) - m);
1264 m += strlen(hostname);
1265
1266 /* total message length */
1267 l = m - message;
1268
1269 memset(&ctx, 0, sizeof(ctx));
1270 blk_SHA1_Init(&ctx);
1271 blk_SHA1_Update(&ctx, message, l);
1272 blk_SHA1_Final(boot_seed, &ctx);
1273
1274 srandom(read_u32(boot_seed));
Willy Tarreau52bf8392020-03-08 00:42:37 +01001275 ha_random_seed(boot_seed, sizeof(boot_seed));
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001276}
1277
Willy Tarreau5a023f02019-03-01 14:19:31 +01001278/* considers splicing proxies' maxconn, computes the ideal global.maxpipes
1279 * setting, and returns it. It may return -1 meaning "unlimited" if some
1280 * unlimited proxies have been found and the global.maxconn value is not yet
1281 * set. It may also return a value greater than maxconn if it's not yet set.
1282 * Note that a value of zero means there is no need for pipes. -1 is never
1283 * returned if global.maxconn is valid.
1284 */
1285static int compute_ideal_maxpipes()
1286{
1287 struct proxy *cur;
1288 int nbfe = 0, nbbe = 0;
1289 int unlimited = 0;
1290 int pipes;
1291 int max;
1292
1293 for (cur = proxies_list; cur; cur = cur->next) {
1294 if (cur->options2 & (PR_O2_SPLIC_ANY)) {
1295 if (cur->cap & PR_CAP_FE) {
1296 max = cur->maxconn;
1297 nbfe += max;
1298 if (!max) {
1299 unlimited = 1;
1300 break;
1301 }
1302 }
1303 if (cur->cap & PR_CAP_BE) {
1304 max = cur->fullconn ? cur->fullconn : global.maxconn;
1305 nbbe += max;
1306 if (!max) {
1307 unlimited = 1;
1308 break;
1309 }
1310 }
1311 }
1312 }
1313
1314 pipes = MAX(nbfe, nbbe);
1315 if (global.maxconn) {
1316 if (pipes > global.maxconn || unlimited)
1317 pipes = global.maxconn;
1318 } else if (unlimited) {
1319 pipes = -1;
1320 }
1321
1322 return pipes >= 4 ? pipes / 4 : pipes;
1323}
1324
Willy Tarreauac350932019-03-01 15:43:14 +01001325/* considers global.maxsocks, global.maxpipes, async engines, SSL frontends and
1326 * rlimits and computes an ideal maxconn. It's meant to be called only when
1327 * maxsock contains the sum of listening FDs, before it is updated based on
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001328 * maxconn and pipes. If there are not enough FDs left, DEFAULT_MAXCONN (by
1329 * default 100) is returned as it is expected that it will even run on tight
1330 * environments, and will maintain compatibility with previous packages that
1331 * used to rely on this value as the default one. The system will emit a
1332 * warning indicating how many FDs are missing anyway if needed.
Willy Tarreauac350932019-03-01 15:43:14 +01001333 */
1334static int compute_ideal_maxconn()
1335{
1336 int ssl_sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1337 int engine_fds = global.ssl_used_async_engines * ssl_sides;
1338 int pipes = compute_ideal_maxpipes();
Willy Tarreaub1beaa32020-03-06 10:25:31 +01001339 int remain = MAX(rlim_fd_cur_at_boot, rlim_fd_max_at_boot);
Willy Tarreauac350932019-03-01 15:43:14 +01001340 int maxconn;
1341
1342 /* we have to take into account these elements :
1343 * - number of engine_fds, which inflates the number of FD needed per
1344 * connection by this number.
1345 * - number of pipes per connection on average : for the unlimited
1346 * case, this is 0.5 pipe FDs per connection, otherwise it's a
1347 * fixed value of 2*pipes.
1348 * - two FDs per connection
1349 */
1350
1351 /* subtract listeners and checks */
1352 remain -= global.maxsock;
1353
Willy Tarreau3f200852019-03-14 19:13:17 +01001354 /* one epoll_fd/kqueue_fd per thread */
1355 remain -= global.nbthread;
1356
1357 /* one wake-up pipe (2 fd) per thread */
1358 remain -= 2 * global.nbthread;
1359
Willy Tarreauac350932019-03-01 15:43:14 +01001360 /* Fixed pipes values : we only subtract them if they're not larger
1361 * than the remaining FDs because pipes are optional.
1362 */
1363 if (pipes >= 0 && pipes * 2 < remain)
1364 remain -= pipes * 2;
1365
1366 if (pipes < 0) {
1367 /* maxsock = maxconn * 2 + maxconn/4 * 2 + maxconn * engine_fds.
1368 * = maxconn * (2 + 0.5 + engine_fds)
1369 * = maxconn * (4 + 1 + 2*engine_fds) / 2
1370 */
1371 maxconn = 2 * remain / (5 + 2 * engine_fds);
1372 } else {
1373 /* maxsock = maxconn * 2 + maxconn * engine_fds.
1374 * = maxconn * (2 + engine_fds)
1375 */
1376 maxconn = remain / (2 + engine_fds);
1377 }
1378
Willy Tarreaudf23c0c2019-03-13 10:10:49 +01001379 return MAX(maxconn, DEFAULT_MAXCONN);
Willy Tarreauac350932019-03-01 15:43:14 +01001380}
1381
Willy Tarreaua409f302020-03-10 17:08:53 +01001382/* computes the estimated maxsock value for the given maxconn based on the
1383 * possibly set global.maxpipes and existing partial global.maxsock. It may
1384 * temporarily change global.maxconn for the time needed to propagate the
1385 * computations, and will reset it.
1386 */
1387static int compute_ideal_maxsock(int maxconn)
1388{
1389 int maxpipes = global.maxpipes;
1390 int maxsock = global.maxsock;
1391
1392
1393 if (!maxpipes) {
1394 int old_maxconn = global.maxconn;
1395
1396 global.maxconn = maxconn;
1397 maxpipes = compute_ideal_maxpipes();
1398 global.maxconn = old_maxconn;
1399 }
1400
1401 maxsock += maxconn * 2; /* each connection needs two sockets */
1402 maxsock += maxpipes * 2; /* each pipe needs two FDs */
1403 maxsock += global.nbthread; /* one epoll_fd/kqueue_fd per thread */
1404 maxsock += 2 * global.nbthread; /* one wake-up pipe (2 fd) per thread */
1405
1406 /* compute fd used by async engines */
1407 if (global.ssl_used_async_engines) {
1408 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
1409
1410 maxsock += maxconn * sides * global.ssl_used_async_engines;
1411 }
1412 return maxsock;
1413}
1414
Thayne McCombs8f0cc5c2021-01-07 21:35:52 -07001415/* Tests if it is possible to set the current process's RLIMIT_NOFILE to
Willy Tarreau304e17e2020-03-10 17:54:54 +01001416 * <maxsock>, then sets it back to the previous value. Returns non-zero if the
1417 * value is accepted, non-zero otherwise. This is used to determine if an
1418 * automatic limit may be applied or not. When it is not, the caller knows that
1419 * the highest we can do is the rlim_max at boot. In case of error, we return
1420 * that the setting is possible, so that we defer the error processing to the
1421 * final stage in charge of enforcing this.
1422 */
1423static int check_if_maxsock_permitted(int maxsock)
1424{
1425 struct rlimit orig_limit, test_limit;
1426 int ret;
1427
1428 if (getrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1429 return 1;
1430
1431 /* don't go further if we can't even set to what we have */
1432 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1433 return 1;
1434
1435 test_limit.rlim_max = MAX(maxsock, orig_limit.rlim_max);
1436 test_limit.rlim_cur = test_limit.rlim_max;
1437 ret = setrlimit(RLIMIT_NOFILE, &test_limit);
1438
1439 if (setrlimit(RLIMIT_NOFILE, &orig_limit) != 0)
1440 return 1;
1441
1442 return ret == 0;
1443}
1444
Amaury Denoyelle484454d2021-05-05 16:18:45 +02001445void mark_tainted(const enum tainted_flags flag)
1446{
1447 HA_ATOMIC_OR(&tainted, flag);
1448}
1449
1450unsigned int get_tainted()
1451{
1452 int tainted_state;
1453 HA_ATOMIC_STORE(&tainted_state, tainted);
1454 return tainted_state;
1455}
Willy Tarreau304e17e2020-03-10 17:54:54 +01001456
William Lallemand73b85e72017-06-01 17:38:51 +02001457/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02001458 * This function initializes all the necessary variables. It only returns
1459 * if everything is OK. If something fails, it exits.
1460 */
Willy Tarreau1b5af7c2016-12-21 18:19:57 +01001461static void init(int argc, char **argv)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001462{
Willy Tarreaubaaee002006-06-26 02:48:02 +02001463 int arg_mode = 0; /* MODE_DEBUG, ... */
Willy Tarreaubaaee002006-06-26 02:48:02 +02001464 char *tmp;
1465 char *cfg_pidfile = NULL;
Willy Tarreau058e9072009-07-20 09:30:05 +02001466 int err_code = 0;
Maxime de Roucy0f503922016-05-13 23:52:55 +02001467 char *err_msg = NULL;
Willy Tarreau477ecd82010-01-03 21:12:30 +01001468 struct wordlist *wl;
Kevinm48936af2010-12-22 16:08:21 +00001469 char *progname;
Willy Tarreau576132e2011-09-10 19:26:56 +02001470 char *change_dir = NULL;
Christopher Fauletd7c91962015-04-30 11:48:27 +02001471 struct proxy *px;
Willy Tarreaue6945732016-12-21 19:57:00 +01001472 struct post_check_fct *pcf;
Willy Tarreauac350932019-03-01 15:43:14 +01001473 int ideal_maxconn;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001474
Christopher Faulete3a5e352017-10-24 13:53:54 +02001475 global.mode = MODE_STARTING;
William Lallemand00417412020-06-05 14:08:41 +02001476 old_argv = copy_argv(argc, argv);
1477 if (!old_argv) {
William Lallemanddf6c5a82020-06-04 17:40:23 +02001478 ha_alert("failed to copy argv.\n");
1479 exit(1);
1480 }
William Lallemand73b85e72017-06-01 17:38:51 +02001481
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001482 if (!init_trash_buffers(1)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001483 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet748919a2017-07-26 14:59:46 +02001484 exit(1);
1485 }
David du Colombier7af46052012-05-16 14:16:48 +02001486
Emeric Brun2b920a12010-09-23 18:30:22 +02001487 /* NB: POSIX does not make it mandatory for gethostname() to NULL-terminate
1488 * the string in case of truncation, and at least FreeBSD appears not to do
1489 * it.
1490 */
1491 memset(hostname, 0, sizeof(hostname));
1492 gethostname(hostname, sizeof(hostname) - 1);
Dragan Dosen4f014152020-06-18 16:56:47 +02001493
1494 if ((localpeer = strdup(hostname)) == NULL) {
1495 ha_alert("Cannot allocate memory for local peer.\n");
1496 exit(EXIT_FAILURE);
1497 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001498 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Emeric Brun2b920a12010-09-23 18:30:22 +02001499
William Lallemand24c928c2020-01-14 17:58:18 +01001500 /* we were in mworker mode, we should restart in mworker mode */
1501 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL)
1502 global.mode |= MODE_MWORKER;
1503
Willy Tarreaubaaee002006-06-26 02:48:02 +02001504 /*
1505 * Initialize the previously static variables.
1506 */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001507
Willy Tarreau173d9952018-01-26 21:48:23 +01001508 totalconn = actconn = listeners = stopping = 0;
Cyril Bonté203ec5a2017-03-23 22:44:13 +01001509 killed = 0;
Christopher Fauletcd7879a2017-10-27 13:53:47 +02001510
Willy Tarreaubaaee002006-06-26 02:48:02 +02001511
1512#ifdef HAPROXY_MEMMAX
Willy Tarreau70060452015-12-14 12:46:07 +01001513 global.rlimit_memmax_all = HAPROXY_MEMMAX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001514#endif
1515
Benoit GARNIERb413c2a2016-03-27 11:08:03 +02001516 tzset();
Willy Tarreauc4c80fb2021-04-11 15:00:34 +02001517 tv_init_process_date();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001518 start_date = now;
1519
Willy Tarreau6c3a6812020-03-06 18:57:15 +01001520 ha_random_boot(argv);
Willy Tarreau84310e22014-02-14 11:59:04 +01001521
Willy Tarreau8ed669b2013-01-11 15:49:37 +01001522 if (init_acl() != 0)
1523 exit(1);
Willy Tarreaub6b3df32018-11-26 16:31:20 +01001524
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001525 /* Initialise lua. */
1526 hlua_init();
Thierry FOURNIER6f1fd482015-01-23 14:06:13 +01001527
Christopher Fauletff2613e2016-11-09 11:36:17 +01001528 /* Initialize process vars */
Willy Tarreaucfc4f242021-05-08 11:41:28 +02001529 vars_init(&proc_vars, SCOPE_PROC);
Christopher Fauletff2613e2016-11-09 11:36:17 +01001530
Willy Tarreau43b78992009-01-25 15:42:27 +01001531 global.tune.options |= GTUNE_USE_SELECT; /* select() is always available */
Willy Tarreaue5733232019-05-22 19:24:06 +02001532#if defined(USE_POLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001533 global.tune.options |= GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001534#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001535#if defined(USE_EPOLL)
Willy Tarreau43b78992009-01-25 15:42:27 +01001536 global.tune.options |= GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001537#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001538#if defined(USE_KQUEUE)
Willy Tarreau43b78992009-01-25 15:42:27 +01001539 global.tune.options |= GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001540#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001541#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001542 global.tune.options |= GTUNE_USE_EVPORTS;
1543#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001544#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001545 global.tune.options |= GTUNE_USE_SPLICE;
1546#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001547#if defined(USE_GETADDRINFO)
1548 global.tune.options |= GTUNE_USE_GAI;
1549#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001550#if defined(SO_REUSEPORT)
1551 global.tune.options |= GTUNE_USE_REUSEPORT;
1552#endif
Willy Tarreau76cc6992020-07-01 18:49:24 +02001553#ifdef USE_THREAD
1554 global.tune.options |= GTUNE_IDLE_POOL_SHARED;
1555#endif
William Dauchya5194602020-03-28 19:29:58 +01001556 global.tune.options |= GTUNE_STRICT_LIMITS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001557
1558 pid = getpid();
1559 progname = *argv;
1560 while ((tmp = strchr(progname, '/')) != NULL)
1561 progname = tmp + 1;
1562
Kevinm48936af2010-12-22 16:08:21 +00001563 /* the process name is used for the logs only */
Eric Salama7cea6062020-10-02 11:58:19 +02001564 chunk_initlen(&global.log_tag, strdup(progname), strlen(progname), strlen(progname));
1565 if (b_orig(&global.log_tag) == NULL) {
1566 chunk_destroy(&global.log_tag);
1567 ha_alert("Cannot allocate memory for log_tag.\n");
1568 exit(EXIT_FAILURE);
1569 }
Kevinm48936af2010-12-22 16:08:21 +00001570
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 argc--; argv++;
1572 while (argc > 0) {
1573 char *flag;
1574
1575 if (**argv == '-') {
1576 flag = *argv+1;
1577
1578 /* 1 arg */
1579 if (*flag == 'v') {
1580 display_version();
Willy Tarreau7b066db2007-12-02 11:28:59 +01001581 if (flag[1] == 'v') /* -vv */
1582 display_build_opts();
Willy Tarreaubaaee002006-06-26 02:48:02 +02001583 exit(0);
1584 }
Willy Tarreaue5733232019-05-22 19:24:06 +02001585#if defined(USE_EPOLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 else if (*flag == 'd' && flag[1] == 'e')
Willy Tarreau43b78992009-01-25 15:42:27 +01001587 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001588#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001589#if defined(USE_POLL)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001590 else if (*flag == 'd' && flag[1] == 'p')
Willy Tarreau43b78992009-01-25 15:42:27 +01001591 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001593#if defined(USE_KQUEUE)
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001594 else if (*flag == 'd' && flag[1] == 'k')
Willy Tarreau43b78992009-01-25 15:42:27 +01001595 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreau1e63130a2007-04-09 12:03:06 +02001596#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001597#if defined(USE_EVPORTS)
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00001598 else if (*flag == 'd' && flag[1] == 'v')
1599 global.tune.options &= ~GTUNE_USE_EVPORTS;
1600#endif
Willy Tarreaue5733232019-05-22 19:24:06 +02001601#if defined(USE_LINUX_SPLICE)
Willy Tarreau3ab68cf2009-01-25 16:03:28 +01001602 else if (*flag == 'd' && flag[1] == 'S')
1603 global.tune.options &= ~GTUNE_USE_SPLICE;
1604#endif
Nenad Merdanovic88afe032014-04-14 15:56:58 +02001605#if defined(USE_GETADDRINFO)
1606 else if (*flag == 'd' && flag[1] == 'G')
1607 global.tune.options &= ~GTUNE_USE_GAI;
1608#endif
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +00001609#if defined(SO_REUSEPORT)
1610 else if (*flag == 'd' && flag[1] == 'R')
1611 global.tune.options &= ~GTUNE_USE_REUSEPORT;
1612#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001613 else if (*flag == 'd' && flag[1] == 'V')
1614 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001615 else if (*flag == 'V')
1616 arg_mode |= MODE_VERBOSE;
1617 else if (*flag == 'd' && flag[1] == 'b')
1618 arg_mode |= MODE_FOREGROUND;
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001619 else if (*flag == 'd' && flag[1] == 'D')
1620 arg_mode |= MODE_DIAG;
Willy Tarreau3eb10b82020-04-15 16:42:39 +02001621 else if (*flag == 'd' && flag[1] == 'W')
1622 arg_mode |= MODE_ZERO_WARNING;
Willy Tarreau6e064432012-05-08 15:40:42 +02001623 else if (*flag == 'd' && flag[1] == 'M')
1624 mem_poison_byte = flag[2] ? strtol(flag + 2, NULL, 0) : 'P';
Willy Tarreau3eed10e2016-11-07 21:03:16 +01001625 else if (*flag == 'd' && flag[1] == 'r')
1626 global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
Willy Tarreau0aa9dbe2021-12-28 15:43:11 +01001627#if defined(HA_HAVE_DUMP_LIBS)
1628 else if (*flag == 'd' && flag[1] == 'L')
1629 arg_mode |= MODE_DUMP_LIBS;
1630#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001631 else if (*flag == 'd')
1632 arg_mode |= MODE_DEBUG;
1633 else if (*flag == 'c')
1634 arg_mode |= MODE_CHECK;
William Lallemand095ba4c2017-06-01 17:38:50 +02001635 else if (*flag == 'D')
Willy Tarreau6bde87b2009-05-18 16:29:51 +02001636 arg_mode |= MODE_DAEMON;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001637 else if (*flag == 'W' && flag[1] == 's') {
Lukas Tribusf46bf952017-11-21 12:39:34 +01001638 arg_mode |= MODE_MWORKER | MODE_FOREGROUND;
Tim Duesterhusd6942c82017-11-20 15:58:35 +01001639#if defined(USE_SYSTEMD)
1640 global.tune.options |= GTUNE_USE_SYSTEMD;
1641#else
Christopher Faulet767a84b2017-11-24 16:50:31 +01001642 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 +01001643 usage(progname);
1644#endif
1645 }
William Lallemand095ba4c2017-06-01 17:38:50 +02001646 else if (*flag == 'W')
1647 arg_mode |= MODE_MWORKER;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001648 else if (*flag == 'q')
1649 arg_mode |= MODE_QUIET;
Olivier Houchardf73629d2017-04-05 22:33:04 +02001650 else if (*flag == 'x') {
William Lallemand4f71d302020-06-04 23:41:29 +02001651 if (argc <= 1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001652 ha_alert("Unix socket path expected with the -x flag\n\n");
William Lallemand45eff442017-06-19 15:57:55 +02001653 usage(progname);
Olivier Houchardf73629d2017-04-05 22:33:04 +02001654 }
William Lallemand4fc09692017-06-19 16:37:19 +02001655 if (old_unixsocket)
Christopher Faulet767a84b2017-11-24 16:50:31 +01001656 ha_warning("-x option already set, overwriting the value\n");
Olivier Houchardf73629d2017-04-05 22:33:04 +02001657 old_unixsocket = argv[1];
William Lallemand4fc09692017-06-19 16:37:19 +02001658
Olivier Houchardf73629d2017-04-05 22:33:04 +02001659 argv++;
1660 argc--;
1661 }
William Lallemande7361152018-10-26 14:47:36 +02001662 else if (*flag == 'S') {
1663 struct wordlist *c;
1664
William Lallemanda6b32492020-06-04 23:49:20 +02001665 if (argc <= 1) {
William Lallemande7361152018-10-26 14:47:36 +02001666 ha_alert("Socket and optional bind parameters expected with the -S flag\n");
1667 usage(progname);
1668 }
1669 if ((c = malloc(sizeof(*c))) == NULL || (c->s = strdup(argv[1])) == NULL) {
1670 ha_alert("Cannot allocate memory\n");
1671 exit(EXIT_FAILURE);
1672 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001673 LIST_INSERT(&mworker_cli_conf, &c->list);
William Lallemande7361152018-10-26 14:47:36 +02001674
1675 argv++;
1676 argc--;
1677 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001678 else if (*flag == 's' && (flag[1] == 'f' || flag[1] == 't')) {
1679 /* list of pids to finish ('f') or terminate ('t') */
1680
1681 if (flag[1] == 'f')
1682 oldpids_sig = SIGUSR1; /* finish then exit */
1683 else
1684 oldpids_sig = SIGTERM; /* terminate immediately */
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001685 while (argc > 1 && argv[1][0] != '-') {
Chris Lane236062f2018-02-05 23:15:44 +00001686 char * endptr = NULL;
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001687 oldpids = realloc(oldpids, (nb_oldpids + 1) * sizeof(int));
1688 if (!oldpids) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001689 ha_alert("Cannot allocate old pid : out of memory.\n");
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001690 exit(1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001691 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001692 argc--; argv++;
Chris Lane236062f2018-02-05 23:15:44 +00001693 errno = 0;
1694 oldpids[nb_oldpids] = strtol(*argv, &endptr, 10);
1695 if (errno) {
1696 ha_alert("-%2s option: failed to parse {%s}: %s\n",
1697 flag,
1698 *argv, strerror(errno));
1699 exit(1);
1700 } else if (endptr && strlen(endptr)) {
Willy Tarreau90807112020-02-25 08:16:33 +01001701 while (isspace((unsigned char)*endptr)) endptr++;
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001702 if (*endptr != 0) {
Chris Lane236062f2018-02-05 23:15:44 +00001703 ha_alert("-%2s option: some bytes unconsumed in PID list {%s}\n",
1704 flag, endptr);
1705 exit(1);
Aurélien Nephtali39b89882018-02-17 20:53:11 +01001706 }
Chris Lane236062f2018-02-05 23:15:44 +00001707 }
Willy Tarreauc6ca1aa2015-10-08 11:32:32 +02001708 if (oldpids[nb_oldpids] <= 0)
1709 usage(progname);
1710 nb_oldpids++;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001711 }
1712 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001713 else if (flag[0] == '-' && flag[1] == 0) { /* "--" */
1714 /* now that's a cfgfile list */
1715 argv++; argc--;
1716 while (argc > 0) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02001717 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001718 ha_alert("Cannot load configuration file/directory %s : %s\n",
1719 *argv,
1720 err_msg);
Willy Tarreaua088d312015-10-08 11:58:48 +02001721 exit(1);
1722 }
Willy Tarreaua088d312015-10-08 11:58:48 +02001723 argv++; argc--;
1724 }
1725 break;
1726 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001727 else { /* >=2 args */
1728 argv++; argc--;
1729 if (argc == 0)
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001730 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001731
1732 switch (*flag) {
Willy Tarreau576132e2011-09-10 19:26:56 +02001733 case 'C' : change_dir = *argv; break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001734 case 'n' : cfg_maxconn = atol(*argv); break;
Willy Tarreau70060452015-12-14 12:46:07 +01001735 case 'm' : global.rlimit_memmax_all = atol(*argv); break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 case 'N' : cfg_maxpconn = atol(*argv); break;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001737 case 'L' :
Dragan Dosen4f014152020-06-18 16:56:47 +02001738 free(localpeer);
1739 if ((localpeer = strdup(*argv)) == NULL) {
1740 ha_alert("Cannot allocate memory for local peer.\n");
1741 exit(EXIT_FAILURE);
1742 }
William Lallemanddaf4cd22018-04-17 16:46:13 +02001743 setenv("HAPROXY_LOCALPEER", localpeer, 1);
Dragan Dosen13cd54c2020-06-18 18:24:05 +02001744 global.localpeer_cmdline = 1;
William Lallemanddaf4cd22018-04-17 16:46:13 +02001745 break;
Willy Tarreau5d01a632009-06-22 16:02:30 +02001746 case 'f' :
Maxime de Roucy0f503922016-05-13 23:52:55 +02001747 if (!list_append_word(&cfg_cfgfiles, *argv, &err_msg)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001748 ha_alert("Cannot load configuration file/directory %s : %s\n",
1749 *argv,
1750 err_msg);
Willy Tarreau5d01a632009-06-22 16:02:30 +02001751 exit(1);
1752 }
Willy Tarreau5d01a632009-06-22 16:02:30 +02001753 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001754 case 'p' : cfg_pidfile = *argv; break;
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001755 default: usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001756 }
1757 }
1758 }
1759 else
Willy Tarreau3bafcdc2011-09-10 19:20:23 +02001760 usage(progname);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001761 argv++; argc--;
1762 }
1763
Christopher Faulete3a5e352017-10-24 13:53:54 +02001764 global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
Amaury Denoyelle7b01a8d2021-03-29 10:29:07 +02001765 | MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
Willy Tarreau0aa9dbe2021-12-28 15:43:11 +01001766 | MODE_DIAG | MODE_DUMP_LIBS));
Willy Tarreaubaaee002006-06-26 02:48:02 +02001767
William Lallemand944e6192018-11-21 15:48:31 +01001768 if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001769 unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
William Lallemand944e6192018-11-21 15:48:31 +01001770 global.mode |= MODE_MWORKER_WAIT;
1771 global.mode &= ~MODE_MWORKER;
William Lallemandcb11fd22017-06-01 17:38:52 +02001772 }
1773
Willy Tarreau7a534eb2021-07-21 10:01:36 +02001774 if ((global.mode & (MODE_MWORKER | MODE_CHECK)) == MODE_MWORKER &&
1775 (getenv("HAPROXY_MWORKER_REEXEC") != NULL)) {
William Lallemandcb11fd22017-06-01 17:38:52 +02001776 atexit_flag = 1;
1777 atexit(reexec_on_failure);
1778 }
1779
Willy Tarreau576132e2011-09-10 19:26:56 +02001780 if (change_dir && chdir(change_dir) < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001781 ha_alert("Could not change to directory %s : %s\n", change_dir, strerror(errno));
Willy Tarreau576132e2011-09-10 19:26:56 +02001782 exit(1);
1783 }
1784
Willy Tarreaubaaee002006-06-26 02:48:02 +02001785 global.maxsock = 10; /* reserve 10 fds ; will be incremented by socket eaters */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001786
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001787#ifdef USE_CPU_AFFINITY
1788 {
1789 int i;
1790 for (i = 0; i < MAX_PROCS; ++i) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02001791 ha_cpuset_zero(&cpu_map.proc[i]);
1792 ha_cpuset_zero(&cpu_map.proc_t1[i]);
Willy Tarreau26f42a02021-05-14 08:26:38 +02001793 }
1794 for (i = 0; i < MAX_THREADS; ++i) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02001795 ha_cpuset_zero(&cpu_map.thread[i]);
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001796 }
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001797 }
Amaury Denoyellea6f9c5d2021-04-23 16:58:08 +02001798#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02001799
William Lallemand944e6192018-11-21 15:48:31 +01001800 /* in wait mode, we don't try to read the configuration files */
1801 if (!(global.mode & MODE_MWORKER_WAIT)) {
Christopher Faulet4e366822021-01-12 18:57:38 +01001802 char *env_cfgfiles = NULL;
1803 int env_err = 0;
Willy Tarreauc4382422009-12-06 13:10:44 +01001804
William Lallemand944e6192018-11-21 15:48:31 +01001805 /* handle cfgfiles that are actually directories */
1806 cfgfiles_expand_directories();
1807
1808 if (LIST_ISEMPTY(&cfg_cfgfiles))
1809 usage(progname);
1810
1811
1812 list_for_each_entry(wl, &cfg_cfgfiles, list) {
1813 int ret;
1814
Christopher Faulet4e366822021-01-12 18:57:38 +01001815 if (env_err == 0) {
1816 if (!memprintf(&env_cfgfiles, "%s%s%s",
1817 (env_cfgfiles ? env_cfgfiles : ""),
1818 (env_cfgfiles ? ";" : ""), wl->s))
1819 env_err = 1;
1820 }
William Lallemand7b302d82019-05-20 11:15:37 +02001821
William Lallemand944e6192018-11-21 15:48:31 +01001822 ret = readcfgfile(wl->s);
1823 if (ret == -1) {
1824 ha_alert("Could not open configuration file %s : %s\n",
1825 wl->s, strerror(errno));
Christopher Faulet4e366822021-01-12 18:57:38 +01001826 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001827 exit(1);
1828 }
1829 if (ret & (ERR_ABORT|ERR_FATAL))
1830 ha_alert("Error(s) found in configuration file : %s\n", wl->s);
1831 err_code |= ret;
Christopher Faulet4e366822021-01-12 18:57:38 +01001832 if (err_code & ERR_ABORT) {
1833 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001834 exit(1);
Christopher Faulet4e366822021-01-12 18:57:38 +01001835 }
Willy Tarreauc4382422009-12-06 13:10:44 +01001836 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001837
William Lallemand944e6192018-11-21 15:48:31 +01001838 /* do not try to resolve arguments nor to spot inconsistencies when
1839 * the configuration contains fatal errors caused by files not found
1840 * or failed memory allocations.
1841 */
1842 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1843 ha_alert("Fatal errors found in configuration.\n");
Christopher Faulet4e366822021-01-12 18:57:38 +01001844 free(env_cfgfiles);
William Lallemand944e6192018-11-21 15:48:31 +01001845 exit(1);
1846 }
Christopher Faulet4e366822021-01-12 18:57:38 +01001847 if (env_err) {
1848 ha_alert("Could not allocate memory for HAPROXY_CFGFILES env variable\n");
1849 exit(1);
1850 }
1851 setenv("HAPROXY_CFGFILES", env_cfgfiles, 1);
1852 free(env_cfgfiles);
William Lallemand7b302d82019-05-20 11:15:37 +02001853
Willy Tarreaub83dc3d2017-04-19 11:24:07 +02001854 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001855 if (global.mode & MODE_MWORKER) {
1856 int proc;
William Lallemand16dd1b32018-11-19 18:46:18 +01001857 struct mworker_proc *tmproc;
1858
William Lallemand482f9a92019-04-12 16:15:00 +02001859 setenv("HAPROXY_MWORKER", "1", 1);
1860
William Lallemand16dd1b32018-11-19 18:46:18 +01001861 if (getenv("HAPROXY_MWORKER_REEXEC") == NULL) {
1862
William Lallemandf3a86832019-04-01 11:29:58 +02001863 tmproc = calloc(1, sizeof(*tmproc));
William Lallemand16dd1b32018-11-19 18:46:18 +01001864 if (!tmproc) {
1865 ha_alert("Cannot allocate process structures.\n");
1866 exit(EXIT_FAILURE);
1867 }
William Lallemand8f7069a2019-04-12 16:09:23 +02001868 tmproc->options |= PROC_O_TYPE_MASTER; /* master */
William Lallemand16dd1b32018-11-19 18:46:18 +01001869 tmproc->reloads = 0;
1870 tmproc->relative_pid = 0;
1871 tmproc->pid = pid;
1872 tmproc->timestamp = start_date.tv_sec;
1873 tmproc->ipc_fd[0] = -1;
1874 tmproc->ipc_fd[1] = -1;
1875
1876 proc_self = tmproc;
1877
Willy Tarreau2b718102021-04-21 07:32:39 +02001878 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemand16dd1b32018-11-19 18:46:18 +01001879 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001880
1881 for (proc = 0; proc < global.nbproc; proc++) {
William Lallemandce83b4a2018-10-26 14:47:30 +02001882
William Lallemandf3a86832019-04-01 11:29:58 +02001883 tmproc = calloc(1, sizeof(*tmproc));
William Lallemandce83b4a2018-10-26 14:47:30 +02001884 if (!tmproc) {
1885 ha_alert("Cannot allocate process structures.\n");
1886 exit(EXIT_FAILURE);
1887 }
1888
William Lallemand8f7069a2019-04-12 16:09:23 +02001889 tmproc->options |= PROC_O_TYPE_WORKER; /* worker */
William Lallemandce83b4a2018-10-26 14:47:30 +02001890 tmproc->pid = -1;
1891 tmproc->reloads = 0;
William Lallemande3683302018-11-19 18:46:17 +01001892 tmproc->timestamp = -1;
William Lallemandce83b4a2018-10-26 14:47:30 +02001893 tmproc->relative_pid = 1 + proc;
William Lallemand550db6d2018-11-06 17:37:12 +01001894 tmproc->ipc_fd[0] = -1;
1895 tmproc->ipc_fd[1] = -1;
William Lallemandce83b4a2018-10-26 14:47:30 +02001896
1897 if (mworker_cli_sockpair_new(tmproc, proc) < 0) {
1898 exit(EXIT_FAILURE);
1899 }
1900
Willy Tarreau2b718102021-04-21 07:32:39 +02001901 LIST_APPEND(&proc_list, &tmproc->list);
William Lallemandce83b4a2018-10-26 14:47:30 +02001902 }
William Lallemand944e6192018-11-21 15:48:31 +01001903 }
1904 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
1905 struct wordlist *it, *c;
1906
Remi Tricot-Le Bretond90aa342021-05-19 10:45:12 +02001907 /* get the info of the children in the env */
1908 if (mworker_env_to_proc_list() < 0) {
1909 exit(EXIT_FAILURE);
1910 }
William Lallemande7361152018-10-26 14:47:36 +02001911
William Lallemand550db6d2018-11-06 17:37:12 +01001912 if (!LIST_ISEMPTY(&mworker_cli_conf)) {
William Lallemande7361152018-10-26 14:47:36 +02001913
William Lallemand550db6d2018-11-06 17:37:12 +01001914 if (mworker_cli_proxy_create() < 0) {
William Lallemande7361152018-10-26 14:47:36 +02001915 ha_alert("Can't create the master's CLI.\n");
1916 exit(EXIT_FAILURE);
1917 }
William Lallemande7361152018-10-26 14:47:36 +02001918
William Lallemand550db6d2018-11-06 17:37:12 +01001919 list_for_each_entry_safe(c, it, &mworker_cli_conf, list) {
1920
1921 if (mworker_cli_proxy_new_listener(c->s) < 0) {
1922 ha_alert("Can't create the master's CLI.\n");
1923 exit(EXIT_FAILURE);
1924 }
Willy Tarreau2b718102021-04-21 07:32:39 +02001925 LIST_DELETE(&c->list);
William Lallemand550db6d2018-11-06 17:37:12 +01001926 free(c->s);
1927 free(c);
1928 }
1929 }
William Lallemandce83b4a2018-10-26 14:47:30 +02001930 }
1931
Eric Salama5ba83352021-03-16 15:11:17 +01001932 if (!LIST_ISEMPTY(&mworker_cli_conf) && !(arg_mode & MODE_MWORKER)) {
1933 ha_warning("a master CLI socket was defined, but master-worker mode (-W) is not enabled.\n");
1934 }
1935
Willy Tarreauf42d7942020-10-20 11:54:49 +02001936 if (global.nbproc > 1 && !global.nbthread) {
1937 ha_warning("nbproc is deprecated!\n"
1938 " | For suffering many limitations, the 'nbproc' directive is now deprecated\n"
1939 " | and scheduled for removal in 2.5. Just comment it out: haproxy will use\n"
1940 " | threads and will run on all allocated processors. You may also switch to\n"
1941 " | 'nbthread %d' to keep the same number of processors. If you absolutely\n"
1942 " | want to run in multi-process mode, you can silence this warning by adding\n"
1943 " | 'nbthread 1', but then please report your use case to developers.\n",
1944 global.nbproc);
1945 }
1946
Willy Tarreaue90904d2021-02-12 14:08:31 +01001947 /* defaults sections are not needed anymore */
1948 proxy_destroy_all_defaults();
1949
Willy Tarreaubb925012009-07-23 13:36:36 +02001950 err_code |= check_config_validity();
Christopher Fauletc1692962019-08-12 09:51:07 +02001951 for (px = proxies_list; px; px = px->next) {
1952 struct server *srv;
1953 struct post_proxy_check_fct *ppcf;
1954 struct post_server_check_fct *pscf;
1955
Christopher Fauletd5bd8242020-11-02 16:20:13 +01001956 if (px->disabled)
1957 continue;
1958
Christopher Fauletc1692962019-08-12 09:51:07 +02001959 list_for_each_entry(pscf, &post_server_check_list, list) {
1960 for (srv = px->srv; srv; srv = srv->next)
1961 err_code |= pscf->fct(srv);
1962 }
1963 list_for_each_entry(ppcf, &post_proxy_check_list, list)
1964 err_code |= ppcf->fct(px);
1965 }
Willy Tarreaubb925012009-07-23 13:36:36 +02001966 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001967 ha_alert("Fatal errors found in configuration.\n");
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001968 exit(1);
1969 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001970
Carl Henrik Lundef91ac192020-02-27 16:45:50 +01001971 err_code |= pattern_finalize_config();
1972 if (err_code & (ERR_ABORT|ERR_FATAL)) {
1973 ha_alert("Failed to finalize pattern config.\n");
1974 exit(1);
1975 }
Willy Tarreau0f936722019-04-11 14:47:08 +02001976
Willy Tarreau70060452015-12-14 12:46:07 +01001977 /* recompute the amount of per-process memory depending on nbproc and
1978 * the shared SSL cache size (allowed to exist in all processes).
1979 */
1980 if (global.rlimit_memmax_all) {
1981#if defined (USE_OPENSSL) && !defined(USE_PRIVATE_CACHE)
1982 int64_t ssl_cache_bytes = global.tune.sslcachesize * 200LL;
1983
1984 global.rlimit_memmax =
1985 ((((int64_t)global.rlimit_memmax_all * 1048576LL) -
1986 ssl_cache_bytes) / global.nbproc +
1987 ssl_cache_bytes + 1048575LL) / 1048576LL;
1988#else
1989 global.rlimit_memmax = global.rlimit_memmax_all / global.nbproc;
1990#endif
1991 }
1992
Willy Tarreaue5733232019-05-22 19:24:06 +02001993#ifdef USE_NS
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01001994 err_code |= netns_init();
1995 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01001996 ha_alert("Failed to initialize namespace support.\n");
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01001997 exit(1);
1998 }
1999#endif
2000
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002001 /* Apply server states */
2002 apply_server_state();
2003
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002004 for (px = proxies_list; px; px = px->next)
Baptiste Assmann4215d7d2016-11-02 15:33:15 +01002005 srv_compute_all_admin_states(px);
2006
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002007 /* Apply servers' configured address */
2008 err_code |= srv_init_addr();
2009 if (err_code & (ERR_ABORT|ERR_FATAL)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002010 ha_alert("Failed to initialize server(s) addr.\n");
Baptiste Assmann83cbaa52016-11-02 15:34:05 +01002011 exit(1);
2012 }
2013
Willy Tarreau3eb10b82020-04-15 16:42:39 +02002014 if (warned & WARN_ANY && global.mode & MODE_ZERO_WARNING) {
2015 ha_alert("Some warnings were found and 'zero-warning' is set. Aborting.\n");
2016 exit(1);
2017 }
2018
Willy Tarreau0aa9dbe2021-12-28 15:43:11 +01002019#if defined(HA_HAVE_DUMP_LIBS)
2020 if (global.mode & MODE_DUMP_LIBS) {
2021 qfprintf(stdout, "List of loaded object files:\n");
2022 chunk_reset(&trash);
2023 if (dump_libs(&trash, 0))
2024 printf("%s", trash.area);
2025 }
2026#endif
2027
Willy Tarreaubaaee002006-06-26 02:48:02 +02002028 if (global.mode & MODE_CHECK) {
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002029 struct peers *pr;
2030 struct proxy *px;
2031
Willy Tarreaubebd2122020-04-15 16:06:11 +02002032 if (warned & WARN_ANY)
2033 qfprintf(stdout, "Warnings were found.\n");
2034
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02002035 for (pr = cfg_peers; pr; pr = pr->next)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002036 if (pr->peers_fe)
2037 break;
2038
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002039 for (px = proxies_list; px; px = px->next)
Willy Tarreauc3914d42020-09-24 08:39:22 +02002040 if (!px->disabled && px->li_all)
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002041 break;
2042
Emeric Brun3a9c0002021-08-13 09:32:50 +02002043 if (!px) {
2044 /* We may only have log-forward section */
2045 for (px = cfg_log_forward; px; px = px->next)
2046 if (!px->disabled && px->li_all)
2047 break;
2048 }
2049
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002050 if (pr || px) {
2051 /* At least one peer or one listener has been found */
2052 qfprintf(stdout, "Configuration file is valid\n");
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02002053 deinit_and_exit(0);
Willy Tarreau8b15ba12012-02-02 17:48:18 +01002054 }
2055 qfprintf(stdout, "Configuration file has no error but will not start (no listener) => exit(2).\n");
2056 exit(2);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002057 }
Willy Tarreaue9b26022011-08-01 20:57:55 +02002058
Amaury Denoyelle5a6926d2021-03-30 17:34:24 +02002059 if (global.mode & MODE_DIAG) {
2060 cfg_run_diagnostics();
2061 }
2062
Willy Tarreau8263d2b2012-08-28 00:06:31 +02002063 /* now we know the buffer size, we can initialize the channels and buffers */
Willy Tarreau9b28e032012-10-12 23:49:43 +02002064 init_buffer();
Willy Tarreau8280d642009-09-23 23:37:52 +02002065
Willy Tarreaue6945732016-12-21 19:57:00 +01002066 list_for_each_entry(pcf, &post_check_list, list) {
2067 err_code |= pcf->fct();
2068 if (err_code & (ERR_ABORT|ERR_FATAL))
2069 exit(1);
2070 }
2071
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072 if (cfg_maxconn > 0)
2073 global.maxconn = cfg_maxconn;
2074
Willy Tarreau4975d142021-03-13 11:00:33 +01002075 if (global.cli_fe)
2076 global.maxsock += global.cli_fe->maxconn;
Willy Tarreau8d687d82019-03-01 09:39:42 +01002077
2078 if (cfg_peers) {
2079 /* peers also need to bypass global maxconn */
2080 struct peers *p = cfg_peers;
2081
2082 for (p = cfg_peers; p; p = p->next)
2083 if (p->peers_fe)
2084 global.maxsock += p->peers_fe->maxconn;
2085 }
2086
Willy Tarreaubaaee002006-06-26 02:48:02 +02002087 if (cfg_pidfile) {
Willy Tarreaua534fea2008-08-03 12:19:50 +02002088 free(global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002089 global.pidfile = strdup(cfg_pidfile);
2090 }
2091
Willy Tarreaud0256482015-01-15 21:45:22 +01002092 /* Now we want to compute the maxconn and possibly maxsslconn values.
Willy Tarreauac350932019-03-01 15:43:14 +01002093 * It's a bit tricky. Maxconn defaults to the pre-computed value based
2094 * on rlim_fd_cur and the number of FDs in use due to the configuration,
2095 * and maxsslconn defaults to DEFAULT_MAXSSLCONN. On top of that we can
2096 * enforce a lower limit based on memmax.
Willy Tarreaud0256482015-01-15 21:45:22 +01002097 *
2098 * If memmax is set, then it depends on which values are set. If
2099 * maxsslconn is set, we use memmax to determine how many cleartext
2100 * connections may be added, and set maxconn to the sum of the two.
2101 * If maxconn is set and not maxsslconn, maxsslconn is computed from
2102 * the remaining amount of memory between memmax and the cleartext
2103 * connections. If neither are set, then it is considered that all
2104 * connections are SSL-capable, and maxconn is computed based on this,
2105 * then maxsslconn accordingly. We need to know if SSL is used on the
2106 * frontends, backends, or both, because when it's used on both sides,
2107 * we need twice the value for maxsslconn, but we only count the
2108 * handshake once since it is not performed on the two sides at the
2109 * same time (frontend-side is terminated before backend-side begins).
2110 * The SSL stack is supposed to have filled ssl_session_cost and
Willy Tarreau474b96a2015-01-28 19:03:21 +01002111 * ssl_handshake_cost during its initialization. In any case, if
2112 * SYSTEM_MAXCONN is set, we still enforce it as an upper limit for
2113 * maxconn in order to protect the system.
Willy Tarreaud0256482015-01-15 21:45:22 +01002114 */
Willy Tarreauac350932019-03-01 15:43:14 +01002115 ideal_maxconn = compute_ideal_maxconn();
2116
Willy Tarreaud0256482015-01-15 21:45:22 +01002117 if (!global.rlimit_memmax) {
2118 if (global.maxconn == 0) {
Willy Tarreauac350932019-03-01 15:43:14 +01002119 global.maxconn = ideal_maxconn;
Willy Tarreaud0256482015-01-15 21:45:22 +01002120 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2121 fprintf(stderr, "Note: setting global.maxconn to %d.\n", global.maxconn);
2122 }
2123 }
2124#ifdef USE_OPENSSL
2125 else if (!global.maxconn && !global.maxsslconn &&
2126 (global.ssl_used_frontend || global.ssl_used_backend)) {
2127 /* memmax is set, compute everything automatically. Here we want
2128 * to ensure that all SSL connections will be served. We take
2129 * care of the number of sides where SSL is used, and consider
2130 * the worst case : SSL used on both sides and doing a handshake
2131 * simultaneously. Note that we can't have more than maxconn
2132 * handshakes at a time by definition, so for the worst case of
2133 * two SSL conns per connection, we count a single handshake.
2134 */
2135 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2136 int64_t mem = global.rlimit_memmax * 1048576ULL;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002137 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002138
2139 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2140 mem -= global.maxzlibmem;
2141 mem = mem * MEM_USABLE_RATIO;
2142
Willy Tarreau304e17e2020-03-10 17:54:54 +01002143 /* Principle: we test once to set maxconn according to the free
2144 * memory. If it results in values the system rejects, we try a
2145 * second time by respecting rlim_fd_max. If it fails again, we
2146 * go back to the initial value and will let the final code
2147 * dealing with rlimit report the error. That's up to 3 attempts.
2148 */
2149 do {
2150 global.maxconn = mem /
2151 ((STREAM_MAX_COST + 2 * global.tune.bufsize) + // stream + 2 buffers per stream
2152 sides * global.ssl_session_max_cost + // SSL buffers, one per side
2153 global.ssl_handshake_max_cost); // 1 handshake per connection max
Willy Tarreaud0256482015-01-15 21:45:22 +01002154
Willy Tarreau304e17e2020-03-10 17:54:54 +01002155 if (retried == 1)
2156 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2157 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002158#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002159 if (global.maxconn > SYSTEM_MAXCONN)
2160 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002161#endif /* SYSTEM_MAXCONN */
Willy Tarreau304e17e2020-03-10 17:54:54 +01002162 global.maxsslconn = sides * global.maxconn;
2163
2164 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2165 break;
2166 } while (retried++ < 2);
2167
Willy Tarreaud0256482015-01-15 21:45:22 +01002168 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2169 fprintf(stderr, "Note: setting global.maxconn to %d and global.maxsslconn to %d.\n",
2170 global.maxconn, global.maxsslconn);
2171 }
2172 else if (!global.maxsslconn &&
2173 (global.ssl_used_frontend || global.ssl_used_backend)) {
2174 /* memmax and maxconn are known, compute maxsslconn automatically.
2175 * maxsslconn being forced, we don't know how many of it will be
2176 * on each side if both sides are being used. The worst case is
2177 * when all connections use only one SSL instance because
2178 * handshakes may be on two sides at the same time.
2179 */
2180 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2181 int64_t mem = global.rlimit_memmax * 1048576ULL;
2182 int64_t sslmem;
2183
2184 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2185 mem -= global.maxzlibmem;
2186 mem = mem * MEM_USABLE_RATIO;
2187
Willy Tarreau87b09662015-04-03 00:22:06 +02002188 sslmem = mem - global.maxconn * (int64_t)(STREAM_MAX_COST + 2 * global.tune.bufsize);
Willy Tarreaud0256482015-01-15 21:45:22 +01002189 global.maxsslconn = sslmem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost);
2190 global.maxsslconn = round_2dig(global.maxsslconn);
2191
2192 if (sslmem <= 0 || global.maxsslconn < sides) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002193 ha_alert("Cannot compute the automatic maxsslconn because global.maxconn is already too "
2194 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2195 "without SSL is %d, but %d was found and SSL is in use.\n",
2196 global.rlimit_memmax,
2197 (int)(mem / (STREAM_MAX_COST + 2 * global.tune.bufsize)),
2198 global.maxconn);
Willy Tarreaud0256482015-01-15 21:45:22 +01002199 exit(1);
2200 }
2201
2202 if (global.maxsslconn > sides * global.maxconn)
2203 global.maxsslconn = sides * global.maxconn;
2204
2205 if (global.mode & (MODE_VERBOSE|MODE_DEBUG))
2206 fprintf(stderr, "Note: setting global.maxsslconn to %d\n", global.maxsslconn);
2207 }
2208#endif
2209 else if (!global.maxconn) {
2210 /* memmax and maxsslconn are known/unused, compute maxconn automatically */
2211 int sides = !!global.ssl_used_frontend + !!global.ssl_used_backend;
2212 int64_t mem = global.rlimit_memmax * 1048576ULL;
2213 int64_t clearmem;
Willy Tarreau304e17e2020-03-10 17:54:54 +01002214 int retried = 0;
Willy Tarreaud0256482015-01-15 21:45:22 +01002215
2216 if (global.ssl_used_frontend || global.ssl_used_backend)
2217 mem -= global.tune.sslcachesize * 200; // about 200 bytes per SSL cache entry
2218
2219 mem -= global.maxzlibmem;
2220 mem = mem * MEM_USABLE_RATIO;
2221
2222 clearmem = mem;
2223 if (sides)
2224 clearmem -= (global.ssl_session_max_cost + global.ssl_handshake_max_cost) * (int64_t)global.maxsslconn;
2225
Willy Tarreau304e17e2020-03-10 17:54:54 +01002226 /* Principle: we test once to set maxconn according to the free
2227 * memory. If it results in values the system rejects, we try a
2228 * second time by respecting rlim_fd_max. If it fails again, we
2229 * go back to the initial value and will let the final code
2230 * dealing with rlimit report the error. That's up to 3 attempts.
2231 */
2232 do {
2233 global.maxconn = clearmem / (STREAM_MAX_COST + 2 * global.tune.bufsize);
2234 if (retried == 1)
2235 global.maxconn = MIN(global.maxconn, ideal_maxconn);
2236 global.maxconn = round_2dig(global.maxconn);
Willy Tarreau474b96a2015-01-28 19:03:21 +01002237#ifdef SYSTEM_MAXCONN
Willy Tarreau304e17e2020-03-10 17:54:54 +01002238 if (global.maxconn > SYSTEM_MAXCONN)
2239 global.maxconn = SYSTEM_MAXCONN;
Willy Tarreau474b96a2015-01-28 19:03:21 +01002240#endif /* SYSTEM_MAXCONN */
Willy Tarreaud0256482015-01-15 21:45:22 +01002241
Willy Tarreau304e17e2020-03-10 17:54:54 +01002242 if (clearmem <= 0 || !global.maxconn) {
2243 ha_alert("Cannot compute the automatic maxconn because global.maxsslconn is already too "
2244 "high for the global.memmax value (%d MB). The absolute maximum possible value "
2245 "is %d, but %d was found.\n",
2246 global.rlimit_memmax,
Christopher Faulet767a84b2017-11-24 16:50:31 +01002247 (int)(mem / (global.ssl_session_max_cost + global.ssl_handshake_max_cost)),
Willy Tarreau304e17e2020-03-10 17:54:54 +01002248 global.maxsslconn);
2249 exit(1);
2250 }
2251
2252 if (check_if_maxsock_permitted(compute_ideal_maxsock(global.maxconn)))
2253 break;
2254 } while (retried++ < 2);
Willy Tarreaud0256482015-01-15 21:45:22 +01002255
2256 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2257 if (sides && global.maxsslconn > sides * global.maxconn) {
2258 fprintf(stderr, "Note: global.maxsslconn is forced to %d which causes global.maxconn "
2259 "to be limited to %d. Better reduce global.maxsslconn to get more "
2260 "room for extra connections.\n", global.maxsslconn, global.maxconn);
2261 }
2262 fprintf(stderr, "Note: setting global.maxconn to %d\n", global.maxconn);
2263 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002264 }
2265
Willy Tarreaua409f302020-03-10 17:08:53 +01002266 global.maxsock = compute_ideal_maxsock(global.maxconn);
2267 global.hardmaxconn = global.maxconn;
Willy Tarreaua4818db2020-06-19 16:20:59 +02002268 if (!global.maxpipes)
2269 global.maxpipes = compute_ideal_maxpipes();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270
Olivier Houchard88698d92019-04-16 19:07:22 +02002271 /* update connection pool thresholds */
2272 global.tune.pool_low_count = ((long long)global.maxsock * global.tune.pool_low_ratio + 99) / 100;
2273 global.tune.pool_high_count = ((long long)global.maxsock * global.tune.pool_high_ratio + 99) / 100;
2274
Willy Tarreauc8d5b952019-02-27 17:25:52 +01002275 proxy_adjust_all_maxconn();
2276
Willy Tarreau1db37712007-06-03 17:16:49 +02002277 if (global.tune.maxpollevents <= 0)
2278 global.tune.maxpollevents = MAX_POLL_EVENTS;
2279
Willy Tarreau060a7612021-03-10 11:06:26 +01002280 if (global.tune.runqueue_depth <= 0) {
2281 /* tests on various thread counts from 1 to 64 have shown an
2282 * optimal queue depth following roughly 1/sqrt(threads).
2283 */
2284 int s = my_flsl(global.nbthread);
2285 s += (global.nbthread / s); // roughly twice the sqrt.
2286 global.tune.runqueue_depth = RUNQUEUE_DEPTH * 2 / s;
2287 }
Olivier Houchard1599b802018-05-24 18:59:04 +02002288
Willy Tarreau6f4a82c2009-03-21 20:43:57 +01002289 if (global.tune.recv_enough == 0)
2290 global.tune.recv_enough = MIN_RECV_AT_ONCE_ENOUGH;
2291
Willy Tarreau27a674e2009-08-17 07:23:33 +02002292 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
2293 global.tune.maxrewrite = global.tune.bufsize / 2;
2294
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295 if (arg_mode & (MODE_DEBUG | MODE_FOREGROUND)) {
2296 /* command line debug mode inhibits configuration mode */
William Lallemand095ba4c2017-06-01 17:38:50 +02002297 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002298 global.mode |= (arg_mode & (MODE_DEBUG | MODE_FOREGROUND));
2299 }
2300
William Lallemand095ba4c2017-06-01 17:38:50 +02002301 if (arg_mode & MODE_DAEMON) {
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002302 /* command line daemon mode inhibits foreground and debug modes mode */
2303 global.mode &= ~(MODE_DEBUG | MODE_FOREGROUND);
William Lallemand095ba4c2017-06-01 17:38:50 +02002304 global.mode |= arg_mode & MODE_DAEMON;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002305 }
Willy Tarreau772f0dd2012-10-26 16:04:28 +02002306
2307 global.mode |= (arg_mode & (MODE_QUIET | MODE_VERBOSE));
Willy Tarreaubaaee002006-06-26 02:48:02 +02002308
William Lallemand095ba4c2017-06-01 17:38:50 +02002309 if ((global.mode & MODE_DEBUG) && (global.mode & (MODE_DAEMON | MODE_QUIET))) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002310 ha_warning("<debug> mode incompatible with <quiet> and <daemon>. Keeping <debug> only.\n");
William Lallemand095ba4c2017-06-01 17:38:50 +02002311 global.mode &= ~(MODE_DAEMON | MODE_QUIET);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002312 }
2313
William Lallemand095ba4c2017-06-01 17:38:50 +02002314 if ((global.nbproc > 1) && !(global.mode & (MODE_DAEMON | MODE_MWORKER))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002315 if (!(global.mode & (MODE_FOREGROUND | MODE_DEBUG)))
Christopher Faulet767a84b2017-11-24 16:50:31 +01002316 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 +02002317 global.nbproc = 1;
2318 }
2319
2320 if (global.nbproc < 1)
2321 global.nbproc = 1;
2322
Christopher Fauletbe0faa22017-08-29 15:37:10 +02002323 if (global.nbthread < 1)
2324 global.nbthread = 1;
2325
Christopher Faulet3ef26392017-08-29 16:46:57 +02002326 /* Realloc trash buffers because global.tune.bufsize may have changed */
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002327 if (!init_trash_buffers(0)) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002328 ha_alert("failed to initialize trash buffers.\n");
Christopher Faulet3ef26392017-08-29 16:46:57 +02002329 exit(1);
2330 }
2331
Christopher Faulet96d44832017-11-14 22:02:30 +01002332 if (!init_log_buffers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002333 ha_alert("failed to initialize log buffers.\n");
Christopher Faulet96d44832017-11-14 22:02:30 +01002334 exit(1);
2335 }
2336
Willy Tarreauef1d1f82007-04-16 00:25:25 +02002337 /*
2338 * Note: we could register external pollers here.
2339 * Built-in pollers have been registered before main().
2340 */
Willy Tarreau4f60f162007-04-08 16:39:58 +02002341
Willy Tarreau43b78992009-01-25 15:42:27 +01002342 if (!(global.tune.options & GTUNE_USE_KQUEUE))
Willy Tarreau1e63130a2007-04-09 12:03:06 +02002343 disable_poller("kqueue");
2344
Emmanuel Hocdet0ba4f482019-04-08 16:53:32 +00002345 if (!(global.tune.options & GTUNE_USE_EVPORTS))
2346 disable_poller("evports");
2347
Willy Tarreau43b78992009-01-25 15:42:27 +01002348 if (!(global.tune.options & GTUNE_USE_EPOLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002349 disable_poller("epoll");
2350
Willy Tarreau43b78992009-01-25 15:42:27 +01002351 if (!(global.tune.options & GTUNE_USE_POLL))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002352 disable_poller("poll");
2353
Willy Tarreau43b78992009-01-25 15:42:27 +01002354 if (!(global.tune.options & GTUNE_USE_SELECT))
Willy Tarreau4f60f162007-04-08 16:39:58 +02002355 disable_poller("select");
2356
2357 /* Note: we could disable any poller by name here */
2358
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002359 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
Willy Tarreau2ff76222007-04-09 19:29:56 +02002360 list_pollers(stderr);
Christopher Fauletb3f4e142016-03-07 12:46:38 +01002361 fprintf(stderr, "\n");
2362 list_filters(stderr);
2363 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002364
Willy Tarreau4f60f162007-04-08 16:39:58 +02002365 if (!init_pollers()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002366 ha_alert("No polling mechanism available.\n"
2367 " It is likely that haproxy was built with TARGET=generic and that FD_SETSIZE\n"
2368 " is too low on this platform to support maxconn and the number of listeners\n"
2369 " and servers. You should rebuild haproxy specifying your system using TARGET=\n"
2370 " in order to support other polling systems (poll, epoll, kqueue) or reduce the\n"
2371 " global maxconn setting to accommodate the system's limitation. For reference,\n"
2372 " FD_SETSIZE=%d on this system, global.maxconn=%d resulting in a maximum of\n"
2373 " %d file descriptors. You should thus reduce global.maxconn by %d. Also,\n"
2374 " check build settings using 'haproxy -vv'.\n\n",
2375 FD_SETSIZE, global.maxconn, global.maxsock, (global.maxsock + 1 - FD_SETSIZE) / 2);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002376 exit(1);
2377 }
Willy Tarreau2ff76222007-04-09 19:29:56 +02002378 if (global.mode & (MODE_VERBOSE|MODE_DEBUG)) {
2379 printf("Using %s() as the polling mechanism.\n", cur_poller.name);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002380 }
2381
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002382 if (!global.node)
2383 global.node = strdup(hostname);
2384
Willy Tarreau02b092f2020-10-07 18:36:54 +02002385 /* stop disabled proxies */
2386 for (px = proxies_list; px; px = px->next) {
Willy Tarreauc3914d42020-09-24 08:39:22 +02002387 if (px->disabled)
Willy Tarreau02b092f2020-10-07 18:36:54 +02002388 stop_proxy(px);
2389 }
2390
Thierry FOURNIERa4a0f3d2015-01-23 12:08:30 +01002391 if (!hlua_post_init())
2392 exit(1);
Thomas Holmes6abded42015-05-12 16:23:58 +01002393
Maxime de Roucy0f503922016-05-13 23:52:55 +02002394 free(err_msg);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395}
2396
Cyril Bonté203ec5a2017-03-23 22:44:13 +01002397void deinit(void)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002398{
Olivier Houchardfbc74e82017-11-24 16:54:05 +01002399 struct proxy *p = proxies_list, *p0;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01002400 struct wordlist *wl, *wlb;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002401 struct uri_auth *uap, *ua = NULL;
William Lallemand0f99e342011-10-12 17:50:54 +02002402 struct logsrv *log, *logb;
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002403 struct build_opts_str *bol, *bolb;
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002404 struct post_deinit_fct *pdf, *pdfb;
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002405 struct proxy_deinit_fct *pxdf, *pxdfb;
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002406 struct server_deinit_fct *srvdf, *srvdfb;
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002407 struct per_thread_init_fct *tif, *tifb;
2408 struct per_thread_deinit_fct *tdf, *tdfb;
2409 struct per_thread_alloc_fct *taf, *tafb;
2410 struct per_thread_free_fct *tff, *tffb;
Tim Duesterhus34bef072020-07-04 11:49:50 +02002411 struct post_server_check_fct *pscf, *pscfb;
Tim Duesterhusfc854942020-09-10 19:46:42 +02002412 struct post_check_fct *pcf, *pcfb;
Tim Duesterhus53508d62020-09-10 19:46:40 +02002413 struct post_proxy_check_fct *ppcf, *ppcfb;
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002414 int cur_fd;
2415
2416 /* At this point the listeners state is weird:
2417 * - most listeners are still bound and referenced in their protocol
2418 * - some might be zombies that are not in their proto anymore, but
2419 * still appear in their proxy's listeners with a valid FD.
2420 * - some might be stopped and still appear in their proxy as FD #-1
2421 * - among all of them, some might be inherited hence shared and we're
2422 * not allowed to pause them or whatever, we must just close them.
2423 * - finally some are not listeners (pipes, logs, stdout, etc) and
2424 * must be left intact.
2425 *
2426 * The safe way to proceed is to unbind (and close) whatever is not yet
2427 * unbound so that no more receiver/listener remains alive. Then close
2428 * remaining listener FDs, which correspond to zombie listeners (those
2429 * belonging to disabled proxies that were in another process).
2430 * objt_listener() would be cleaner here but not converted yet.
2431 */
2432 protocol_unbind_all();
2433
2434 for (cur_fd = 0; cur_fd < global.maxsock; cur_fd++) {
Willy Tarreau1a3770c2020-10-14 12:13:51 +02002435 if (!fdtab || !fdtab[cur_fd].owner)
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002436 continue;
2437
Willy Tarreaua74cb382020-10-15 21:29:49 +02002438 if (fdtab[cur_fd].iocb == &sock_accept_iocb) {
Willy Tarreauae7bc4a2020-09-23 16:46:22 +02002439 struct listener *l = fdtab[cur_fd].owner;
2440
2441 BUG_ON(l->state != LI_INIT);
2442 unbind_listener(l);
2443 }
2444 }
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002445
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002446 deinit_signals();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002447 while (p) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002448 /* build a list of unique uri_auths */
2449 if (!ua)
2450 ua = p->uri_auth;
2451 else {
2452 /* check if p->uri_auth is unique */
2453 for (uap = ua; uap; uap=uap->next)
2454 if (uap == p->uri_auth)
2455 break;
2456
Willy Tarreauaccc4e12008-06-24 11:14:45 +02002457 if (!uap && p->uri_auth) {
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002458 /* add it, if it is */
2459 p->uri_auth->next = ua;
2460 ua = p->uri_auth;
2461 }
William Lallemand0f99e342011-10-12 17:50:54 +02002462 }
2463
Willy Tarreau4d2d0982007-05-14 00:39:29 +02002464 p0 = p;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002465 p = p->next;
Amaury Denoyelle27fefa12021-03-24 16:13:20 +01002466 free_proxy(p0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002467 }/* end while(p) */
Willy Tarreaudd815982007-10-16 12:25:14 +02002468
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002469 while (ua) {
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002470 struct stat_scope *scope, *scopep;
2471
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002472 uap = ua;
2473 ua = ua->next;
2474
Willy Tarreaua534fea2008-08-03 12:19:50 +02002475 free(uap->uri_prefix);
2476 free(uap->auth_realm);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002477 free(uap->node);
2478 free(uap->desc);
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002479
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002480 userlist_free(uap->userlist);
Amaury Denoyelle68fd7e42021-03-25 17:15:52 +01002481 free_act_rules(&uap->http_req_rules);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01002482
Tim Duesterhus00f00cf2020-09-10 19:46:38 +02002483 scope = uap->scope;
2484 while (scope) {
2485 scopep = scope;
2486 scope = scope->next;
2487
2488 free(scopep->px_id);
2489 free(scopep);
2490 }
2491
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002492 free(uap);
2493 }
2494
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01002495 userlist_free(userlist);
2496
David Carlier834cb2e2015-09-25 12:02:25 +01002497 cfg_unregister_sections();
2498
Christopher Faulet0132d062017-07-26 15:33:35 +02002499 deinit_log_buffers();
David Carlier834cb2e2015-09-25 12:02:25 +01002500
Willy Tarreau05554e62016-12-21 20:46:26 +01002501 list_for_each_entry(pdf, &post_deinit_list, list)
2502 pdf->fct();
2503
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002504 ha_free(&global.log_send_hostname);
Dragan Dosen43885c72015-10-01 13:18:13 +02002505 chunk_destroy(&global.log_tag);
Willy Tarreau61cfdf42021-02-20 10:46:51 +01002506 ha_free(&global.chroot);
2507 ha_free(&global.pidfile);
2508 ha_free(&global.node);
2509 ha_free(&global.desc);
2510 ha_free(&oldpids);
2511 ha_free(&old_argv);
2512 ha_free(&localpeer);
2513 ha_free(&global.server_state_base);
2514 ha_free(&global.server_state_file);
Olivier Houchard3f795f72019-04-17 22:51:06 +02002515 task_destroy(idle_conn_task);
Olivier Houchard9ea5d362019-02-14 18:29:09 +01002516 idle_conn_task = NULL;
Krzysztof Piotr Oledzki8001d612008-05-31 13:53:23 +02002517
William Lallemand0f99e342011-10-12 17:50:54 +02002518 list_for_each_entry_safe(log, logb, &global.logsrvs, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002519 LIST_DELETE(&log->list);
Amaury Denoyelled688e012021-04-20 17:05:47 +02002520 free(log->conf.file);
William Lallemand0f99e342011-10-12 17:50:54 +02002521 free(log);
2522 }
Willy Tarreau477ecd82010-01-03 21:12:30 +01002523 list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) {
Maxime de Roucy0f503922016-05-13 23:52:55 +02002524 free(wl->s);
Willy Tarreau2b718102021-04-21 07:32:39 +02002525 LIST_DELETE(&wl->list);
Willy Tarreau477ecd82010-01-03 21:12:30 +01002526 free(wl);
2527 }
2528
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002529 list_for_each_entry_safe(bol, bolb, &build_opts_list, list) {
2530 if (bol->must_free)
2531 free((void *)bol->str);
Willy Tarreau2b718102021-04-21 07:32:39 +02002532 LIST_DELETE(&bol->list);
Willy Tarreaucdb737e2016-12-21 18:43:10 +01002533 free(bol);
2534 }
2535
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002536 list_for_each_entry_safe(pxdf, pxdfb, &proxy_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002537 LIST_DELETE(&pxdf->list);
Tim Duesterhus17e363f2020-07-04 11:49:47 +02002538 free(pxdf);
2539 }
2540
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002541 list_for_each_entry_safe(pdf, pdfb, &post_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002542 LIST_DELETE(&pdf->list);
Tim Duesterhusfdf904a2020-07-04 11:49:48 +02002543 free(pdf);
2544 }
2545
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002546 list_for_each_entry_safe(srvdf, srvdfb, &server_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002547 LIST_DELETE(&srvdf->list);
Tim Duesterhus0837eb12020-07-04 11:49:49 +02002548 free(srvdf);
2549 }
2550
Tim Duesterhusfc854942020-09-10 19:46:42 +02002551 list_for_each_entry_safe(pcf, pcfb, &post_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002552 LIST_DELETE(&pcf->list);
Tim Duesterhusfc854942020-09-10 19:46:42 +02002553 free(pcf);
2554 }
2555
Tim Duesterhus34bef072020-07-04 11:49:50 +02002556 list_for_each_entry_safe(pscf, pscfb, &post_server_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002557 LIST_DELETE(&pscf->list);
Tim Duesterhus34bef072020-07-04 11:49:50 +02002558 free(pscf);
2559 }
2560
Tim Duesterhus53508d62020-09-10 19:46:40 +02002561 list_for_each_entry_safe(ppcf, ppcfb, &post_proxy_check_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002562 LIST_DELETE(&ppcf->list);
Tim Duesterhus53508d62020-09-10 19:46:40 +02002563 free(ppcf);
2564 }
2565
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002566 list_for_each_entry_safe(tif, tifb, &per_thread_init_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002567 LIST_DELETE(&tif->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002568 free(tif);
2569 }
2570
2571 list_for_each_entry_safe(tdf, tdfb, &per_thread_deinit_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002572 LIST_DELETE(&tdf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002573 free(tdf);
2574 }
2575
2576 list_for_each_entry_safe(taf, tafb, &per_thread_alloc_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002577 LIST_DELETE(&taf->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002578 free(taf);
2579 }
2580
2581 list_for_each_entry_safe(tff, tffb, &per_thread_free_list, list) {
Willy Tarreau2b718102021-04-21 07:32:39 +02002582 LIST_DELETE(&tff->list);
Tim Duesterhusf0c25d22020-09-10 19:46:41 +02002583 free(tff);
2584 }
2585
Willy Tarreaucfc4f242021-05-08 11:41:28 +02002586 vars_prune(&proc_vars, NULL, NULL);
Willy Tarreau2455ceb2018-11-26 15:57:34 +01002587 pool_destroy_all();
Krzysztof Piotr Oledzkia643baf2008-05-29 23:53:44 +02002588 deinit_pollers();
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589} /* end deinit() */
2590
Willy Tarreauf3ca5a02020-06-15 18:43:46 +02002591__attribute__((noreturn)) void deinit_and_exit(int status)
Tim Duesterhus26540552020-06-14 00:37:41 +02002592{
Amaury Denoyelle890f4be2021-08-09 15:02:56 +02002593 global.mode |= MODE_STOPPING;
Tim Duesterhus26540552020-06-14 00:37:41 +02002594 deinit();
2595 exit(status);
2596}
William Lallemand72160322018-11-06 17:37:16 +01002597
Willy Tarreau918ff602011-07-25 16:33:49 +02002598/* Runs the polling loop */
Willy Tarreau3ebd55e2020-03-03 14:59:56 +01002599void run_poll_loop()
Willy Tarreau4f60f162007-04-08 16:39:58 +02002600{
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002601 int next, wake;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002602
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02002603 tv_update_date(0,1);
Willy Tarreau4f60f162007-04-08 16:39:58 +02002604 while (1) {
Willy Tarreauc49ba522019-12-11 08:12:23 +01002605 wake_expired_tasks();
2606
William Lallemand1aab50b2018-06-07 09:46:01 +02002607 /* check if we caught some signals and process them in the
2608 first thread */
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002609 if (signal_queue_len && tid == 0) {
2610 activity[tid].wake_signal++;
William Lallemand1aab50b2018-06-07 09:46:01 +02002611 signal_process_queue();
Willy Tarreaua7ad4ae2020-06-19 12:06:34 +02002612 }
2613
2614 /* Process a few tasks */
2615 process_runnable_tasks();
Willy Tarreau29857942009-05-10 09:01:21 +02002616
Willy Tarreau7067b3a2019-06-02 11:11:29 +02002617 /* also stop if we failed to cleanly stop all tasks */
2618 if (killed > 1)
2619 break;
2620
Willy Tarreau10146c92015-04-13 20:44:19 +02002621 /* expire immediately if events are pending */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002622 wake = 1;
Olivier Houchard305d5ab2019-07-24 18:07:06 +02002623 if (thread_has_tasks())
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002624 activity[tid].wake_tasks++;
Olivier Houchard79321b92018-07-26 17:55:11 +02002625 else {
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002626 _HA_ATOMIC_OR(&sleeping_thread_mask, tid_bit);
2627 __ha_barrier_atomic_store();
Willy Tarreau95abd5b2020-03-23 09:33:32 +01002628 if (thread_has_tasks()) {
Olivier Houchard79321b92018-07-26 17:55:11 +02002629 activity[tid].wake_tasks++;
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002630 _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit);
Olivier Houchard79321b92018-07-26 17:55:11 +02002631 } else
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002632 wake = 0;
Olivier Houchard79321b92018-07-26 17:55:11 +02002633 }
Willy Tarreau10146c92015-04-13 20:44:19 +02002634
Willy Tarreau4f46a352020-03-23 09:27:28 +01002635 if (!wake) {
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002636 int i;
2637
2638 if (stopping) {
Ilya Shipitsin3df59892021-05-10 12:50:00 +05002639 /* stop muxes before acknowledging stopping */
Amaury Denoyelled3a88c12021-05-03 10:47:51 +02002640 if (!(stopping_thread_mask & tid_bit)) {
2641 task_wakeup(mux_stopping_data[tid].task, TASK_WOKEN_OTHER);
2642 wake = 1;
2643 }
2644
Willy Tarreau1db42732021-04-06 11:44:07 +02002645 if (_HA_ATOMIC_OR_FETCH(&stopping_thread_mask, tid_bit) == tid_bit) {
Willy Tarreaud6455742020-05-13 14:30:25 +02002646 /* notify all threads that stopping was just set */
2647 for (i = 0; i < global.nbthread; i++)
Willy Tarreau369a2ef2020-06-29 19:23:19 +02002648 if (((all_threads_mask & ~stopping_thread_mask) >> i) & 1)
Willy Tarreaud6455742020-05-13 14:30:25 +02002649 wake_thread(i);
2650 }
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002651 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002652
2653 /* stop when there's nothing left to do */
2654 if ((jobs - unstoppable_jobs) == 0 &&
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002655 (stopping_thread_mask & all_threads_mask) == all_threads_mask) {
2656 /* wake all threads waiting on jobs==0 */
2657 for (i = 0; i < global.nbthread; i++)
2658 if (((all_threads_mask & ~tid_bit) >> i) & 1)
2659 wake_thread(i);
Willy Tarreau4f46a352020-03-23 09:27:28 +01002660 break;
Willy Tarreaud7a6b2f2020-05-13 13:51:01 +02002661 }
Willy Tarreau4f46a352020-03-23 09:27:28 +01002662 }
2663
Willy Tarreauc49ba522019-12-11 08:12:23 +01002664 /* If we have to sleep, measure how long */
2665 next = wake ? TICK_ETERNITY : next_timer_expiry();
2666
Willy Tarreau58b458d2008-06-29 22:40:23 +02002667 /* The poller will ensure it returns around <next> */
Willy Tarreau2ae84e42019-05-28 16:44:05 +02002668 cur_poller.poll(&cur_poller, next, wake);
Emeric Brun64cc49c2017-10-03 14:46:45 +02002669
Willy Tarreaud80cb4e2018-01-20 19:30:13 +01002670 activity[tid].loops++;
Willy Tarreau4f60f162007-04-08 16:39:58 +02002671 }
2672}
2673
Christopher Faulet1d17c102017-08-29 15:38:48 +02002674static void *run_thread_poll_loop(void *data)
2675{
Willy Tarreau082b6282019-05-22 14:42:12 +02002676 struct per_thread_alloc_fct *ptaf;
Christopher Faulet1d17c102017-08-29 15:38:48 +02002677 struct per_thread_init_fct *ptif;
2678 struct per_thread_deinit_fct *ptdf;
Willy Tarreau082b6282019-05-22 14:42:12 +02002679 struct per_thread_free_fct *ptff;
Willy Tarreau34a150c2019-06-11 09:16:41 +02002680 static int init_left = 0;
Willy Tarreauaf613e82020-06-05 08:40:51 +02002681 __decl_thread(static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER);
2682 __decl_thread(static pthread_cond_t init_cond = PTHREAD_COND_INITIALIZER);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002683
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02002684 ha_set_tid((unsigned long)data);
Willy Tarreaud022e9c2019-09-24 08:25:15 +02002685 sched = &task_per_thread[tid];
Willy Tarreau91e6df02019-05-03 17:21:18 +02002686
Willy Tarreauf6178242019-05-21 19:46:58 +02002687#if (_POSIX_TIMERS > 0) && defined(_POSIX_THREAD_CPUTIME)
Willy Tarreau91e6df02019-05-03 17:21:18 +02002688#ifdef USE_THREAD
Willy Tarreau8323a372019-05-20 18:57:53 +02002689 pthread_getcpuclockid(pthread_self(), &ti->clock_id);
Willy Tarreau624dcbf2019-05-20 20:23:06 +02002690#else
Willy Tarreau8323a372019-05-20 18:57:53 +02002691 ti->clock_id = CLOCK_THREAD_CPUTIME_ID;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002692#endif
Willy Tarreau663fda42019-05-21 15:14:08 +02002693#endif
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002694 /* Now, initialize one thread init at a time. This is better since
2695 * some init code is a bit tricky and may release global resources
2696 * after reallocating them locally. This will also ensure there is
2697 * no race on file descriptors allocation.
2698 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002699#ifdef USE_THREAD
2700 pthread_mutex_lock(&init_mutex);
2701#endif
2702 /* The first thread must set the number of threads left */
2703 if (!init_left)
2704 init_left = global.nbthread;
2705 init_left--;
Willy Tarreau91e6df02019-05-03 17:21:18 +02002706
Willy Tarreauc4c80fb2021-04-11 15:00:34 +02002707 tv_init_thread_date();
Christopher Faulet1d17c102017-08-29 15:38:48 +02002708
Willy Tarreau082b6282019-05-22 14:42:12 +02002709 /* per-thread alloc calls performed here are not allowed to snoop on
2710 * other threads, so they are free to initialize at their own rhythm
2711 * as long as they act as if they were alone. None of them may rely
2712 * on resources initialized by the other ones.
2713 */
2714 list_for_each_entry(ptaf, &per_thread_alloc_list, list) {
2715 if (!ptaf->fct()) {
2716 ha_alert("failed to allocate resources for thread %u.\n", tid);
2717 exit(1);
2718 }
2719 }
2720
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002721 /* per-thread init calls performed here are not allowed to snoop on
2722 * other threads, so they are free to initialize at their own rhythm
2723 * as long as they act as if they were alone.
2724 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02002725 list_for_each_entry(ptif, &per_thread_init_list, list) {
2726 if (!ptif->fct()) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002727 ha_alert("failed to initialize thread %u.\n", tid);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002728 exit(1);
2729 }
2730 }
2731
Willy Tarreau71092822019-06-10 09:51:04 +02002732 /* enabling protocols will result in fd_insert() calls to be performed,
2733 * we want all threads to have already allocated their local fd tables
Willy Tarreau34a150c2019-06-11 09:16:41 +02002734 * before doing so, thus only the last thread does it.
Willy Tarreau71092822019-06-10 09:51:04 +02002735 */
Willy Tarreau34a150c2019-06-11 09:16:41 +02002736 if (init_left == 0)
Willy Tarreaue4d7c9d2019-06-10 10:14:52 +02002737 protocol_enable_all();
Willy Tarreau6ec902a2019-06-07 14:41:11 +02002738
Willy Tarreau34a150c2019-06-11 09:16:41 +02002739#ifdef USE_THREAD
2740 pthread_cond_broadcast(&init_cond);
2741 pthread_mutex_unlock(&init_mutex);
2742
2743 /* now wait for other threads to finish starting */
2744 pthread_mutex_lock(&init_mutex);
2745 while (init_left)
2746 pthread_cond_wait(&init_cond, &init_mutex);
2747 pthread_mutex_unlock(&init_mutex);
2748#endif
Willy Tarreau3078e9f2019-05-20 10:50:43 +02002749
Willy Tarreaua45a8b52019-12-06 16:31:45 +01002750#if defined(PR_SET_NO_NEW_PRIVS) && defined(USE_PRCTL)
2751 /* Let's refrain from using setuid executables. This way the impact of
2752 * an eventual vulnerability in a library remains limited. It may
2753 * impact external checks but who cares about them anyway ? In the
2754 * worst case it's possible to disable the option. Obviously we do this
2755 * in workers only. We can't hard-fail on this one as it really is
2756 * implementation dependent though we're interested in feedback, hence
2757 * the warning.
2758 */
2759 if (!(global.tune.options & GTUNE_INSECURE_SETUID) && !master) {
2760 static int warn_fail;
Willy Tarreau18515722021-04-06 11:57:41 +02002761 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 +01002762 ha_warning("Failed to disable setuid, please report to developers with detailed "
2763 "information about your operating system. You can silence this warning "
2764 "by adding 'insecure-setuid-wanted' in the 'global' section.\n");
2765 }
2766 }
2767#endif
2768
Willy Tarreaud96f1122019-12-03 07:07:36 +01002769#if defined(RLIMIT_NPROC)
2770 /* all threads have started, it's now time to prevent any new thread
2771 * or process from starting. Obviously we do this in workers only. We
2772 * can't hard-fail on this one as it really is implementation dependent
2773 * though we're interested in feedback, hence the warning.
2774 */
2775 if (!(global.tune.options & GTUNE_INSECURE_FORK) && !master) {
2776 struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
2777 static int warn_fail;
2778
Willy Tarreau18515722021-04-06 11:57:41 +02002779 if (setrlimit(RLIMIT_NPROC, &limit) == -1 && !_HA_ATOMIC_FETCH_ADD(&warn_fail, 1)) {
Willy Tarreaud96f1122019-12-03 07:07:36 +01002780 ha_warning("Failed to disable forks, please report to developers with detailed "
2781 "information about your operating system. You can silence this warning "
2782 "by adding 'insecure-fork-wanted' in the 'global' section.\n");
2783 }
2784 }
2785#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02002786 run_poll_loop();
2787
2788 list_for_each_entry(ptdf, &per_thread_deinit_list, list)
2789 ptdf->fct();
2790
Willy Tarreau082b6282019-05-22 14:42:12 +02002791 list_for_each_entry(ptff, &per_thread_free_list, list)
2792 ptff->fct();
2793
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002794#ifdef USE_THREAD
Olivier Houchardb23a61f2019-03-08 18:51:17 +01002795 _HA_ATOMIC_AND(&all_threads_mask, ~tid_bit);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002796 if (tid > 0)
2797 pthread_exit(NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02002798#endif
Christopher Fauletcd7879a2017-10-27 13:53:47 +02002799 return NULL;
2800}
Christopher Faulet1d17c102017-08-29 15:38:48 +02002801
William Dauchyf9af9d72019-11-17 15:47:16 +01002802/* set uid/gid depending on global settings */
2803static void set_identity(const char *program_name)
2804{
2805 if (global.gid) {
2806 if (getgroups(0, NULL) > 0 && setgroups(0, NULL) == -1)
2807 ha_warning("[%s.main()] Failed to drop supplementary groups. Using 'gid'/'group'"
2808 " without 'uid'/'user' is generally useless.\n", program_name);
2809
2810 if (setgid(global.gid) == -1) {
2811 ha_alert("[%s.main()] Cannot set gid %d.\n", program_name, global.gid);
2812 protocol_unbind_all();
2813 exit(1);
2814 }
2815 }
2816
2817 if (global.uid && setuid(global.uid) == -1) {
2818 ha_alert("[%s.main()] Cannot set uid %d.\n", program_name, global.uid);
2819 protocol_unbind_all();
2820 exit(1);
2821 }
2822}
2823
Willy Tarreaubaaee002006-06-26 02:48:02 +02002824int main(int argc, char **argv)
2825{
2826 int err, retry;
2827 struct rlimit limit;
Willy Tarreau269ab312012-09-05 08:02:48 +02002828 int pidfd = -1;
Willy Tarreau08293ed2021-07-14 17:54:01 +02002829 int intovf = (unsigned char)argc + 1; /* let the compiler know it's strictly positive */
2830
2831 /* Catch forced CFLAGS that miss 2-complement integer overflow */
2832 if (intovf + 0x7FFFFFFF >= intovf) {
2833 fprintf(stderr,
2834 "FATAL ERROR: invalid code detected -- cannot go further, please recompile!\n"
2835 "The source code was miscompiled by the compiler, which usually indicates that\n"
2836 "some of the CFLAGS needed to work around overzealous compiler optimizations\n"
2837 "were overwritten at build time. Please do not force CFLAGS, and read Makefile\n"
2838 "and INSTALL files to decide on the best way to pass your local build options.\n"
2839 "\nBuild options :"
2840#ifdef BUILD_TARGET
2841 "\n TARGET = " BUILD_TARGET
2842#endif
2843#ifdef BUILD_CPU
2844 "\n CPU = " BUILD_CPU
2845#endif
2846#ifdef BUILD_CC
2847 "\n CC = " BUILD_CC
2848#endif
2849#ifdef BUILD_CFLAGS
2850 "\n CFLAGS = " BUILD_CFLAGS
2851#endif
2852#ifdef BUILD_OPTIONS
2853 "\n OPTIONS = " BUILD_OPTIONS
2854#endif
2855#ifdef BUILD_DEBUG
2856 "\n DEBUG = " BUILD_DEBUG
2857#endif
2858 "\n\n");
2859 return 1;
2860 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002861
Olivier Houchard5fa300d2018-02-03 15:15:21 +01002862 setvbuf(stdout, NULL, _IONBF, 0);
Willy Tarreau5794fb02018-11-25 18:43:29 +01002863
Willy Tarreauff9c9142019-02-07 10:39:36 +01002864 /* this can only safely be done here, though it's optimized away by
2865 * the compiler.
2866 */
2867 if (MAX_PROCS < 1 || MAX_PROCS > LONGBITS) {
2868 ha_alert("MAX_PROCS value must be between 1 and %d inclusive; "
2869 "HAProxy was built with value %d, please fix it and rebuild.\n",
2870 LONGBITS, MAX_PROCS);
2871 exit(1);
2872 }
2873
Willy Tarreaubf696402019-03-01 10:09:28 +01002874 /* take a copy of initial limits before we possibly change them */
2875 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau2bd0f812020-10-13 15:36:08 +02002876
2877 if (limit.rlim_max == RLIM_INFINITY)
2878 limit.rlim_max = limit.rlim_cur;
Willy Tarreaubf696402019-03-01 10:09:28 +01002879 rlim_fd_cur_at_boot = limit.rlim_cur;
2880 rlim_fd_max_at_boot = limit.rlim_max;
2881
Willy Tarreau5794fb02018-11-25 18:43:29 +01002882 /* process all initcalls in order of potential dependency */
2883 RUN_INITCALLS(STG_PREPARE);
2884 RUN_INITCALLS(STG_LOCK);
2885 RUN_INITCALLS(STG_ALLOC);
2886 RUN_INITCALLS(STG_POOL);
2887 RUN_INITCALLS(STG_REGISTER);
2888 RUN_INITCALLS(STG_INIT);
2889
Emeric Bruncf20bf12010-10-22 16:06:11 +02002890 init(argc, argv);
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002891 signal_register_fct(SIGQUIT, dump, SIGQUIT);
2892 signal_register_fct(SIGUSR1, sig_soft_stop, SIGUSR1);
2893 signal_register_fct(SIGHUP, sig_dump_state, SIGHUP);
William Lallemand73b85e72017-06-01 17:38:51 +02002894 signal_register_fct(SIGUSR2, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002895
Willy Tarreaue437c442010-03-17 18:02:46 +01002896 /* Always catch SIGPIPE even on platforms which define MSG_NOSIGNAL.
2897 * Some recent FreeBSD setups report broken pipes, and MSG_NOSIGNAL
2898 * was defined there, so let's stay on the safe side.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002899 */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02002900 signal_register_fct(SIGPIPE, NULL, 0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901
Willy Tarreaudc23a922011-02-16 11:10:36 +01002902 /* ulimits */
2903 if (!global.rlimit_nofile)
2904 global.rlimit_nofile = global.maxsock;
2905
2906 if (global.rlimit_nofile) {
Willy Tarreaue5cfdac2019-03-01 10:32:05 +01002907 limit.rlim_cur = global.rlimit_nofile;
2908 limit.rlim_max = MAX(rlim_fd_max_at_boot, limit.rlim_cur);
2909
Willy Tarreaudc23a922011-02-16 11:10:36 +01002910 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
Willy Tarreauef635472016-06-21 11:48:18 +02002911 getrlimit(RLIMIT_NOFILE, &limit);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002912 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2913 ha_alert("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
2914 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002915 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002916 }
2917 else {
2918 /* try to set it to the max possible at least */
2919 limit.rlim_cur = limit.rlim_max;
2920 if (setrlimit(RLIMIT_NOFILE, &limit) != -1)
2921 getrlimit(RLIMIT_NOFILE, &limit);
Willy Tarreau164dd0b2016-06-21 11:51:59 +02002922
William Dauchya5194602020-03-28 19:29:58 +01002923 ha_warning("[%s.main()] Cannot raise FD limit to %d, limit is %d.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002924 argv[0], global.rlimit_nofile, (int)limit.rlim_cur);
2925 global.rlimit_nofile = limit.rlim_cur;
2926 }
Willy Tarreaudc23a922011-02-16 11:10:36 +01002927 }
2928 }
2929
2930 if (global.rlimit_memmax) {
2931 limit.rlim_cur = limit.rlim_max =
Willy Tarreau70060452015-12-14 12:46:07 +01002932 global.rlimit_memmax * 1048576ULL;
Willy Tarreaudc23a922011-02-16 11:10:36 +01002933#ifdef RLIMIT_AS
2934 if (setrlimit(RLIMIT_AS, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002935 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2936 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2937 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002938 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002939 }
2940 else
William Dauchya5194602020-03-28 19:29:58 +01002941 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002942 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002943 }
2944#else
2945 if (setrlimit(RLIMIT_DATA, &limit) == -1) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01002946 if (global.tune.options & GTUNE_STRICT_LIMITS) {
2947 ha_alert("[%s.main()] Cannot fix MEM limit to %d megs.\n",
2948 argv[0], global.rlimit_memmax);
Jerome Magnin50f757c2021-01-12 20:19:38 +01002949 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01002950 }
2951 else
William Dauchya5194602020-03-28 19:29:58 +01002952 ha_warning("[%s.main()] Cannot fix MEM limit to %d megs.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01002953 argv[0], global.rlimit_memmax);
Willy Tarreaudc23a922011-02-16 11:10:36 +01002954 }
2955#endif
2956 }
2957
William Lallemand9993c172022-01-07 18:19:42 +01002958 /* Try to get the listeners FD from the previous process using
2959 * _getsocks on the stat socket, it must never been done in wait mode
2960 * and check mode
2961 */
2962 if (old_unixsocket &&
2963 !(global.mode & (MODE_MWORKER_WAIT|MODE_CHECK))) {
William Lallemand85b0bd92017-06-01 17:38:53 +02002964 if (strcmp("/dev/null", old_unixsocket) != 0) {
Willy Tarreau42961742020-08-28 18:42:45 +02002965 if (sock_get_old_sockets(old_unixsocket) != 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01002966 ha_alert("Failed to get the sockets from the old process!\n");
William Lallemand85b0bd92017-06-01 17:38:53 +02002967 if (!(global.mode & MODE_MWORKER))
2968 exit(1);
2969 }
Olivier Houchardf73629d2017-04-05 22:33:04 +02002970 }
2971 }
William Lallemand85b0bd92017-06-01 17:38:53 +02002972 get_cur_unixsocket();
2973
Willy Tarreaubaaee002006-06-26 02:48:02 +02002974 /* We will loop at most 100 times with 10 ms delay each time.
2975 * That's at most 1 second. We only send a signal to old pids
2976 * if we cannot grab at least one port.
2977 */
2978 retry = MAX_START_RETRIES;
2979 err = ERR_NONE;
2980 while (retry >= 0) {
2981 struct timeval w;
Willy Tarreaue91bff22020-09-02 11:11:43 +02002982 err = protocol_bind_all(retry == 0 || nb_oldpids == 0);
Willy Tarreaue13e9252007-12-20 23:05:50 +01002983 /* exit the loop on no error or fatal error */
2984 if ((err & (ERR_RETRYABLE|ERR_FATAL)) != ERR_RETRYABLE)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002985 break;
Willy Tarreaubb545b42010-08-25 12:58:59 +02002986 if (nb_oldpids == 0 || retry == 0)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002987 break;
2988
2989 /* FIXME-20060514: Solaris and OpenBSD do not support shutdown() on
2990 * listening sockets. So on those platforms, it would be wiser to
2991 * simply send SIGUSR1, which will not be undoable.
2992 */
Willy Tarreaubb545b42010-08-25 12:58:59 +02002993 if (tell_old_pids(SIGTTOU) == 0) {
2994 /* no need to wait if we can't contact old pids */
2995 retry = 0;
2996 continue;
2997 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 /* give some time to old processes to stop listening */
2999 w.tv_sec = 0;
3000 w.tv_usec = 10*1000;
3001 select(0, NULL, NULL, NULL, &w);
3002 retry--;
3003 }
3004
Willy Tarreaue91bff22020-09-02 11:11:43 +02003005 /* Note: protocol_bind_all() sends an alert when it fails. */
Willy Tarreau0a3b9d92009-02-04 17:05:23 +01003006 if ((err & ~ERR_WARN) != ERR_NONE) {
Willy Tarreaue91bff22020-09-02 11:11:43 +02003007 ha_alert("[%s.main()] Some protocols failed to start their listeners! Exiting.\n", argv[0]);
Willy Tarreauf68da462009-06-09 14:36:00 +02003008 if (retry != MAX_START_RETRIES && nb_oldpids) {
3009 protocol_unbind_all(); /* cleanup everything we can */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 tell_old_pids(SIGTTIN);
Willy Tarreauf68da462009-06-09 14:36:00 +02003011 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003012 exit(1);
3013 }
3014
William Lallemand944e6192018-11-21 15:48:31 +01003015 if (!(global.mode & MODE_MWORKER_WAIT) && listeners == 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003016 ha_alert("[%s.main()] No enabled listener found (check for 'bind' directives) ! Exiting.\n", argv[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003017 /* Note: we don't have to send anything to the old pids because we
3018 * never stopped them. */
3019 exit(1);
3020 }
3021
Willy Tarreaue91bff22020-09-02 11:11:43 +02003022 /* Ok, all listeners should now be bound, close any leftover sockets
Olivier Houchardf73629d2017-04-05 22:33:04 +02003023 * the previous process gave us, we don't need them anymore
3024 */
3025 while (xfer_sock_list != NULL) {
3026 struct xfer_sock_list *tmpxfer = xfer_sock_list->next;
3027 close(xfer_sock_list->fd);
3028 free(xfer_sock_list->iface);
3029 free(xfer_sock_list->namespace);
3030 free(xfer_sock_list);
3031 xfer_sock_list = tmpxfer;
3032 }
Willy Tarreaudd815982007-10-16 12:25:14 +02003033
Willy Tarreaubaaee002006-06-26 02:48:02 +02003034 /* prepare pause/play signals */
Willy Tarreau24f4efa2010-08-27 17:56:48 +02003035 signal_register_fct(SIGTTOU, sig_pause, SIGTTOU);
3036 signal_register_fct(SIGTTIN, sig_listen, SIGTTIN);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003037
Willy Tarreaubaaee002006-06-26 02:48:02 +02003038 /* MODE_QUIET can inhibit alerts and warnings below this line */
3039
PiBa-NL149a81a2017-12-25 21:03:31 +01003040 if (getenv("HAPROXY_MWORKER_REEXEC") != NULL) {
3041 /* either stdin/out/err are already closed or should stay as they are. */
3042 if ((global.mode & MODE_DAEMON)) {
3043 /* daemon mode re-executing, stdin/stdout/stderr are already closed so keep quiet */
3044 global.mode &= ~MODE_VERBOSE;
3045 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3046 }
3047 } else {
3048 if ((global.mode & MODE_QUIET) && !(global.mode & MODE_VERBOSE)) {
3049 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003050 stdio_quiet(-1);
PiBa-NL149a81a2017-12-25 21:03:31 +01003051 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 }
3053
3054 /* open log & pid files before the chroot */
William Lallemand80293002017-11-06 11:00:03 +01003055 if ((global.mode & MODE_DAEMON || global.mode & MODE_MWORKER) && global.pidfile != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056 unlink(global.pidfile);
3057 pidfd = open(global.pidfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
3058 if (pidfd < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003059 ha_alert("[%s.main()] Cannot create pidfile %s\n", argv[0], global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060 if (nb_oldpids)
3061 tell_old_pids(SIGTTIN);
Willy Tarreaudd815982007-10-16 12:25:14 +02003062 protocol_unbind_all();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 exit(1);
3064 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003065 }
3066
Willy Tarreaub38651a2007-03-24 17:24:39 +01003067 if ((global.last_checks & LSTCHK_NETADM) && global.uid) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003068 ha_alert("[%s.main()] Some configuration options require full privileges, so global.uid cannot be changed.\n"
3069 "", argv[0]);
Willy Tarreaudd815982007-10-16 12:25:14 +02003070 protocol_unbind_all();
Willy Tarreaub38651a2007-03-24 17:24:39 +01003071 exit(1);
3072 }
3073
Jackie Tapia749f74c2020-07-22 18:59:40 -05003074 /* If the user is not root, we'll still let them try the configuration
3075 * but we inform them that unexpected behaviour may occur.
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003076 */
3077 if ((global.last_checks & LSTCHK_NETADM) && getuid())
Christopher Faulet767a84b2017-11-24 16:50:31 +01003078 ha_warning("[%s.main()] Some options which require full privileges"
3079 " might not work well.\n"
3080 "", argv[0]);
Willy Tarreau4e30ed72009-02-04 18:02:48 +01003081
William Lallemand095ba4c2017-06-01 17:38:50 +02003082 if ((global.mode & (MODE_MWORKER|MODE_DAEMON)) == 0) {
3083
3084 /* chroot if needed */
3085 if (global.chroot != NULL) {
3086 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003087 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003088 if (nb_oldpids)
3089 tell_old_pids(SIGTTIN);
3090 protocol_unbind_all();
3091 exit(1);
3092 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003093 }
Willy Tarreauf223cc02007-10-15 18:57:08 +02003094 }
3095
William Lallemand944e6192018-11-21 15:48:31 +01003096 if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
Willy Tarreaubb545b42010-08-25 12:58:59 +02003097 nb_oldpids = tell_old_pids(oldpids_sig);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003098
William Lallemand27edc4b2019-05-07 17:49:33 +02003099 /* send a SIGTERM to workers who have a too high reloads number */
3100 if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
3101 mworker_kill_max_reloads(SIGTERM);
3102
Willy Tarreaubaaee002006-06-26 02:48:02 +02003103 /* Note that any error at this stage will be fatal because we will not
3104 * be able to restart the old pids.
3105 */
3106
William Dauchyf9af9d72019-11-17 15:47:16 +01003107 if ((global.mode & (MODE_MWORKER | MODE_DAEMON)) == 0)
3108 set_identity(argv[0]);
Willy Tarreau636848a2019-04-15 19:38:50 +02003109
Willy Tarreaubaaee002006-06-26 02:48:02 +02003110 /* check ulimits */
3111 limit.rlim_cur = limit.rlim_max = 0;
3112 getrlimit(RLIMIT_NOFILE, &limit);
3113 if (limit.rlim_cur < global.maxsock) {
William Dauchy0fec3ab2019-10-27 20:08:11 +01003114 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3115 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
3116 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
3117 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3118 global.maxsock);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003119 exit(1);
William Dauchy0fec3ab2019-10-27 20:08:11 +01003120 }
3121 else
3122 ha_alert("[%s.main()] FD limit (%d) too low for maxconn=%d/maxsock=%d. "
William Dauchya5194602020-03-28 19:29:58 +01003123 "Please raise 'ulimit-n' to %d or more to avoid any trouble.\n",
William Dauchy0fec3ab2019-10-27 20:08:11 +01003124 argv[0], (int)limit.rlim_cur, global.maxconn, global.maxsock,
3125 global.maxsock);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 }
3127
William Lallemand944e6192018-11-21 15:48:31 +01003128 if (global.mode & (MODE_DAEMON | MODE_MWORKER | MODE_MWORKER_WAIT)) {
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003129 struct proxy *px;
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003130 struct peers *curpeers;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 int ret = 0;
3132 int proc;
William Lallemande1340412017-12-28 16:09:36 +01003133 int devnullfd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003134
William Lallemand095ba4c2017-06-01 17:38:50 +02003135 /*
3136 * if daemon + mworker: must fork here to let a master
3137 * process live in background before forking children
3138 */
William Lallemand73b85e72017-06-01 17:38:51 +02003139
3140 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)
3141 && (global.mode & MODE_MWORKER)
3142 && (global.mode & MODE_DAEMON)) {
William Lallemand095ba4c2017-06-01 17:38:50 +02003143 ret = fork();
3144 if (ret < 0) {
Christopher Faulet767a84b2017-11-24 16:50:31 +01003145 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003146 protocol_unbind_all();
3147 exit(1); /* there has been an error */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003148 } else if (ret > 0) { /* parent leave to daemonize */
William Lallemand095ba4c2017-06-01 17:38:50 +02003149 exit(0);
William Lallemandbfd8eb52018-07-04 15:31:23 +02003150 } else /* change the process group ID in the child (master process) */
3151 setsid();
William Lallemand095ba4c2017-06-01 17:38:50 +02003152 }
William Lallemande20b6a62017-06-01 17:38:55 +02003153
William Lallemande20b6a62017-06-01 17:38:55 +02003154
William Lallemanddeed7802017-11-06 11:00:04 +01003155 /* if in master-worker mode, write the PID of the father */
3156 if (global.mode & MODE_MWORKER) {
3157 char pidstr[100];
Willy Tarreau76a80c72019-06-22 07:41:38 +02003158 snprintf(pidstr, sizeof(pidstr), "%d\n", (int)getpid());
Willy Tarreau46ec48b2018-01-23 19:20:19 +01003159 if (pidfd >= 0)
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003160 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemanddeed7802017-11-06 11:00:04 +01003161 }
3162
Willy Tarreaubaaee002006-06-26 02:48:02 +02003163 /* the father launches the required number of processes */
William Lallemand944e6192018-11-21 15:48:31 +01003164 if (!(global.mode & MODE_MWORKER_WAIT)) {
William Lallemand9a1ee7a2019-04-01 11:30:02 +02003165 if (global.mode & MODE_MWORKER)
3166 mworker_ext_launch_all();
William Lallemand944e6192018-11-21 15:48:31 +01003167 for (proc = 0; proc < global.nbproc; proc++) {
3168 ret = fork();
3169 if (ret < 0) {
3170 ha_alert("[%s.main()] Cannot fork.\n", argv[0]);
3171 protocol_unbind_all();
3172 exit(1); /* there has been an error */
3173 }
Willy Tarreau52bf8392020-03-08 00:42:37 +01003174 else if (ret == 0) { /* child breaks here */
Willy Tarreaua9274a12021-07-21 10:17:02 +02003175 /* This one must not be exported, it's internal! */
3176 unsetenv("HAPROXY_MWORKER_REEXEC");
Willy Tarreau52bf8392020-03-08 00:42:37 +01003177 ha_random_jump96(relative_pid);
William Lallemand944e6192018-11-21 15:48:31 +01003178 break;
Willy Tarreau52bf8392020-03-08 00:42:37 +01003179 }
William Lallemand944e6192018-11-21 15:48:31 +01003180 if (pidfd >= 0 && !(global.mode & MODE_MWORKER)) {
3181 char pidstr[100];
3182 snprintf(pidstr, sizeof(pidstr), "%d\n", ret);
Willy Tarreau2e8ab6b2020-03-14 11:03:20 +01003183 DISGUISE(write(pidfd, pidstr, strlen(pidstr)));
William Lallemand944e6192018-11-21 15:48:31 +01003184 }
3185 if (global.mode & MODE_MWORKER) {
3186 struct mworker_proc *child;
William Lallemandce83b4a2018-10-26 14:47:30 +02003187
William Lallemand220567e2018-11-21 18:04:53 +01003188 ha_notice("New worker #%d (%d) forked\n", relative_pid, ret);
William Lallemand944e6192018-11-21 15:48:31 +01003189 /* find the right mworker_proc */
3190 list_for_each_entry(child, &proc_list, list) {
3191 if (child->relative_pid == relative_pid &&
William Lallemand8f7069a2019-04-12 16:09:23 +02003192 child->reloads == 0 && child->options & PROC_O_TYPE_WORKER) {
William Lallemand944e6192018-11-21 15:48:31 +01003193 child->timestamp = now.tv_sec;
3194 child->pid = ret;
William Lallemand1dc69632019-06-12 19:11:33 +02003195 child->version = strdup(haproxy_version);
William Lallemand944e6192018-11-21 15:48:31 +01003196 break;
3197 }
William Lallemandce83b4a2018-10-26 14:47:30 +02003198 }
3199 }
William Lallemandbc193052018-09-11 10:06:26 +02003200
William Lallemand944e6192018-11-21 15:48:31 +01003201 relative_pid++; /* each child will get a different one */
3202 pid_bit <<= 1;
3203 }
3204 } else {
3205 /* wait mode */
3206 global.nbproc = 1;
3207 proc = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003209
3210#ifdef USE_CPU_AFFINITY
3211 if (proc < global.nbproc && /* child */
Willy Tarreauff9c9142019-02-07 10:39:36 +01003212 proc < MAX_PROCS && /* only the first 32/64 processes may be pinned */
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003213 ha_cpuset_count(&cpu_map.proc[proc])) { /* only do this if the process has a CPU map */
Olivier Houchard97148f62017-08-16 17:29:11 +02003214
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003215#ifdef __FreeBSD__
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003216 struct hap_cpuset *set = &cpu_map.proc[proc];
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003217 ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(set->cpuset), &set->cpuset);
David Carlier2d0493a2020-12-02 21:14:51 +00003218#elif defined(__linux__) || defined(__DragonFly__)
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003219 struct hap_cpuset *set = &cpu_map.proc[proc];
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003220 sched_setaffinity(0, sizeof(set->cpuset), &set->cpuset);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01003221#endif
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003222 }
Pieter Baauwcaa6a1b2015-09-17 21:26:40 +02003223#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02003224 /* close the pidfile both in children and father */
Willy Tarreau269ab312012-09-05 08:02:48 +02003225 if (pidfd >= 0) {
3226 //lseek(pidfd, 0, SEEK_SET); /* debug: emulate eglibc bug */
3227 close(pidfd);
3228 }
Willy Tarreaud137dd32010-08-25 12:49:05 +02003229
3230 /* We won't ever use this anymore */
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003231 ha_free(&global.pidfile);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003232
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003233 if (proc == global.nbproc) {
William Lallemand944e6192018-11-21 15:48:31 +01003234 if (global.mode & (MODE_MWORKER|MODE_MWORKER_WAIT)) {
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003235
3236 if ((!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) &&
3237 (global.mode & MODE_DAEMON)) {
3238 /* detach from the tty, this is required to properly daemonize. */
William Lallemande1340412017-12-28 16:09:36 +01003239 if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL))
3240 stdio_quiet(-1);
3241
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003242 global.mode &= ~MODE_VERBOSE;
3243 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
PiBa-NLbaf6ea42017-11-28 23:26:08 +01003244 }
3245
William Lallemandb3f2be32018-09-11 10:06:18 +02003246 mworker_loop();
William Lallemand1499b9b2017-06-07 15:04:47 +02003247 /* should never get there */
3248 exit(EXIT_FAILURE);
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003249 }
William Lallemandcf4e4962017-06-08 19:05:48 +02003250#if defined(USE_OPENSSL) && !defined(OPENSSL_NO_DH)
Grant Zhang872f9c22017-01-21 01:10:18 +00003251 ssl_free_dh();
3252#endif
William Lallemand1499b9b2017-06-07 15:04:47 +02003253 exit(0); /* parent must leave */
Willy Tarreauedaff0a2015-05-01 17:01:08 +02003254 }
3255
William Lallemandcb11fd22017-06-01 17:38:52 +02003256 /* child must never use the atexit function */
3257 atexit_flag = 0;
3258
William Lallemandbc193052018-09-11 10:06:26 +02003259 /* close useless master sockets */
3260 if (global.mode & MODE_MWORKER) {
3261 struct mworker_proc *child, *it;
3262 master = 0;
3263
William Lallemand309dc9a2018-10-26 14:47:45 +02003264 mworker_cli_proxy_stop();
3265
William Lallemandbc193052018-09-11 10:06:26 +02003266 /* free proc struct of other processes */
3267 list_for_each_entry_safe(child, it, &proc_list, list) {
William Lallemandce83b4a2018-10-26 14:47:30 +02003268 /* close the FD of the master side for all
3269 * workers, we don't need to close the worker
3270 * side of other workers since it's done with
3271 * the bind_proc */
Tim Duesterhus742e0f92018-11-25 20:03:39 +01003272 if (child->ipc_fd[0] >= 0)
3273 close(child->ipc_fd[0]);
William Lallemandce83b4a2018-10-26 14:47:30 +02003274 if (child->relative_pid == relative_pid &&
3275 child->reloads == 0) {
3276 /* keep this struct if this is our pid */
3277 proc_self = child;
William Lallemandbc193052018-09-11 10:06:26 +02003278 continue;
William Lallemandce83b4a2018-10-26 14:47:30 +02003279 }
Willy Tarreau2b718102021-04-21 07:32:39 +02003280 LIST_DELETE(&child->list);
Tim Duesterhus9b7a9762019-05-16 20:23:22 +02003281 mworker_free_child(child);
3282 child = NULL;
William Lallemandbc193052018-09-11 10:06:26 +02003283 }
3284 }
Willy Tarreau1605c7a2018-01-23 19:01:49 +01003285
William Lallemande1340412017-12-28 16:09:36 +01003286 if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE)) {
3287 devnullfd = open("/dev/null", O_RDWR, 0);
3288 if (devnullfd < 0) {
3289 ha_alert("Cannot open /dev/null\n");
3290 exit(EXIT_FAILURE);
3291 }
3292 }
3293
William Lallemand095ba4c2017-06-01 17:38:50 +02003294 /* Must chroot and setgid/setuid in the children */
3295 /* chroot if needed */
3296 if (global.chroot != NULL) {
3297 if (chroot(global.chroot) == -1 || chdir("/") == -1) {
Willy Tarreau46317372021-06-15 08:59:19 +02003298 ha_alert("[%s.main()] Cannot chroot(%s).\n", argv[0], global.chroot);
William Lallemand095ba4c2017-06-01 17:38:50 +02003299 if (nb_oldpids)
3300 tell_old_pids(SIGTTIN);
3301 protocol_unbind_all();
3302 exit(1);
3303 }
3304 }
3305
Willy Tarreau61cfdf42021-02-20 10:46:51 +01003306 ha_free(&global.chroot);
William Dauchyf9af9d72019-11-17 15:47:16 +01003307 set_identity(argv[0]);
William Lallemand095ba4c2017-06-01 17:38:50 +02003308
William Lallemand7f80eb22017-05-26 18:19:55 +02003309 /* pass through every cli socket, and check if it's bound to
3310 * the current process and if it exposes listeners sockets.
3311 * Caution: the GTUNE_SOCKET_TRANSFER is now set after the fork.
3312 * */
3313
Willy Tarreau4975d142021-03-13 11:00:33 +01003314 if (global.cli_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003315 struct bind_conf *bind_conf;
3316
Willy Tarreau4975d142021-03-13 11:00:33 +01003317 list_for_each_entry(bind_conf, &global.cli_fe->conf.bind, by_fe) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003318 if (bind_conf->level & ACCESS_FD_LISTENERS) {
Willy Tarreaue26993c2020-09-03 07:18:55 +02003319 if (!bind_conf->settings.bind_proc || bind_conf->settings.bind_proc & (1UL << proc)) {
William Lallemand7f80eb22017-05-26 18:19:55 +02003320 global.tune.options |= GTUNE_SOCKET_TRANSFER;
3321 break;
3322 }
3323 }
3324 }
3325 }
3326
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003327 /* we might have to unbind some proxies from some processes */
Olivier Houchardfbc74e82017-11-24 16:54:05 +01003328 px = proxies_list;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003329 while (px != NULL) {
Willy Tarreauc3914d42020-09-24 08:39:22 +02003330 if (px->bind_proc && !px->disabled) {
Willy Tarreau337c8352020-09-24 10:51:29 +02003331 if (!(px->bind_proc & (1UL << proc)))
3332 stop_proxy(px);
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003333 }
3334 px = px->next;
3335 }
3336
Emeric Brunc47ba592020-10-07 10:13:10 +02003337 /* we might have to unbind some log forward proxies from some processes */
3338 px = cfg_log_forward;
3339 while (px != NULL) {
Willy Tarreauc3914d42020-09-24 08:39:22 +02003340 if (px->bind_proc && !px->disabled) {
Willy Tarreau337c8352020-09-24 10:51:29 +02003341 if (!(px->bind_proc & (1UL << proc)))
3342 stop_proxy(px);
Emeric Brunc47ba592020-10-07 10:13:10 +02003343 }
3344 px = px->next;
3345 }
3346
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003347 /* we might have to unbind some peers sections from some processes */
Frédéric Lécailleed2b4a62017-07-13 09:07:09 +02003348 for (curpeers = cfg_peers; curpeers; curpeers = curpeers->next) {
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003349 if (!curpeers->peers_fe)
3350 continue;
3351
3352 if (curpeers->peers_fe->bind_proc & (1UL << proc))
3353 continue;
3354
3355 stop_proxy(curpeers->peers_fe);
3356 /* disable this peer section so that it kills itself */
Willy Tarreau47c8c022015-09-28 16:39:25 +02003357 signal_unregister_handler(curpeers->sighandler);
Olivier Houchard3f795f72019-04-17 22:51:06 +02003358 task_destroy(curpeers->sync_task);
Willy Tarreau47c8c022015-09-28 16:39:25 +02003359 curpeers->sync_task = NULL;
Olivier Houchard3f795f72019-04-17 22:51:06 +02003360 task_destroy(curpeers->peers_fe->task);
Willy Tarreau47c8c022015-09-28 16:39:25 +02003361 curpeers->peers_fe->task = NULL;
Willy Tarreauf83d3fe2015-05-01 19:13:41 +02003362 curpeers->peers_fe = NULL;
3363 }
3364
William Lallemand2e8fad92018-11-13 16:18:23 +01003365 /*
3366 * This is only done in daemon mode because we might want the
3367 * logs on stdout in mworker mode. If we're NOT in QUIET mode,
3368 * we should now close the 3 first FDs to ensure that we can
3369 * detach from the TTY. We MUST NOT do it in other cases since
3370 * it would have already be done, and 0-2 would have been
3371 * affected to listening sockets
Willy Tarreaubaaee002006-06-26 02:48:02 +02003372 */
William Lallemand2e8fad92018-11-13 16:18:23 +01003373 if ((global.mode & MODE_DAEMON) &&
3374 (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 /* detach from the tty */
William Lallemande1340412017-12-28 16:09:36 +01003376 stdio_quiet(devnullfd);
Willy Tarreau106cb762008-11-16 07:40:34 +01003377 global.mode &= ~MODE_VERBOSE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 global.mode |= MODE_QUIET; /* ensure that we won't say anything from now */
3379 }
3380 pid = getpid(); /* update child's pid */
William Lallemandbfd8eb52018-07-04 15:31:23 +02003381 if (!(global.mode & MODE_MWORKER)) /* in mworker mode we don't want a new pgid for the children */
3382 setsid();
Willy Tarreau2ff76222007-04-09 19:29:56 +02003383 fork_poller();
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 }
3385
William Dauchye039f262019-11-17 15:47:15 +01003386 /* try our best to re-enable core dumps depending on system capabilities.
3387 * What is addressed here :
3388 * - remove file size limits
3389 * - remove core size limits
3390 * - mark the process dumpable again if it lost it due to user/group
3391 */
3392 if (global.tune.options & GTUNE_SET_DUMPABLE) {
3393 limit.rlim_cur = limit.rlim_max = RLIM_INFINITY;
3394
3395#if defined(RLIMIT_FSIZE)
3396 if (setrlimit(RLIMIT_FSIZE, &limit) == -1) {
3397 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3398 ha_alert("[%s.main()] Failed to set the raise the maximum "
3399 "file size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003400 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003401 }
3402 else
3403 ha_warning("[%s.main()] Failed to set the raise the maximum "
William Dauchya5194602020-03-28 19:29:58 +01003404 "file size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003405 }
3406#endif
3407
3408#if defined(RLIMIT_CORE)
3409 if (setrlimit(RLIMIT_CORE, &limit) == -1) {
3410 if (global.tune.options & GTUNE_STRICT_LIMITS) {
3411 ha_alert("[%s.main()] Failed to set the raise the core "
3412 "dump size.\n", argv[0]);
Jerome Magnin50f757c2021-01-12 20:19:38 +01003413 exit(1);
William Dauchye039f262019-11-17 15:47:15 +01003414 }
3415 else
3416 ha_warning("[%s.main()] Failed to set the raise the core "
William Dauchya5194602020-03-28 19:29:58 +01003417 "dump size.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003418 }
3419#endif
3420
3421#if defined(USE_PRCTL)
3422 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1)
3423 ha_warning("[%s.main()] Failed to set the dumpable flag, "
3424 "no core will be dumped.\n", argv[0]);
devnexen@gmail.com078062b2021-08-21 09:13:10 +01003425#elif defined(USE_PROCCTL)
3426 int traceable = PROC_TRACE_CTL_ENABLE;
3427 if (procctl(P_PID, getpid(), PROC_TRACE_CTL, &traceable) == -1)
3428 ha_warning("[%s.main()] Failed to set the traceable flag, "
3429 "no core will be dumped.\n", argv[0]);
William Dauchye039f262019-11-17 15:47:15 +01003430#endif
3431 }
3432
Christopher Faulete3a5e352017-10-24 13:53:54 +02003433 global.mode &= ~MODE_STARTING;
Willy Tarreau4f60f162007-04-08 16:39:58 +02003434 /*
3435 * That's it : the central polling loop. Run until we stop.
3436 */
Christopher Faulet1d17c102017-08-29 15:38:48 +02003437#ifdef USE_THREAD
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003438 {
William Lallemand1aab50b2018-06-07 09:46:01 +02003439 sigset_t blocked_sig, old_sig;
Willy Tarreauc40efc12019-05-03 09:22:44 +02003440 int i;
3441
William Lallemand1aab50b2018-06-07 09:46:01 +02003442 /* ensure the signals will be blocked in every thread */
3443 sigfillset(&blocked_sig);
3444 sigdelset(&blocked_sig, SIGPROF);
3445 sigdelset(&blocked_sig, SIGBUS);
3446 sigdelset(&blocked_sig, SIGFPE);
3447 sigdelset(&blocked_sig, SIGILL);
3448 sigdelset(&blocked_sig, SIGSEGV);
3449 pthread_sigmask(SIG_SETMASK, &blocked_sig, &old_sig);
3450
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003451 /* Create nbthread-1 thread. The first thread is the current process */
David Carliera92c5ce2019-09-13 05:03:12 +01003452 ha_thread_info[0].pthread = pthread_self();
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003453 for (i = 1; i < global.nbthread; i++)
David Carliera92c5ce2019-09-13 05:03:12 +01003454 pthread_create(&ha_thread_info[i].pthread, NULL, &run_thread_poll_loop, (void *)(long)i);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003455
Christopher Faulet62519022017-10-16 15:49:32 +02003456#ifdef USE_CPU_AFFINITY
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003457 /* Now the CPU affinity for all threads */
Amaury Denoyelleaf02c572021-04-15 16:29:58 +02003458
3459 /* If on multiprocess, use proc_t1 except for the first process.
3460 */
3461 if ((relative_pid - 1) > 0)
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003462 cpu_map.thread[0] = cpu_map.proc_t1[relative_pid-1];
Willy Tarreau7764a572019-07-16 15:10:34 +02003463
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003464 for (i = 0; i < global.nbthread; i++) {
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003465 if (ha_cpuset_count(&cpu_map.proc[relative_pid-1]))
3466 ha_cpuset_and(&cpu_map.thread[i], &cpu_map.proc[relative_pid-1]);
Christopher Faulet62519022017-10-16 15:49:32 +02003467
Willy Tarreau421f02e2018-01-20 18:19:22 +01003468 if (i < MAX_THREADS && /* only the first 32/64 threads may be pinned */
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003469 ha_cpuset_count(&cpu_map.thread[i])) {/* only do this if the thread has a THREAD map */
David Carlier5e4c8e22019-09-13 05:12:58 +01003470#if defined(__APPLE__)
3471 int j;
Amaury Denoyelle8f685c12021-04-27 16:45:29 +02003472 unsigned long set = cpu_map.thread[i].cpuset;
David Carlier5e4c8e22019-09-13 05:12:58 +01003473
Amaury Denoyelle8f685c12021-04-27 16:45:29 +02003474 while ((j = ffsl(set)) > 0) {
David Carlier5e4c8e22019-09-13 05:12:58 +01003475 thread_affinity_policy_data_t cpu_set = { j - 1 };
3476 thread_port_t mthread = pthread_mach_thread_np(ha_thread_info[i].pthread);
3477 thread_policy_set(mthread, THREAD_AFFINITY_POLICY, (thread_policy_t)&cpu_set, 1);
Amaury Denoyelle8f685c12021-04-27 16:45:29 +02003478 set &= ~(1UL << (j - 1));
David Carlier5e4c8e22019-09-13 05:12:58 +01003479 }
3480#else
Amaury Denoyellefc6ac532021-04-27 10:46:36 +02003481 struct hap_cpuset *set = &cpu_map.thread[i];
David Carliera92c5ce2019-09-13 05:03:12 +01003482 pthread_setaffinity_np(ha_thread_info[i].pthread,
Amaury Denoyelle982fb532021-04-21 18:39:58 +02003483 sizeof(set->cpuset), &set->cpuset);
David Carlier5e4c8e22019-09-13 05:12:58 +01003484#endif
Olivier Houchard829aa242017-12-01 18:19:43 +01003485 }
Christopher Faulet1d17c102017-08-29 15:38:48 +02003486 }
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003487#endif /* !USE_CPU_AFFINITY */
3488
William Lallemand1aab50b2018-06-07 09:46:01 +02003489 /* when multithreading we need to let only the thread 0 handle the signals */
William Lallemandd3801c12018-09-11 10:06:23 +02003490 haproxy_unblock_signals();
William Lallemand1aab50b2018-06-07 09:46:01 +02003491
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003492 /* Finally, start the poll loop for the first thread */
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02003493 run_thread_poll_loop(0);
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003494
3495 /* Wait the end of other threads */
3496 for (i = 1; i < global.nbthread; i++)
David Carliera92c5ce2019-09-13 05:03:12 +01003497 pthread_join(ha_thread_info[i].pthread, NULL);
Christopher Faulet1d17c102017-08-29 15:38:48 +02003498
Christopher Fauletb79a94c2017-05-30 15:34:30 +02003499#if defined(DEBUG_THREAD) || defined(DEBUG_FULL)
3500 show_lock_stats();
3501#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003502 }
Christopher Fauletcd7879a2017-10-27 13:53:47 +02003503#else /* ! USE_THREAD */
William Lallemandd3801c12018-09-11 10:06:23 +02003504 haproxy_unblock_signals();
Willy Tarreaub4f7cc32019-05-03 09:27:30 +02003505 run_thread_poll_loop(0);
Christopher Faulet62519022017-10-16 15:49:32 +02003506#endif
Christopher Faulet1d17c102017-08-29 15:38:48 +02003507
Tim Duesterhus0a3b43d2020-06-14 00:37:42 +02003508 deinit_and_exit(0);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003509}
3510
Willy Tarreaubaaee002006-06-26 02:48:02 +02003511/*
3512 * Local variables:
3513 * c-indent-level: 8
3514 * c-basic-offset: 8
3515 * End:
3516 */